summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2012-02-28 23:06:21 +0000
committerTed Kremenek <kremenek@apple.com>2012-02-28 23:06:21 +0000
commitc89f4b05721f53cfbaf32fc0c4919a4616e68440 (patch)
tree5c1742cecf2a398a94d5bdce4fc8b037bfac9585 /lib
parent15f87771cae0c31da45c05b34841d0a2ca70bc87 (diff)
downloadclang-c89f4b05721f53cfbaf32fc0c4919a4616e68440.tar.gz
clang-c89f4b05721f53cfbaf32fc0c4919a4616e68440.tar.bz2
clang-c89f4b05721f53cfbaf32fc0c4919a4616e68440.tar.xz
[analyzer diagnostics] start prototyping stripping PathDiagnostics of unnecessary cruft caused by path inlining.
This introduces a concept of a "prunable" PathDiagnosticEvent. Currently this is a flag, but we may evolve the concept to make this more dynamically inferred. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151663 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/StaticAnalyzer/Core/BugReporter.cpp50
-rw-r--r--lib/StaticAnalyzer/Core/BugReporterVisitors.cpp11
2 files changed, 61 insertions, 0 deletions
diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp
index de3c8ed81a..8d9b614841 100644
--- a/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -111,6 +111,51 @@ GetCurrentOrNextStmt(const ExplodedNode *N) {
}
//===----------------------------------------------------------------------===//
+// Diagnostic cleanup.
+//===----------------------------------------------------------------------===//
+
+/// Recursively scan through a path and prune out calls and macros pieces
+/// that aren't needed. Return true if afterwards the path contains
+/// "interesting stuff" which means it should be pruned from the parent path.
+static bool RemoveUneededCalls(PathPieces &pieces) {
+ bool containsSomethingInteresting = false;
+ const unsigned N = pieces.size();
+
+ for (unsigned i = 0 ; i < N ; ++i) {
+ // Remove the front piece from the path. If it is still something we
+ // want to keep once we are done, we will push it back on the end.
+ IntrusiveRefCntPtr<PathDiagnosticPiece> piece(pieces.front());
+ pieces.pop_front();
+
+ if (PathDiagnosticCallPiece *call =
+ dyn_cast<PathDiagnosticCallPiece>(piece)) {
+ // Recursively clean out the subclass. Keep this call around if
+ // it contains any informative diagnostics.
+ if (!RemoveUneededCalls(call->path))
+ continue;
+ containsSomethingInteresting = true;
+ }
+ else if (PathDiagnosticMacroPiece *macro =
+ dyn_cast<PathDiagnosticMacroPiece>(piece)) {
+ if (!RemoveUneededCalls(macro->subPieces))
+ continue;
+ containsSomethingInteresting = true;
+ }
+ else if (PathDiagnosticEventPiece *event =
+ dyn_cast<PathDiagnosticEventPiece>(piece)) {
+ // We never throw away an event, but we do throw it away wholesale
+ // as part of a path if we throw the entire path away.
+ if (!event->isPrunable())
+ containsSomethingInteresting = true;
+ }
+
+ pieces.push_back(piece);
+ }
+
+ return containsSomethingInteresting;
+}
+
+//===----------------------------------------------------------------------===//
// PathDiagnosticBuilder and its associated routines and helper objects.
//===----------------------------------------------------------------------===//
@@ -1749,6 +1794,11 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
GenerateMinimalPathDiagnostic(PD, PDB, N);
break;
}
+
+ // Finally, prune the diagnostic path of uninteresting stuff.
+ bool hasSomethingInteresting = RemoveUneededCalls(PD.getMutablePieces());
+ assert(hasSomethingInteresting);
+ (void) hasSomethingInteresting;
}
void BugReporter::Register(BugType *BT) {
diff --git a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
index 2980190945..1d29d5ff0a 100644
--- a/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ b/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -436,6 +436,17 @@ PathDiagnosticPiece *ConditionBRVisitor::VisitNode(const ExplodedNode *N,
const ExplodedNode *Prev,
BugReporterContext &BRC,
BugReport &BR) {
+ PathDiagnosticPiece *piece = VisitNodeImpl(N, Prev, BRC, BR);
+ if (PathDiagnosticEventPiece *ev =
+ dyn_cast_or_null<PathDiagnosticEventPiece>(piece))
+ ev->setPrunable(true);
+ return piece;
+}
+
+PathDiagnosticPiece *ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N,
+ const ExplodedNode *Prev,
+ BugReporterContext &BRC,
+ BugReport &BR) {
const ProgramPoint &progPoint = N->getLocation();