diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-09-22 01:24:53 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-09-22 01:24:53 +0000 |
commit | 5a751b993f4b4222b4038b1fe51a72c0e3178306 (patch) | |
tree | b329d2b55f6081795f82703a26224c9ab5cc29ff /clang/lib/StaticAnalyzer/Core/BugReporter.cpp | |
parent | 6f3d2f0acdf14b17aa0bbc79dcbe74cb687d1d1b (diff) | |
download | bcm5719-llvm-5a751b993f4b4222b4038b1fe51a72c0e3178306.tar.gz bcm5719-llvm-5a751b993f4b4222b4038b1fe51a72c0e3178306.zip |
[analyzer] Allow a BugReport to be marked "invalid" during path generation.
This is intended to allow visitors to make decisions about whether a
BugReport is likely a false positive. Currently there are no visitors
making use of this feature, so there are no tests.
When a BugReport is marked invalid, the invalidator must provide a key
that identifies the invaliation (intended to be the visitor type and a
context pointer of some kind). This allows us to reverse the decision
later on. Being able to reverse a decision about invalidation gives us more
flexibility, and allows us to formulate conditions like "this report is
invalid UNLESS the original argument is 'foo'". We can use this to
fine-tune our false-positive suppression (coming soon).
llvm-svn: 164446
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/BugReporter.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/BugReporter.cpp | 46 |
1 files changed, 38 insertions, 8 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index e95f31c0d6b..e45d43e3131 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -432,7 +432,7 @@ static void updateStackPiecesWithMessage(PathDiagnosticPiece *P, static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM); -static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, +static bool GenerateMinimalPathDiagnostic(PathDiagnostic& PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, ArrayRef<BugReporterVisitor *> visitors) { @@ -756,9 +756,13 @@ static void GenerateMinimalPathDiagnostic(PathDiagnostic& PD, } } + if (!PDB.getBugReport()->isValid()) + return false; + // After constructing the full PathDiagnostic, do a pass over it to compact // PathDiagnosticPieces that occur within a macro. CompactPathDiagnostic(PD.getMutablePieces(), PDB.getSourceManager()); + return true; } //===----------------------------------------------------------------------===// @@ -1164,7 +1168,7 @@ static void reversePropagateInterestingSymbols(BugReport &R, } } -static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, +static bool GenerateExtensivePathDiagnostic(PathDiagnostic& PD, PathDiagnosticBuilder &PDB, const ExplodedNode *N, ArrayRef<BugReporterVisitor *> visitors) { @@ -1337,6 +1341,8 @@ static void GenerateExtensivePathDiagnostic(PathDiagnostic& PD, } } } + + return PDB.getBugReport()->isValid(); } //===----------------------------------------------------------------------===// @@ -1866,17 +1872,27 @@ static void CompactPathDiagnostic(PathPieces &path, const SourceManager& SM) { path.push_back(*I); } -void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, +bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, PathDiagnosticConsumer &PC, ArrayRef<BugReport *> &bugReports) { - assert(!bugReports.empty()); + + bool HasValid = false; SmallVector<const ExplodedNode *, 10> errorNodes; for (ArrayRef<BugReport*>::iterator I = bugReports.begin(), E = bugReports.end(); I != E; ++I) { + if ((*I)->isValid()) { + HasValid = true; errorNodes.push_back((*I)->getErrorNode()); + } else { + errorNodes.push_back(0); + } } + // If all the reports have been marked invalid, we're done. + if (!HasValid) + return false; + // Construct a new graph that contains only a single path from the error // node to a root. const std::pair<std::pair<ExplodedGraph*, NodeBackMap*>, @@ -1887,6 +1903,7 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, assert(GPair.second.second < bugReports.size()); BugReport *R = bugReports[GPair.second.second]; assert(R && "No original report found for sliced graph."); + assert(R->isValid() && "Report selected from trimmed graph marked invalid."); OwningPtr<ExplodedGraph> ReportGraph(GPair.first.first); OwningPtr<NodeBackMap> BackMap(GPair.first.second); @@ -1932,14 +1949,24 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, if (LastPiece) PD.setEndOfPath(LastPiece); else - return; + return false; switch (PDB.getGenerationScheme()) { case PathDiagnosticConsumer::Extensive: - GenerateExtensivePathDiagnostic(PD, PDB, N, visitors); + if (!GenerateExtensivePathDiagnostic(PD, PDB, N, visitors)) { + assert(!R->isValid() && "Failed on valid report"); + // Try again. We'll filter out the bad report when we trim the graph. + // FIXME: It would be more efficient to use the same intermediate + // trimmed graph, and just repeat the shortest-path search. + return generatePathDiagnostic(PD, PC, bugReports); + } break; case PathDiagnosticConsumer::Minimal: - GenerateMinimalPathDiagnostic(PD, PDB, N, visitors); + if (!GenerateMinimalPathDiagnostic(PD, PDB, N, visitors)) { + assert(!R->isValid() && "Failed on valid report"); + // Try again. We'll filter out the bad report when we trim the graph. + return generatePathDiagnostic(PD, PC, bugReports); + } break; case PathDiagnosticConsumer::None: llvm_unreachable("PathDiagnosticConsumer::None should never appear here"); @@ -1958,6 +1985,8 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, assert(hasSomethingInteresting); (void) hasSomethingInteresting; } + + return true; } void BugReporter::Register(BugType *BT) { @@ -2129,7 +2158,8 @@ void BugReporter::FlushReport(BugReport *exampleReport, // specified by the PathDiagnosticConsumer. if (PD.getGenerationScheme() != PathDiagnosticConsumer::None) { if (!bugReports.empty()) - GeneratePathDiagnostic(*D.get(), PD, bugReports); + if (!generatePathDiagnostic(*D.get(), PD, bugReports)) + return; } // If the path is empty, generate a single step path with the location |