aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/ExprEngine.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2013-02-21 23:57:17 +0000
committerJordan Rose <jordan_rose@apple.com>2013-02-21 23:57:17 +0000
commit9f1d541ef1aca8f953e5bb4e7177969f0a2062d5 (patch)
treee0054aa29b2c5dff3f6ed9d98f5cd1065439f102 /lib/StaticAnalyzer/Core/ExprEngine.cpp
parent3892d022f36ee5bf3be4a55ea01c08d323ef6235 (diff)
[analyzer] Make sure a temporary object region matches its initial bindings.
When creating a temporary region (say, when a struct rvalue is used as the base of a member expr), make sure we account for any derived-to-base casts. We don't actually record these in the LazyCompoundVal that represents the rvalue, but we need to make sure that the temporary region we're creating (a) matches the bindings, and (b) matches its expression. Most of the time this will do exactly the same thing as before, but it fixes spurious "garbage value" warnings introduced in r175234 by the use of lazy bindings to model trivial copy constructors. <rdar://problem/13265460> git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175830 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngine.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp35
1 files changed, 31 insertions, 4 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 06b1db564d..60fd8d019e 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -173,10 +173,37 @@ static ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State,
SVal V = State->getSVal(E, LC);
if (V.getAs<NonLoc>()) {
- MemRegionManager &MRMgr = State->getStateManager().getRegionManager();
- const MemRegion *R = MRMgr.getCXXTempObjectRegion(E, LC);
- State = State->bindLoc(loc::MemRegionVal(R), V);
- State = State->BindExpr(E, LC, loc::MemRegionVal(R));
+ 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 = E->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();
+ }
+
+ // 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);
+
+ // 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(E, LC, Reg);
}
return State;