Let StackFrameContext represent if the call expr is evaluated as lvalue.
This is required for supporting const reference to temporary objects.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@120093 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp
index 68c5e15..5307074 100644
--- a/lib/Analysis/AnalysisContext.cpp
+++ b/lib/Analysis/AnalysisContext.cpp
@@ -152,7 +152,8 @@
 }
 
 void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
-  Profile(ID, getAnalysisContext(), getParent(), CallSite, Block, Index);
+  Profile(ID, getAnalysisContext(), getParent(), CallSite.getPointer(),
+          CallSite.getInt(), Block, Index);
 }
 
 void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) {
@@ -188,15 +189,15 @@
 const StackFrameContext*
 LocationContextManager::getStackFrame(AnalysisContext *ctx,
                                       const LocationContext *parent,
-                                      const Stmt *s, const CFGBlock *blk,
-                                      unsigned idx) {
+                                      const Stmt *s, bool asLValue,
+                                      const CFGBlock *blk, unsigned idx) {
   llvm::FoldingSetNodeID ID;
-  StackFrameContext::Profile(ID, ctx, parent, s, blk, idx);
+  StackFrameContext::Profile(ID, ctx, parent, s, asLValue, blk, idx);
   void *InsertPos;
   StackFrameContext *L =
    cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
   if (!L) {
-    L = new StackFrameContext(ctx, parent, s, blk, idx);
+    L = new StackFrameContext(ctx, parent, s, asLValue, blk, idx);
     Contexts.InsertNode(L, InsertPos);
   }
   return L;
diff --git a/lib/Checker/AggExprVisitor.cpp b/lib/Checker/AggExprVisitor.cpp
index f31bcec..9244275 100644
--- a/lib/Checker/AggExprVisitor.cpp
+++ b/lib/Checker/AggExprVisitor.cpp
@@ -53,7 +53,7 @@
 }
 
 void AggExprVisitor::VisitCXXConstructExpr(CXXConstructExpr *E) {
-  Eng.VisitCXXConstructExpr(E, Dest, Pred, DstSet);
+  Eng.VisitCXXConstructExpr(E, Dest, Pred, DstSet, false);
 }
 
 void GRExprEngine::VisitAggExpr(const Expr *E, const MemRegion *Dest, 
diff --git a/lib/Checker/Environment.cpp b/lib/Checker/Environment.cpp
index 914070e..0bbe40d 100644
--- a/lib/Checker/Environment.cpp
+++ b/lib/Checker/Environment.cpp
@@ -65,11 +65,22 @@
         if (CT->isVoidType())
           return UnknownVal();
 
+        if (C->getCastKind() == CK_NoOp) {
+          E = C->getSubExpr();
+          continue;
+        }
         break;
       }
 
-        // Handle all other Stmt* using a lookup.
+      case Stmt::CXXExprWithTemporariesClass:
+        E = cast<CXXExprWithTemporaries>(E)->getSubExpr();
+        continue;
 
+      case Stmt::CXXBindTemporaryExprClass:
+        E = cast<CXXBindTemporaryExpr>(E)->getSubExpr();
+        continue;
+        
+      // Handle all other Stmt* using a lookup.
       default:
         break;
     };
diff --git a/lib/Checker/GRCXXExprEngine.cpp b/lib/Checker/GRCXXExprEngine.cpp
index e9939af..4a0fdc6 100644
--- a/lib/Checker/GRCXXExprEngine.cpp
+++ b/lib/Checker/GRCXXExprEngine.cpp
@@ -100,7 +100,7 @@
 void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, 
                                          const MemRegion *Dest,
                                          ExplodedNode *Pred,
-                                         ExplodedNodeSet &Dst) {
+                                         ExplodedNodeSet &Dst, bool asLValue) {
   if (!Dest)
     Dest = ValMgr.getRegionManager().getCXXObjectRegion(E,
                                                     Pred->getLocationContext());
@@ -125,7 +125,7 @@
   // The callee stack frame context used to create the 'this' parameter region.
   const StackFrameContext *SFC = AMgr.getStackFrame(CD, 
                                                     Pred->getLocationContext(),
-                                   E, Builder->getBlock(), Builder->getIndex());
+                        E, asLValue, Builder->getBlock(), Builder->getIndex());
 
   const CXXThisRegion *ThisR =getCXXThisRegion(E->getConstructor()->getParent(),
                                                SFC);
@@ -153,7 +153,7 @@
   // Create the context for 'this' region.
   const StackFrameContext *SFC = AMgr.getStackFrame(DD,
                                                     Pred->getLocationContext(),
-                                                    S, Builder->getBlock(),
+                                                 S, false, Builder->getBlock(),
                                                     Builder->getIndex());
 
   const CXXThisRegion *ThisR = getCXXThisRegion(DD->getParent(), SFC);
@@ -239,7 +239,7 @@
 
   const StackFrameContext *SFC = AMgr.getStackFrame(MD, 
                                                     Pred->getLocationContext(),
-                                                    MCE, 
+                                                    MCE, false,
                                                     Builder->getBlock(), 
                                                     Builder->getIndex());
   const CXXThisRegion *ThisR = getCXXThisRegion(MD->getParent(), SFC);
diff --git a/lib/Checker/GRCoreEngine.cpp b/lib/Checker/GRCoreEngine.cpp
index 270985f..a676e6c 100644
--- a/lib/Checker/GRCoreEngine.cpp
+++ b/lib/Checker/GRCoreEngine.cpp
@@ -758,7 +758,7 @@
     const StackFrameContext *OldLocCtx = CalleeCtx;
     const StackFrameContext *NewLocCtx = AMgr.getStackFrame(NewAnaCtx, 
                                                OldLocCtx->getParent(),
-                                               OldLocCtx->getCallSite(),
+                                               OldLocCtx->getCallSite(), false,
                                                OldLocCtx->getCallSiteBlock(), 
                                                OldLocCtx->getIndex());
 
diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp
index f0aa38b..2181b70 100644
--- a/lib/Checker/GRExprEngine.cpp
+++ b/lib/Checker/GRExprEngine.cpp
@@ -918,7 +918,7 @@
       const CXXConstructExpr *C = cast<CXXConstructExpr>(S);
       // For block-level CXXConstructExpr, we don't have a destination region.
       // Let VisitCXXConstructExpr() create one.
-      VisitCXXConstructExpr(C, 0, Pred, Dst);
+      VisitCXXConstructExpr(C, 0, Pred, Dst, false);
       break;
     }
 
@@ -1117,7 +1117,6 @@
 
   switch (Ex->getStmtClass()) {
     // C++ stuff we don't support yet.
-    case Stmt::CXXExprWithTemporariesClass:
     case Stmt::CXXMemberCallExprClass:
     case Stmt::CXXScalarValueInitExprClass: {
       SaveAndRestore<bool> OldSink(Builder->BuildSinks);
@@ -1147,6 +1146,24 @@
       break;
     }
 
+    case Stmt::CXXExprWithTemporariesClass: {
+      const CXXExprWithTemporaries *expr = cast<CXXExprWithTemporaries>(Ex);
+      VisitLValue(expr->getSubExpr(), Pred, Dst);
+      break;
+    }
+
+    case Stmt::CXXBindTemporaryExprClass: {
+      const CXXBindTemporaryExpr *expr = cast<CXXBindTemporaryExpr>(Ex);
+      VisitLValue(expr->getSubExpr(), Pred, Dst);
+      break;
+    }
+
+    case Stmt::CXXTemporaryObjectExprClass: {
+      const CXXTemporaryObjectExpr *expr = cast<CXXTemporaryObjectExpr>(Ex);
+      VisitCXXTemporaryObjectExpr(expr, Pred, Dst, true);
+      break;
+    }
+
     case Stmt::CompoundLiteralExprClass:
       VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(Ex), Pred, Dst, true);
       return;
@@ -1643,11 +1660,13 @@
   if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
     const CXXThisRegion *ThisR =
       getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx);
-    // We might not have 'this' region in the binding if we didn't inline
-    // the ctor call.
+
     SVal ThisV = state->getSVal(ThisR);
-    loc::MemRegionVal *V = dyn_cast<loc::MemRegionVal>(&ThisV);
-    if (V) {
+
+    if (calleeCtx->evalAsLValue()) {
+      state = state->BindExpr(CCE, ThisV);
+    } else {
+      loc::MemRegionVal *V = cast<loc::MemRegionVal>(&ThisV);
       SVal ObjVal = state->getSVal(V->getRegion());
       assert(isa<nonloc::LazyCompoundVal>(ObjVal));
       state = state->BindExpr(CCE, ObjVal);
@@ -2073,7 +2092,7 @@
     const StackFrameContext *stackFrame = 
       AMgr.getStackFrame(AMgr.getAnalysisContext(FD), 
                          Pred->getLocationContext(),
-                         CE, Builder->getBlock(), Builder->getIndex());
+                         CE, false, Builder->getBlock(), Builder->getIndex());
     // Now we have the definition of the callee, create a CallEnter node.
     CallEnter Loc(CE, stackFrame, Pred->getLocationContext());
 
@@ -2089,7 +2108,7 @@
       return false;
     const StackFrameContext *stackFrame = 
       AMgr.getStackFrame(C, Pred->getLocationContext(),
-                         CE, Builder->getBlock(), Builder->getIndex());
+                         CE, false, Builder->getBlock(), Builder->getIndex());
     CallEnter Loc(CE, stackFrame, Pred->getLocationContext());
     ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
     Dst.Add(N);