summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorDevin Coughlin <dcoughlin@apple.com>2016-12-19 22:23:22 +0000
committerDevin Coughlin <dcoughlin@apple.com>2016-12-19 22:23:22 +0000
commit5b1ee2fad97ceec55c6b22154b425954649a95b8 (patch)
tree865843eacb97918d695c4289b6dc9f0307986868 /clang/lib
parentd9430944f4bb423a15785a0cea2bc6a76c50ecdb (diff)
downloadbcm5719-llvm-5b1ee2fad97ceec55c6b22154b425954649a95b8.tar.gz
bcm5719-llvm-5b1ee2fad97ceec55c6b22154b425954649a95b8.zip
[analyzer] Add sink after construction of temporary with no-return destructor.
The analyzer's CFG currently doesn't have nodes for calls to temporary destructors. This causes the analyzer to explore infeasible paths in which a no-return destructor would have stopped exploration and so results in false positives when no-return destructors are used to implement assertions. To mitigate these false positives, this patch stops generates a sink after evaluating a constructor on a temporary object that has a no-return destructor. This results in a loss of coverage because the time at which the destructor is called may be after the time of construction (especially for lifetime-extended temporaries). This addresses PR15599. rdar://problem/29131566 llvm-svn: 290140
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp24
1 files changed, 24 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 011f776d0b0..7e9b2033ca3 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -346,6 +346,30 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
defaultEvalCall(Bldr, *I, *Call);
}
+ // If the CFG was contructed without elements for temporary destructors
+ // and the just-called constructor created a temporary object then
+ // stop exploration if the temporary object has a noreturn constructor.
+ // This can lose coverage because the destructor, if it were present
+ // in the CFG, would be called at the end of the full expression or
+ // later (for life-time extended temporaries) -- but avoids infeasible
+ // paths when no-return temporary destructors are used for assertions.
+ const AnalysisDeclContext *ADC = LCtx->getAnalysisDeclContext();
+ if (!ADC->getCFGBuildOptions().AddTemporaryDtors) {
+ const MemRegion *Target = Call->getCXXThisVal().getAsRegion();
+ if (Target && isa<CXXTempObjectRegion>(Target) &&
+ Call->getDecl()->getParent()->isAnyDestructorNoReturn()) {
+
+ for (ExplodedNode *N : DstEvaluated) {
+ Bldr.generateSink(CE, N, N->getState());
+ }
+
+ // There is no need to run the PostCall and PostStmtchecker
+ // callbacks because we just generated sinks on all nodes in th
+ // frontier.
+ return;
+ }
+ }
+
ExplodedNodeSet DstPostCall;
getCheckerManager().runCheckersForPostCall(DstPostCall, DstEvaluated,
*Call, *this);
OpenPOWER on IntegriCloud