From d527cf89e66af87e2fdf31fe51236b1375783f10 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Mon, 2 Sep 2013 09:09:15 +0000 Subject: [analyzer] Add very limited support for temporary destructors This is an improved version of r186498. It enables ExprEngine to reason about temporary object destructors. However, these destructor calls are never inlined, since this feature is still broken. Still, this is sufficient to properly handle noreturn temporary destructors. Now, the analyzer correctly handles expressions like "a || A()", and executes the destructor of "A" only on the paths where "a" evaluted to false. Temporary destructor processing is still off by default and one has to explicitly request it by setting cfg-temporary-dtors=true. Reviewers: jordan_rose CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1259 llvm-svn: 189746 --- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'clang/lib/StaticAnalyzer/Core/ExprEngine.cpp') diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 6aa9174ad6e..79139df786e 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -601,7 +601,15 @@ void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D, void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D, ExplodedNode *Pred, - ExplodedNodeSet &Dst) {} + ExplodedNodeSet &Dst) { + + QualType varType = D.getBindTemporaryExpr()->getSubExpr()->getType(); + + // FIXME: Inlining of temporary destructors is not supported yet anyway, so we + // just put a NULL region for now. This will need to be changed later. + VisitCXXDestructor(varType, NULL, D.getBindTemporaryExpr(), + /*IsBase=*/ false, Pred, Dst); +} void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &DstTop) { @@ -1332,7 +1340,8 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF) { - PrettyStackTraceLocationContext StackCrashInfo(Pred->getLocationContext()); + const LocationContext *LCtx = Pred->getLocationContext(); + PrettyStackTraceLocationContext StackCrashInfo(LCtx); currBldrCtx = &BldCtx; // Check for NULL conditions; e.g. "for(;;)" @@ -1347,10 +1356,14 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, SVal TrueVal = SVB.makeTruthVal(true); SVal FalseVal = SVB.makeTruthVal(false); - // Resolve the condition in the precense of nested '||' and '&&'. if (const Expr *Ex = dyn_cast(Condition)) Condition = Ex->IgnoreParens(); - Condition = ResolveCondition(Condition, BldCtx.getBlock()); + + // If the value is already available, we don't need to do anything. + if (Pred->getState()->getSVal(Condition, LCtx).isUnknownOrUndef()) { + // Resolve the condition in the presence of nested '||' and '&&'. + Condition = ResolveCondition(Condition, BldCtx.getBlock()); + } // Cast truth values to the correct type. if (const Expr *Ex = dyn_cast(Condition)) { @@ -1360,7 +1373,6 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, getContext().getLogicalOperationType()); } - PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(), Condition->getLocStart(), "Error evaluating branch"); -- cgit v1.2.3