summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2013-06-03 23:00:00 +0000
committerJordan Rose <jordan_rose@apple.com>2013-06-03 23:00:00 +0000
commit8c54b44fb3cb5c0e252ddd3ba7136a916f6ed3bf (patch)
tree2252ea542b26a35dac8a9ca38d204cc860823e2f /clang/lib/StaticAnalyzer/Core/BugReporter.cpp
parentb60b844265b7ed5739c8062f409db59ba1233b85 (diff)
downloadbcm5719-llvm-8c54b44fb3cb5c0e252ddd3ba7136a916f6ed3bf.tar.gz
bcm5719-llvm-8c54b44fb3cb5c0e252ddd3ba7136a916f6ed3bf.zip
[analyzer; new edges] Eliminate "cycle edges" for a single subexpression.
Generating context arrows can result in quite a few arrows surrounding a relatively simple expression, often containing only a single path note. | 1 +--2---+ v/ v auto m = new m // 3 (the path note) |\ | 5 +--4---+ v Note also that 5 and 1 are two ends of the "same" arrow, i.e. they go from event to event. 3 is not an arrow but the path note itself. Now, if we see a pair of edges like 2 and 4---where 4 is the reverse of 2 and there is optionally a single path note between them---we will eliminate /both/ edges. Anything more complicated will be left as is (more edges involved, an inlined call, etc). The next commit will refine this to preserve the arrows in a larger expression, so that we don't lose all context. llvm-svn: 183162
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/BugReporter.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Core/BugReporter.cpp50
1 files changed, 50 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
index a0a4791ffd6..fc1016a1c6a 100644
--- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
+++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
@@ -2092,6 +2092,54 @@ static void simplifySimpleBranches(PathPieces &pieces) {
}
}
+static void removeContextCycles(PathPieces &Path, ParentMap &PM) {
+ for (PathPieces::iterator I = Path.begin(), E = Path.end(); I != E; ) {
+ // Pattern match the current piece and its successor.
+ PathDiagnosticControlFlowPiece *PieceI =
+ dyn_cast<PathDiagnosticControlFlowPiece>(*I);
+
+ if (!PieceI) {
+ ++I;
+ continue;
+ }
+
+ const Stmt *s1Start = getLocStmt(PieceI->getStartLocation());
+ const Stmt *s1End = getLocStmt(PieceI->getEndLocation());
+
+ PathPieces::iterator NextI = I; ++NextI;
+ if (NextI == E)
+ break;
+
+ PathDiagnosticControlFlowPiece *PieceNextI =
+ dyn_cast<PathDiagnosticControlFlowPiece>(*NextI);
+
+ if (!PieceNextI) {
+ if (isa<PathDiagnosticEventPiece>(*NextI)) {
+ ++NextI;
+ if (NextI == E)
+ break;
+ PieceNextI = dyn_cast<PathDiagnosticControlFlowPiece>(*NextI);
+ }
+
+ if (!PieceNextI) {
+ ++I;
+ continue;
+ }
+ }
+
+ const Stmt *s2Start = getLocStmt(PieceNextI->getStartLocation());
+ const Stmt *s2End = getLocStmt(PieceNextI->getEndLocation());
+
+ if (s1Start && s2Start && s1Start == s2End && s2Start == s1End) {
+ Path.erase(I);
+ I = Path.erase(NextI);
+ continue;
+ }
+
+ ++I;
+ }
+}
+
/// \brief Return true if X is contained by Y.
static bool lexicalContains(ParentMap &PM,
const Stmt *X,
@@ -2342,6 +2390,8 @@ static bool optimizeEdges(PathPieces &path, SourceManager &SM,
// Adjust edges into subexpressions to make them more uniform
// and aesthetically pleasing.
addContextEdges(path, SM, PM, LC);
+ // Remove "cyclical" edges that include one or more context edges.
+ removeContextCycles(path, PM);
// Hoist edges originating from branch conditions to branches
// for simple branches.
simplifySimpleBranches(path);
OpenPOWER on IntegriCloud