]> granicus.if.org Git - clang/commitdiff
After inlining the CXXConstructExpr, bind the temporary object region to it.
authorZhongxing Xu <xuzhongxing@gmail.com>
Wed, 22 Dec 2010 07:20:27 +0000 (07:20 +0000)
committerZhongxing Xu <xuzhongxing@gmail.com>
Wed, 22 Dec 2010 07:20:27 +0000 (07:20 +0000)
This change is necessary when the variable is a const reference and we need
the l-value of the construct expr.  After that, when binding the variable,
recover the lazy compound value when the variable is not a reference.

In Environment, use the value of a no-op cast expression when it has one.
Otherwise, blast-through it.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122388 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Checker/Environment.cpp
lib/Checker/GRExprEngine.cpp
test/Analysis/method-call.cpp

index 7bf2929161c9f5a815252bc85d2769e1a8725f58..954129883d6a0e0d38c9a684301eaa029c4a1efe 100644 (file)
@@ -63,7 +63,12 @@ SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder) const {
         if (CT->isVoidType())
           return UnknownVal();
         if (C->getCastKind() == CK_NoOp) {
-          E = C->getSubExpr();
+          // If the no-op cast has value, use it. Should we always propagate
+          // values through all levels of no-op casts?
+          if (const SVal* X = ExprBindings.lookup(C))
+            return *X;
+          else
+            E = C->getSubExpr();
           continue;
         }
         break;
index 2945de162a9f37a0f839ec1f0926724aa400dd92..a24a5df4fb699b81f87f67f5ae30b7c3e8e75f92 100644 (file)
@@ -1475,15 +1475,8 @@ void GRExprEngine::ProcessCallExit(GRCallExitNodeBuilder &B) {
       getCXXThisRegion(CCE->getConstructor()->getParent(), calleeCtx);
 
     SVal ThisV = state->getSVal(ThisR);
-
-    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);
-    }
+    // Always bind the region to the CXXConstructExpr.
+    state = state->BindExpr(CCE, ThisV);
   }
 
   B.generateNode(state);
@@ -2508,7 +2501,12 @@ void GRExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
 
   if (InitEx) {
     if (VD->getType()->isReferenceType() && !InitEx->isLValue()) {
-      CreateCXXTemporaryObject(InitEx, Pred, Tmp);
+      // If the initializer is C++ record type, it should already has a 
+      // temp object.
+      if (!InitEx->getType()->isRecordType())
+        CreateCXXTemporaryObject(InitEx, Pred, Tmp);
+      else
+        Tmp.Add(Pred);
     } else
       Visit(InitEx, Pred, Tmp);
   } else
@@ -2527,6 +2525,14 @@ void GRExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
     if (InitEx) {
       SVal InitVal = state->getSVal(InitEx);
 
+      // We bound the temp obj region to the CXXConstructExpr. Now recover
+      // the lazy compound value when the variable is not a reference.
+      if (AMgr.getLangOptions().CPlusPlus && VD->getType()->isRecordType() && 
+          !VD->getType()->isReferenceType() && isa<loc::MemRegionVal>(InitVal)){
+        InitVal = state->getSVal(cast<loc::MemRegionVal>(InitVal).getRegion());
+        assert(isa<nonloc::LazyCompoundVal>(InitVal));
+      }
+
       // Recover some path-sensitivity if a scalar value evaluated to
       // UnknownVal.
       if ((InitVal.isUnknown() ||
index 31065f41dbff7e4badeb7dbef9bcca10aa4470c8..8c6b9da0f40163d8026b30a6a5673c65f84b16c3 100644 (file)
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-inline-call -analyzer-store region -verify %s
-// XFAIL: *
 
 struct A {
   int x;