diff options
author | Jordan Rose <jordan_rose@apple.com> | 2013-06-03 23:00:00 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2013-06-03 23:00:00 +0000 |
commit | 8c54b44fb3cb5c0e252ddd3ba7136a916f6ed3bf (patch) | |
tree | 2252ea542b26a35dac8a9ca38d204cc860823e2f /clang/lib/StaticAnalyzer/Core/BugReporter.cpp | |
parent | b60b844265b7ed5739c8062f409db59ba1233b85 (diff) | |
download | bcm5719-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.cpp | 50 |
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); |