r290140 - [analyzer] Add sink after construction of temporary with no-return destructor.
Devin Coughlin via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 19 14:23:22 PST 2016
Author: dcoughlin
Date: Mon Dec 19 16:23:22 2016
New Revision: 290140
URL: http://llvm.org/viewvc/llvm-project?rev=290140&view=rev
Log:
[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
Modified:
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
cfe/trunk/test/Analysis/temporaries.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp?rev=290140&r1=290139&r2=290140&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp Mon Dec 19 16:23:22 2016
@@ -346,6 +346,30 @@ void ExprEngine::VisitCXXConstructExpr(c
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);
Modified: cfe/trunk/test/Analysis/temporaries.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/temporaries.cpp?rev=290140&r1=290139&r2=290140&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/temporaries.cpp (original)
+++ cfe/trunk/test/Analysis/temporaries.cpp Mon Dec 19 16:23:22 2016
@@ -413,6 +413,32 @@ namespace destructors {
value ? DefaultParam(42) : DefaultParam(42);
}
}
+#else // !TEMPORARY_DTORS
+
+// Test for fallback logic that conservatively stops exploration after
+// executing a temporary constructor for a class with a no-return destructor
+// when temporary destructors are not enabled in the CFG.
+
+ struct CtorWithNoReturnDtor {
+ CtorWithNoReturnDtor() = default;
+
+ ~CtorWithNoReturnDtor() __attribute__((noreturn));
+ };
+
+ void testDefaultContructorWithNoReturnDtor() {
+ CtorWithNoReturnDtor();
+ clang_analyzer_warnIfReached(); // no-warning
+ }
+
+ void testLifeExtensionWithNoReturnDtor() {
+ const CtorWithNoReturnDtor &c = CtorWithNoReturnDtor();
+
+ // This represents an (expected) loss of coverage, since the destructor
+ // of the lifetime-exended temporary is executed at at the end of
+ // scope.
+ clang_analyzer_warnIfReached(); // no-warning
+ }
+
#endif // TEMPORARY_DTORS
}
More information about the cfe-commits
mailing list