]> granicus.if.org Git - clang/commitdiff
Let StackFrameContext represent if the call expr is evaluated as lvalue.
authorZhongxing Xu <xuzhongxing@gmail.com>
Wed, 24 Nov 2010 13:08:51 +0000 (13:08 +0000)
committerZhongxing Xu <xuzhongxing@gmail.com>
Wed, 24 Nov 2010 13:08:51 +0000 (13:08 +0000)
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

include/clang/Analysis/AnalysisContext.h
include/clang/Checker/PathSensitive/AnalysisManager.h
include/clang/Checker/PathSensitive/GRExprEngine.h
lib/Analysis/AnalysisContext.cpp
lib/Checker/AggExprVisitor.cpp
lib/Checker/Environment.cpp
lib/Checker/GRCXXExprEngine.cpp
lib/Checker/GRCoreEngine.cpp
lib/Checker/GRExprEngine.cpp

index 0a61f440dae63a228de7b8c2a4f44cea976cce25..a941f7fe57d0f15d19cdd5d6c3f5da35ea0d853e 100644 (file)
@@ -198,8 +198,9 @@ public:
 };
 
 class StackFrameContext : public LocationContext {
-  // The callsite where this stack frame is established.
-  const Stmt *CallSite;
+  // The callsite where this stack frame is established. The int bit indicates
+  // whether the call expr should return an l-value when it has reference type.
+  llvm::PointerIntPair<const Stmt *, 1> CallSite;
 
   // The parent block of the callsite.
   const CFGBlock *Block;
@@ -209,14 +210,17 @@ class StackFrameContext : public LocationContext {
 
   friend class LocationContextManager;
   StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
-                    const Stmt *s, const CFGBlock *blk, unsigned idx)
-    : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk),
-      Index(idx) {}
+                    const Stmt *s, bool asLValue, const CFGBlock *blk, 
+                    unsigned idx)
+    : LocationContext(StackFrame, ctx, parent), CallSite(s, asLValue), 
+      Block(blk), Index(idx) {}
 
 public:
   ~StackFrameContext() {}
 
-  const Stmt *getCallSite() const { return CallSite; }
+  const Stmt *getCallSite() const { return CallSite.getPointer(); }
+
+  bool evalAsLValue() const { return CallSite.getInt(); }
 
   const CFGBlock *getCallSiteBlock() const { return Block; }
 
@@ -226,8 +230,9 @@ public:
 
   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
                       const LocationContext *parent, const Stmt *s,
-                      const CFGBlock *blk, unsigned idx) {
+                      bool asLValue, const CFGBlock *blk, unsigned idx) {
     ProfileCommon(ID, StackFrame, ctx, parent, s);
+    ID.AddBoolean(asLValue);
     ID.AddPointer(blk);
     ID.AddInteger(idx);
   }
@@ -295,8 +300,8 @@ public:
 
   const StackFrameContext *getStackFrame(AnalysisContext *ctx,
                                          const LocationContext *parent,
-                                         const Stmt *s, const CFGBlock *blk,
-                                         unsigned idx);
+                                         const Stmt *s, bool asLValue,
+                                         const CFGBlock *blk, unsigned idx);
 
   const ScopeContext *getScope(AnalysisContext *ctx,
                                const LocationContext *parent,
index 79d990389080ae564f42e9aea723f7c470b7ac40..ce33269da08b17d8fa07c51e59aca0fd65aff5f0 100644 (file)
@@ -178,23 +178,24 @@ public:
 
   const StackFrameContext *getStackFrame(AnalysisContext *Ctx,
                                          LocationContext const *Parent,
-                                         Stmt const *S, const CFGBlock *Blk,
-                                         unsigned Idx) {
-    return LocCtxMgr.getStackFrame(Ctx, Parent, S, Blk, Idx);
+                                         const Stmt *S, bool asLValue,
+                                         const CFGBlock *Blk, unsigned Idx) {
+    return LocCtxMgr.getStackFrame(Ctx, Parent, S, asLValue, Blk, Idx);
   }
 
   // Get the top level stack frame.
   const StackFrameContext *getStackFrame(Decl const *D, 
                                          idx::TranslationUnit *TU) {
-    return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D, TU), 0, 0, 0, 0);
+    return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D, TU), 0, 0, 0, 0, 0);
   }
 
   // Get a stack frame with parent.
-  StackFrameContext const *getStackFrame(Decl const *D, 
+  StackFrameContext const *getStackFrame(const Decl *D, 
                                          LocationContext const *Parent,
-                                         Stmt const *S, const CFGBlock *Blk,
-                                         unsigned Idx) {
-    return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S, Blk,Idx);
+                                         const Stmt *S, bool asLValue,
+                                         const CFGBlock *Blk, unsigned Idx) {
+    return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), Parent, S, asLValue,
+                                   Blk,Idx);
   }
 };
 
index 04fce44480d0191cc25c51fe824f296e7907e1c6..4e97b8ee2e575e46fe5678040dd3af6259fb1c1e 100644 (file)
@@ -424,9 +424,16 @@ public:
 
   void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, 
                         ExplodedNodeSet & Dst);
-  
+
+  void VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *expr,
+                                   ExplodedNode *Pred, ExplodedNodeSet &Dst, 
+                                   bool asLValue) {
+    VisitCXXConstructExpr(expr, 0, Pred, Dst, asLValue);
+  }
+
   void VisitCXXConstructExpr(const CXXConstructExpr *E, const MemRegion *Dest,
-                             ExplodedNode *Pred, ExplodedNodeSet &Dst);
+                             ExplodedNode *Pred, ExplodedNodeSet &Dst, 
+                             bool asLValue);
 
   void VisitCXXDestructor(const CXXDestructorDecl *DD,
                           const MemRegion *Dest, const Stmt *S,
index 68c5e158f3a5c43fdb9a0cfb596233297ff8f3ae..5307074dce6889d10d8a4336dcf706acee0cf45c 100644 (file)
@@ -152,7 +152,8 @@ void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
 }
 
 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 @@ LocationContextManager::getLocationContext(AnalysisContext *ctx,
 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;
index f31bcec73adc2b52cee1ca1d566d4c37b08100c0..924427534349e726a43c416a73cac3b5bc577508 100644 (file)
@@ -53,7 +53,7 @@ void AggExprVisitor::VisitCastExpr(CastExpr *E) {
 }
 
 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, 
index 914070e030b4376e3d72843de846c8e5827d9e12..0bbe40dc1a808a68a9972d9b2bfbd0b5afdcc187 100644 (file)
@@ -65,11 +65,22 @@ SVal Environment::GetSVal(const Stmt *E, ValueManager& ValMgr) const {
         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;
     };
index e9939af1eb51683be070b2bc7fde4cf5b92fab80..4a0fdc66ed8e05c483c148dd1bb38d4021801094 100644 (file)
@@ -100,7 +100,7 @@ void GRExprEngine::CreateCXXTemporaryObject(const Expr *Ex, ExplodedNode *Pred,
 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 @@ void GRExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
   // 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 @@ void GRExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
   // 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 @@ void GRExprEngine::EvalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD,
 
   const StackFrameContext *SFC = AMgr.getStackFrame(MD, 
                                                     Pred->getLocationContext(),
-                                                    MCE, 
+                                                    MCE, false,
                                                     Builder->getBlock(), 
                                                     Builder->getIndex());
   const CXXThisRegion *ThisR = getCXXThisRegion(MD->getParent(), SFC);
index 270985f4164f504a497fe25e556484be996c15a5..a676e6ca26f625242e7bb40786d3c5d618ac9dbe 100644 (file)
@@ -758,7 +758,7 @@ void GRCallEnterNodeBuilder::GenerateNode(const GRState *state) {
     const StackFrameContext *OldLocCtx = CalleeCtx;
     const StackFrameContext *NewLocCtx = AMgr.getStackFrame(NewAnaCtx, 
                                                OldLocCtx->getParent(),
-                                               OldLocCtx->getCallSite(),
+                                               OldLocCtx->getCallSite(), false,
                                                OldLocCtx->getCallSiteBlock(), 
                                                OldLocCtx->getIndex());
 
index f0aa38b07c1a96a0b410e07ce43af6caa15b8987..2181b705f768c2de3fc5cef468395caff8c26a65 100644 (file)
@@ -918,7 +918,7 @@ void GRExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
       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 @@ void GRExprEngine::VisitLValue(const Expr* Ex, ExplodedNode* Pred,
 
   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 @@ void GRExprEngine::VisitLValue(const Expr* Ex, ExplodedNode* Pred,
       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 @@ void GRExprEngine::ProcessCallExit(GRCallExitNodeBuilder &B) {
   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 @@ bool GRExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,
     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 @@ bool GRExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,
       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);