[analyzer diagnostics] Refactor filtration for PathDiagnosticConsumers that don't support cross-file diagnostics

into a common place.  Currently enable this filtration for Plist diagnostics as well.

llvm-svn: 151664
This commit is contained in:
Ted Kremenek 2012-02-28 23:27:39 +00:00
parent 2429c6ffe7
commit 0f70a6f51e
3 changed files with 49 additions and 37 deletions

View File

@ -68,6 +68,10 @@ public:
virtual bool supportsLogicalOpControlFlow() const { return false; }
virtual bool supportsAllBlockEdges() const { return false; }
virtual bool useVerboseDescription() const { return true; }
/// Return true if the PathDiagnosticConsumer supports individual
/// PathDiagnostics that span multiple files.
virtual bool supportsCrossFileDiagnostics() const { return false; }
protected:
bool flushed;

View File

@ -145,35 +145,14 @@ void HTMLDiagnostics::ReportDiag(const PathDiagnostic& D,
// First flatten out the entire path to make it easier to use.
PathPieces path;
flattenPath(path, D.path);
// The path as already been prechecked that all parts of the path are
// from the same file and that it is non-empty.
const SourceManager &SMgr = (*path.begin())->getLocation().getManager();
FileID FID;
// Verify that the entire path is from the same FileID.
for (PathPieces::const_iterator I = path.begin(), E = path.end();
I != E; ++I) {
FullSourceLoc L = (*I)->getLocation().asLocation().getExpansionLoc();
if (FID.isInvalid()) {
FID = SMgr.getFileID(L);
} else if (SMgr.getFileID(L) != FID)
return; // FIXME: Emit a warning?
// Check the source ranges.
for (PathDiagnosticPiece::range_iterator RI = (*I)->ranges_begin(),
RE = (*I)->ranges_end();
RI != RE; ++RI) {
SourceLocation L = SMgr.getExpansionLoc(RI->getBegin());
if (!L.isFileID() || SMgr.getFileID(L) != FID)
return; // FIXME: Emit a warning?
L = SMgr.getExpansionLoc(RI->getEnd());
if (!L.isFileID() || SMgr.getFileID(L) != FID)
return; // FIXME: Emit a warning?
}
}
if (FID.isInvalid())
return; // FIXME: Emit a warning?
assert(!path.empty());
FileID FID =
(*path.begin())->getLocation().asLocation().getExpansionLoc().getFileID();
assert(!FID.isInvalid());
// Create a new rewriter to generate HTML.
Rewriter R(const_cast<SourceManager&>(SMgr), PP.getLangOptions());

View File

@ -13,6 +13,7 @@
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
#include "clang/Basic/SourceManager.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
@ -76,19 +77,49 @@ PathDiagnosticConsumer::~PathDiagnosticConsumer() {
}
void PathDiagnosticConsumer::HandlePathDiagnostic(PathDiagnostic *D) {
if (!D)
return;
llvm::OwningPtr<PathDiagnostic> OwningD(D);
if (D->path.empty()) {
delete D;
if (!D || D->path.empty())
return;
}
// We need to flatten the locations (convert Stmt* to locations) because
// the referenced statements may be freed by the time the diagnostics
// are emitted.
D->flattenLocations();
// If the PathDiagnosticConsumer does not support diagnostics that
// cross file boundaries, prune out such diagnostics now.
if (!supportsCrossFileDiagnostics()) {
// Verify that the entire path is from the same FileID.
FileID FID;
const SourceManager &SMgr = (*D->path.begin())->getLocation().getManager();
for (PathPieces::const_iterator I = D->path.begin(), E = D->path.end();
I != E; ++I) {
FullSourceLoc L = (*I)->getLocation().asLocation().getExpansionLoc();
if (FID.isInvalid()) {
FID = SMgr.getFileID(L);
} else if (SMgr.getFileID(L) != FID)
return; // FIXME: Emit a warning?
// Check the source ranges.
for (PathDiagnosticPiece::range_iterator RI = (*I)->ranges_begin(),
RE = (*I)->ranges_end();
RI != RE; ++RI) {
SourceLocation L = SMgr.getExpansionLoc(RI->getBegin());
if (!L.isFileID() || SMgr.getFileID(L) != FID)
return; // FIXME: Emit a warning?
L = SMgr.getExpansionLoc(RI->getEnd());
if (!L.isFileID() || SMgr.getFileID(L) != FID)
return; // FIXME: Emit a warning?
}
}
if (FID.isInvalid())
return; // FIXME: Emit a warning?
}
// Profile the node to see if we already have something matching it
llvm::FoldingSetNodeID profile;
D->Profile(profile);
@ -110,16 +141,14 @@ void PathDiagnosticConsumer::HandlePathDiagnostic(PathDiagnostic *D) {
shouldKeepOriginal = false;
}
if (shouldKeepOriginal) {
delete D;
if (shouldKeepOriginal)
return;
}
}
Diags.RemoveNode(orig);
delete orig;
}
Diags.InsertNode(D);
Diags.InsertNode(OwningD.take());
}