When binding an rvalue to a reference, create a temporary object. Use
CXXObjectRegion to represent it.
In Environment, lookup a literal expression before make up a value for it.
llvm-svn: 93047
diff --git a/clang/lib/Analysis/Environment.cpp b/clang/lib/Analysis/Environment.cpp
index dd2f08b..f04cf7b 100644
--- a/clang/lib/Analysis/Environment.cpp
+++ b/clang/lib/Analysis/Environment.cpp
@@ -37,7 +37,12 @@
}
case Stmt::IntegerLiteralClass: {
- return ValMgr.makeIntVal(cast<IntegerLiteral>(E));
+ // In C++, this expression may have been bound to a temporary object.
+ SVal const *X = ExprBindings.lookup(E);
+ if (X)
+ return *X;
+ else
+ return ValMgr.makeIntVal(cast<IntegerLiteral>(E));
}
// Casts where the source and target type are the same
diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp
index 0336ae5..ed3dc8a 100644
--- a/clang/lib/Analysis/GRExprEngine.cpp
+++ b/clang/lib/Analysis/GRExprEngine.cpp
@@ -887,6 +887,11 @@
case Stmt::UnaryOperatorClass:
VisitUnaryOperator(cast<UnaryOperator>(Ex), Pred, Dst, true);
return;
+
+ // In C++, binding an rvalue to a reference requires to create an object.
+ case Stmt::IntegerLiteralClass:
+ CreateCXXTemporaryObject(Ex, Pred, Dst);
+ return;
default:
// Arbitrary subexpressions can return aggregate temporaries that
@@ -2992,6 +2997,26 @@
CheckerVisit(B, Dst, Tmp3, false);
}
+void GRExprEngine::CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+ ExplodedNodeSet Tmp;
+ Visit(Ex, Pred, Tmp);
+ for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
+ const GRState *state = GetState(*I);
+
+ // Bind the temporary object to the value of the expression. Then bind
+ // the expression to the location of the object.
+ SVal V = state->getSVal(Ex);
+
+ const MemRegion *R =
+ ValMgr.getRegionManager().getCXXObjectRegion(Ex,
+ Pred->getLocationContext());
+
+ state = state->bindLoc(loc::MemRegionVal(R), V);
+ MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, loc::MemRegionVal(R)));
+ }
+}
+
//===----------------------------------------------------------------------===//
// Checker registration/lookup.
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Analysis/MemRegion.cpp b/clang/lib/Analysis/MemRegion.cpp
index 5be882a..c17e4e8 100644
--- a/clang/lib/Analysis/MemRegion.cpp
+++ b/clang/lib/Analysis/MemRegion.cpp
@@ -304,14 +304,14 @@
}
void CXXObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
- QualType T,
+ Expr const *Ex,
const MemRegion *sReg) {
- ID.AddPointer(T.getTypePtr());
+ ID.AddPointer(Ex);
ID.AddPointer(sReg);
}
void CXXObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
- ProfileRegion(ID, T, getSuperRegion());
+ ProfileRegion(ID, Ex, getSuperRegion());
}
//===----------------------------------------------------------------------===//
@@ -580,8 +580,11 @@
}
const CXXObjectRegion*
-MemRegionManager::getCXXObjectRegion(QualType T) {
- return getSubRegion<CXXObjectRegion>(T, getUnknownRegion());
+MemRegionManager::getCXXObjectRegion(Expr const *E,
+ LocationContext const *LC) {
+ const StackFrameContext *SFC = LC->getCurrentStackFrame();
+ assert(SFC);
+ return getSubRegion<CXXObjectRegion>(E, getStackLocalsRegion(SFC));
}
const CXXThisRegion*