aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/ExprEngine.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2013-02-22 01:51:15 +0000
committerJordan Rose <jordan_rose@apple.com>2013-02-22 01:51:15 +0000
commit5e5440ba9c135f523f72e7e7c5da59d390d697c5 (patch)
tree484f8a826bd0c90edab9f2fb8826f3b0a3411e53 /lib/StaticAnalyzer/Core/ExprEngine.cpp
parentf08740ba5903d089a53cc315c19286e2189f9ff3 (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.cpp67
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;
}