diff options
author | Ted Kremenek <kremenek@apple.com> | 2013-05-21 21:38:05 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2013-05-21 21:38:05 +0000 |
commit | 9f0629f669cb73ea2a12e347d3e2f15bc37ee0ef (patch) | |
tree | def72742f988babbf3cc41d151c253f451bcbf77 /clang/lib/StaticAnalyzer/Core/BugReporter.cpp | |
parent | 6d5bbec32e7e175b6623f1109b2ca6fad4335d21 (diff) | |
download | bcm5719-llvm-9f0629f669cb73ea2a12e347d3e2f15bc37ee0ef.tar.gz bcm5719-llvm-9f0629f669cb73ea2a12e347d3e2f15bc37ee0ef.zip |
[analyzer;alternate edges] prune out extra edges to a subexpression where we dive-in and out of a subexpression.
Fixes <rdar://problem/13941891>.
llvm-svn: 182426
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/BugReporter.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/BugReporter.cpp | 50 |
1 files changed, 46 insertions, 4 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index 7cc75b67561..7bc3b8f20b3 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -1950,6 +1950,18 @@ void PathPieces::dump() const { } } +/// \brief Return true if X is contained by Y. +static bool lexicalContains(ParentMap &PM, + const Stmt *X, + const Stmt *Y) { + while (X) { + if (X == Y) + return true; + X = PM.getParent(X); + } + return false; +} + static bool optimizeEdges(PathPieces &path, SourceManager &SM, OptimizedCallsSet &OCS, LocationContextMap &LCM) { @@ -2058,10 +2070,40 @@ static bool optimizeEdges(PathPieces &path, SourceManager &SM, // to prevent this optimization. // if (s1End && s1End == s2Start && level2) { - if (isIncrementOrInitInForLoop(s1End, level2) || - (isa<Expr>(s1End) && PM.isConsumedExpr(cast<Expr>(s1End)) && - !isConditionForTerminator(level2, s1End))) - { + bool removeEdge = false; + // Remove edges into the increment or initialization of a + // loop that have no interleaving event. This means that + // they aren't interesting. + if (isIncrementOrInitInForLoop(s1End, level2)) + removeEdge = true; + // Next only consider edges that are not anchored on + // the condition of a terminator. This are intermediate edges + // that we might want to trim. + else if (!isConditionForTerminator(level2, s1End)) { + // Trim edges on expressions that are consumed by + // the parent expression. + if (isa<Expr>(s1End) && PM.isConsumedExpr(cast<Expr>(s1End))) { + removeEdge = true; + } + // Trim edges where a lexical containment doesn't exist. + // For example: + // + // X -> Y -> Z + // + // If 'Z' lexically contains Y (it is an ancestor) and + // 'X' does not lexically contain Y (it is a descendant OR + // it has no lexical relationship at all) then trim. + // + // This can eliminate edges where we dive into a subexpression + // and then pop back out, etc. + else if (s1Start && s2End && + lexicalContains(PM, s2Start, s2End) && + !lexicalContains(PM, s1End, s1Start)) { + removeEdge = true; + } + } + + if (removeEdge) { PieceI->setEndLocation(PieceNextI->getEndLocation()); path.erase(NextI); hasChanges = true; |