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 } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits