From 56d8fd0b8a65a7ccae3669cd650ca443cf24b73e Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Tue, 28 Feb 2012 23:27:39 +0000 Subject: [PATCH] [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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151664 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Core/BugReporter/PathDiagnostic.h | 4 ++ lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp | 35 +++----------- lib/StaticAnalyzer/Core/PathDiagnostic.cpp | 47 +++++++++++++++---- 3 files changed, 49 insertions(+), 37 deletions(-) diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index 42d8482eba..965ac3085e 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -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; diff --git a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp index 8004ef45a6..3740ba1005 100644 --- a/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ b/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -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); - - 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? + // 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(); + 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(SMgr), PP.getLangOptions()); diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp index a866b34158..2adc0f2c38 100644 --- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -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 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()); } -- 2.40.0