diff options
author | Jordan Rose <jordan_rose@apple.com> | 2013-02-22 01:51:15 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2013-02-22 01:51:15 +0000 |
commit | 5e5440ba9c135f523f72e7e7c5da59d390d697c5 (patch) | |
tree | 484f8a826bd0c90edab9f2fb8826f3b0a3411e53 /lib/StaticAnalyzer/Core/ExprEngine.cpp | |
parent | f08740ba5903d089a53cc315c19286e2189f9ff3 (diff) |
[analyzer] Make sure a materialized temporary matches its bindings.
This is a follow-up to r175830, which made sure a temporary object region
created for, say, a struct rvalue matched up with the initial bindings
being stored into it. This does the same for the case in which the AST
actually tells us that we need to create a temporary via a
MaterializeObjectExpr. I've unified the two code paths and moved a static
helper function onto ExprEngine.
This also caused a bit of test churn, causing us to go back to describing
temporary regions without a 'const' qualifier. This seems acceptable; it's
our behavior from a few months ago.
<rdar://problem/13265460> (part 2)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175854 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngine.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 67 |
1 files changed, 33 insertions, 34 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index f15a02be2b..5d5b9b70cb 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -165,47 +165,46 @@ ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) { return state; } -/// If the value of the given expression is a NonLoc, copy it into a new -/// temporary region, and replace the value of the expression with that. -static ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State, - const LocationContext *LC, - const Expr *Ex) { +ProgramStateRef +ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State, + const LocationContext *LC, + const Expr *Ex, + const Expr *Result) { SVal V = State->getSVal(Ex, LC); + if (!Result && !V.getAs<NonLoc>()) + return State; - if (V.getAs<NonLoc>()) { - ProgramStateManager &StateMgr = State->getStateManager(); - MemRegionManager &MRMgr = StateMgr.getRegionManager(); - StoreManager &StoreMgr = StateMgr.getStoreManager(); - - // We need to be careful about treating a derived type's value as - // bindings for a base type. Start by stripping and recording base casts. - SmallVector<const CastExpr *, 4> Casts; - const Expr *Inner = Ex->IgnoreParens(); - while (const CastExpr *CE = dyn_cast<CastExpr>(Inner)) { - if (CE->getCastKind() == CK_DerivedToBase || - CE->getCastKind() == CK_UncheckedDerivedToBase) - Casts.push_back(CE); - else if (CE->getCastKind() != CK_NoOp) - break; - - Inner = CE->getSubExpr()->IgnoreParens(); - } + ProgramStateManager &StateMgr = State->getStateManager(); + MemRegionManager &MRMgr = StateMgr.getRegionManager(); + StoreManager &StoreMgr = StateMgr.getStoreManager(); + + // We need to be careful about treating a derived type's value as + // bindings for a base type. Start by stripping and recording base casts. + SmallVector<const CastExpr *, 4> Casts; + const Expr *Inner = Ex->IgnoreParens(); + while (const CastExpr *CE = dyn_cast<CastExpr>(Inner)) { + if (CE->getCastKind() == CK_DerivedToBase || + CE->getCastKind() == CK_UncheckedDerivedToBase) + Casts.push_back(CE); + else if (CE->getCastKind() != CK_NoOp) + break; - // Create a temporary object region for the inner expression (which may have - // a more derived type) and bind the NonLoc value into it. - SVal Reg = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(Inner, LC)); - State = State->bindLoc(Reg, V); + Inner = CE->getSubExpr()->IgnoreParens(); + } - // Re-apply the casts (from innermost to outermost) for type sanity. - for (SmallVectorImpl<const CastExpr *>::reverse_iterator I = Casts.rbegin(), - E = Casts.rend(); - I != E; ++I) { - Reg = StoreMgr.evalDerivedToBase(Reg, *I); - } + // Create a temporary object region for the inner expression (which may have + // a more derived type) and bind the NonLoc value into it. + SVal Reg = loc::MemRegionVal(MRMgr.getCXXTempObjectRegion(Inner, LC)); + State = State->bindLoc(Reg, V); - State = State->BindExpr(Ex, LC, Reg); + // Re-apply the casts (from innermost to outermost) for type sanity. + for (SmallVectorImpl<const CastExpr *>::reverse_iterator I = Casts.rbegin(), + E = Casts.rend(); + I != E; ++I) { + Reg = StoreMgr.evalDerivedToBase(Reg, *I); } + State = State->BindExpr(Result ? Result : Ex, LC, Reg); return State; } |