aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2013-02-15 00:32:15 +0000
committerJordan Rose <jordan_rose@apple.com>2013-02-15 00:32:15 +0000
commitbc403861bc4e6f7ad1371e9e129f0f25b38b3a9a (patch)
treef65b4d97763ba7614dd89d32f11303a7ba98b165 /lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
parent28743b006bd88cd7d0ea97b4f17646f8fc429b89 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175234 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngineCXX.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCXX.cpp54
1 files changed, 48 insertions, 6 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 1f0c523ac6..fdd50a6b54 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/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);
}