summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Core/BugReporter.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2013-05-21 21:38:05 +0000
committerTed Kremenek <kremenek@apple.com>2013-05-21 21:38:05 +0000
commit9f0629f669cb73ea2a12e347d3e2f15bc37ee0ef (patch)
treedef72742f988babbf3cc41d151c253f451bcbf77 /clang/lib/StaticAnalyzer/Core/BugReporter.cpp
parent6d5bbec32e7e175b6623f1109b2ca6fad4335d21 (diff)
downloadbcm5719-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.cpp50
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;
OpenPOWER on IntegriCloud