diff options
author | Jordan Rose <jordan_rose@apple.com> | 2013-02-15 00:32:15 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2013-02-15 00:32:15 +0000 |
commit | 88bb563c4350ce67ebc435de046fa395e74c4670 (patch) | |
tree | 234adefe53031b8ee0b5fe8b6fbcbe414030f695 /clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | |
parent | 2516d7b0e87d1f74941c876e1d3bb3638ce8b204 (diff) | |
download | bcm5719-llvm-88bb563c4350ce67ebc435de046fa395e74c4670.tar.gz bcm5719-llvm-88bb563c4350ce67ebc435de046fa395e74c4670.zip |
Re-apply "[analyzer] Model trivial copy/move ctors with an aggregate bind."
...after a host of optimizations related to the use of LazyCompoundVals
(our implementation of aggregate binds).
Originally applied in r173951.
Reverted in r174069 because it was causing hangs.
Re-applied in r174212.
Reverted in r174265 because it was /still/ causing hangs.
If this needs to be reverted again it will be punted to far in the future.
llvm-svn: 175234
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 54 |
1 files changed, 48 insertions, 6 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 1f0c523ac66..fdd50a6b544 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -49,6 +49,35 @@ void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, V)); } +void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred, + const CXXConstructorCall &Call) { + const CXXConstructExpr *CtorExpr = Call.getOriginExpr(); + assert(CtorExpr->getConstructor()->isCopyOrMoveConstructor()); + assert(CtorExpr->getConstructor()->isTrivial()); + + SVal ThisVal = Call.getCXXThisVal(); + const LocationContext *LCtx = Pred->getLocationContext(); + + ExplodedNodeSet Dst; + Bldr.takeNodes(Pred); + + SVal V = Call.getArgSVal(0); + + // Make sure the value being copied is not unknown. + if (const Loc *L = dyn_cast<Loc>(&V)) + V = Pred->getState()->getSVal(*L); + + evalBind(Dst, CtorExpr, Pred, ThisVal, V, true); + + PostStmt PS(CtorExpr, LCtx); + for (ExplodedNodeSet::iterator I = Dst.begin(), E = Dst.end(); + I != E; ++I) { + ProgramStateRef State = (*I)->getState(); + State = bindReturnValue(Call, LCtx, State); + Bldr.generateNode(PS, State, *I); + } +} + void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, ExplodedNode *Pred, ExplodedNodeSet &destNodes) { @@ -56,6 +85,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, ProgramStateRef State = Pred->getState(); const MemRegion *Target = 0; + bool IsArray = false; switch (CE->getConstructionKind()) { case CXXConstructExpr::CK_Complete: { @@ -79,6 +109,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, Target = State->getLValue(AT->getElementType(), getSValBuilder().makeZeroArrayIndex(), Base).getAsRegion(); + IsArray = true; } else { Target = State->getLValue(Var, LCtx).getAsRegion(); } @@ -148,14 +179,25 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, getCheckerManager().runCheckersForPreCall(DstPreCall, DstPreVisit, *Call, *this); - ExplodedNodeSet DstInvalidated; - StmtNodeBuilder Bldr(DstPreCall, DstInvalidated, *currBldrCtx); - for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); - I != E; ++I) - defaultEvalCall(Bldr, *I, *Call); + ExplodedNodeSet DstEvaluated; + StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx); + + if (CE->getConstructor()->isTrivial() && + CE->getConstructor()->isCopyOrMoveConstructor() && + !IsArray) { + // FIXME: Handle other kinds of trivial constructors as well. + for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); + I != E; ++I) + performTrivialCopy(Bldr, *I, *Call); + + } else { + for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end(); + I != E; ++I) + defaultEvalCall(Bldr, *I, *Call); + } ExplodedNodeSet DstPostCall; - getCheckerManager().runCheckersForPostCall(DstPostCall, DstInvalidated, + getCheckerManager().runCheckersForPostCall(DstPostCall, DstEvaluated, *Call, *this); getCheckerManager().runCheckersForPostStmt(destNodes, DstPostCall, CE, *this); } |