This is the first step to build a better evaluation model for GRExprEngine.  A
new VisitLValue method is added to replace the old VisitLVal. The semantics
model becomes more explicit to separate rvalue evaluation from lvalue
evaluation.  


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57627 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index 47e2905..f97f8b2 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -42,9 +42,12 @@
 
   virtual MemRegionManager& getRegionManager() { return MRMgr; }
 
+  // FIXME: Investigate what is using this. This method should be removed.
   virtual LVal getLVal(const VarDecl* VD) {
     return lval::MemRegionVal(MRMgr.getVarRegion(VD));
   }
+
+  virtual RVal getLValue(const GRState* St, const Expr* Ex);
   
   virtual Store
   RemoveDeadBindings(Store store, Stmt* Loc, const LiveVariables& Live,
@@ -73,6 +76,35 @@
   return new BasicStoreManager(StMgr);
 }
 
+// FIXME: replace ArrayOffset and FieldOffset with some region value.
+RVal BasicStoreManager::getLValue(const GRState* St, const Expr* Ex) {
+  if (const DeclRefExpr* DRE = dyn_cast<DeclRefExpr>(Ex)) {
+    const VarDecl* VD = cast<VarDecl>(DRE->getDecl());
+    QualType T = VD->getType();
+
+    // Array and struct variable have no lvalue.
+    assert(!T->isArrayType());
+
+    return lval::MemRegionVal(MRMgr.getVarRegion(VD));
+
+  } else if (const ArraySubscriptExpr* A = dyn_cast<ArraySubscriptExpr>(Ex)) {
+    const Expr* Base = A->getBase()->IgnoreParens();
+    const Expr* Idx  = A->getIdx()->IgnoreParens();
+    RVal BaseV = StateMgr.GetRVal(St, Base);
+    RVal IdxV = StateMgr.GetRVal(St, Idx);
+    return lval::ArrayOffset::Make(StateMgr.getBasicVals(), BaseV, IdxV);
+
+  } else if (const MemberExpr* M = dyn_cast<MemberExpr>(Ex)) {
+    Expr* Base = M->getBase()->IgnoreParens();
+    RVal BaseV = StateMgr.GetRVal(St, Base);
+    return lval::FieldOffset::Make(StateMgr.getBasicVals(), BaseV, 
+                                   M->getMemberDecl());
+  } else {
+    Ex->dump();
+    assert(0);
+  }
+}
+
 RVal BasicStoreManager::GetRVal(Store St, LVal LV, QualType T) {
   
   if (isa<UnknownVal>(LV))
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index c391c6f..2d24134 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -395,7 +395,7 @@
   }
 }
 
-void GRExprEngine::VisitLVal(Expr* Ex, NodeTy* Pred, NodeSet& Dst) {
+void GRExprEngine::VisitLValue(Expr* Ex, NodeTy* Pred, NodeSet& Dst) {
   
   Ex = Ex->IgnoreParens();
   
@@ -406,8 +406,8 @@
   
   switch (Ex->getStmtClass()) {
     default:
-      Visit(Ex, Pred, Dst);
-      return;
+      Ex->dump();
+      assert(0 && "Other kinds of expressions do not have lvalue.");
       
     case Stmt::ArraySubscriptExprClass:
       VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(Ex), Pred, Dst, true);
@@ -788,59 +788,79 @@
 // Transfer functions: Loads and stores.
 //===----------------------------------------------------------------------===//
 
-void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* D, NodeTy* Pred, NodeSet& Dst,
-                                    bool asLVal) {
+void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* Ex, NodeTy* Pred, NodeSet& Dst,
+                                    bool asLValue) {
   
   const GRState* St = GetState(Pred);
-  RVal X = RVal::MakeVal(getStateManager(), D);
-  
-  if (asLVal)
-    MakeNode(Dst, D, Pred, SetRVal(St, D, cast<LVal>(X)));
-  else {
-    RVal V = isa<lval::MemRegionVal>(X) ? GetRVal(St, cast<LVal>(X)) : X;
-    MakeNode(Dst, D, Pred, SetRVal(St, D, V));
+
+  const ValueDecl* D = Ex->getDecl();
+
+  if (const VarDecl* VD = dyn_cast<VarDecl>(D)) {
+
+    QualType T = VD->getType();
+    if (T->isArrayType()) {
+      assert(!asLValue && "Array variable has no lvalue.");
+
+      // C++ standard says array value should be implicitly converted to pointer
+      // in some cases. We don't have such context information right now.  We
+      // use a MemRegionVal to represent this. May be changed in the future.
+
+      RVal V = lval::MemRegionVal(StateMgr.getRegion(VD));
+      MakeNode(Dst, Ex, Pred, SetRVal(St, Ex, V));
+      return;
+    }
+
+    RVal V = GetLValue(St, Ex);
+    if (asLValue)
+      MakeNode(Dst, Ex, Pred, SetRVal(St, Ex, V));
+    else
+      EvalLoad(Dst, Ex, Pred, St, V);
+    return;
+
+  } else if (const EnumConstantDecl* ED = dyn_cast<EnumConstantDecl>(D)) {
+    assert(!asLValue && "EnumConstantDecl does not have lvalue.");
+
+    BasicValueFactory& BasicVals = StateMgr.getBasicVals();
+    RVal V = nonlval::ConcreteInt(BasicVals.getValue(ED->getInitVal()));
+    MakeNode(Dst, Ex, Pred, SetRVal(St, Ex, V));
+    return;
+
+  } else if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {
+    assert(!asLValue && "FunctionDecl does not have lvalue.");
+
+    RVal V = lval::FuncVal(FD);
+    MakeNode(Dst, Ex, Pred, SetRVal(St, Ex, V));
+    return;
   }
+  
+  assert (false &&
+          "ValueDecl support for this ValueDecl not implemented.");
 }
 
 /// VisitArraySubscriptExpr - Transfer function for array accesses
 void GRExprEngine::VisitArraySubscriptExpr(ArraySubscriptExpr* A, NodeTy* Pred,
-                                           NodeSet& Dst, bool asLVal) {
+                                           NodeSet& Dst, bool asLValue) {
   
   Expr* Base = A->getBase()->IgnoreParens();
   Expr* Idx  = A->getIdx()->IgnoreParens();
   
-  // Always visit the base as an LVal expression.  This computes the
-  // abstract address of the base object.
   NodeSet Tmp;
-  
-  if (LVal::IsLValType(Base->getType())) // Base always is an LVal.
-    Visit(Base, Pred, Tmp);
-  else  
-    VisitLVal(Base, Pred, Tmp);
+
+  // Get Base's rvalue, which should be an LocVal.
+  Visit(Base, Pred, Tmp);
   
   for (NodeSet::iterator I1=Tmp.begin(), E1=Tmp.end(); I1!=E1; ++I1) {
     
     // Evaluate the index.
-
     NodeSet Tmp2;
     Visit(Idx, *I1, Tmp2);
       
     for (NodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end(); I2!=E2; ++I2) {
 
       const GRState* St = GetState(*I2);
-      RVal BaseV = GetRVal(St, Base);
-      RVal IdxV  = GetRVal(St, Idx);      
-      
-      // If IdxV is 0, return just BaseV.
-      
-      bool useBase = false;
-      
-      if (nonlval::ConcreteInt* IdxInt = dyn_cast<nonlval::ConcreteInt>(&IdxV))        
-        useBase = IdxInt->getValue() == 0;
-      
-      RVal V = useBase ? BaseV : lval::ArrayOffset::Make(getBasicVals(), BaseV,IdxV);
+      RVal V = GetLValue(St, A);
 
-      if (asLVal)
+      if (asLValue)
         MakeNode(Dst, A, *I2, SetRVal(St, A, V));
       else
         EvalLoad(Dst, A, *I2, St, V);
@@ -850,65 +870,22 @@
 
 /// VisitMemberExpr - Transfer function for member expressions.
 void GRExprEngine::VisitMemberExpr(MemberExpr* M, NodeTy* Pred,
-                                   NodeSet& Dst, bool asLVal) {
+                                   NodeSet& Dst, bool asLValue) {
   
   Expr* Base = M->getBase()->IgnoreParens();
 
-  // Always visit the base as an LVal expression.  This computes the
-  // abstract address of the base object.
   NodeSet Tmp;
-  
-  if (asLVal) {
-      
-    if (LVal::IsLValType(Base->getType())) // Base always is an LVal.
-      Visit(Base, Pred, Tmp);
-    else  
-      VisitLVal(Base, Pred, Tmp);
-  
-    for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
-      const GRState* St = GetState(*I);
-      RVal BaseV = GetRVal(St, Base);      
-      
-      RVal V = lval::FieldOffset::Make(getBasicVals(), GetRVal(St, Base),
-                                       M->getMemberDecl());
-      
-      MakeNode(Dst, M, *I, SetRVal(St, M, V));
-    }
-    
-    return;
-  }
 
-  // Evaluate the base.  Can be an LVal or NonLVal (depends on whether
-  //  or not isArrow() is true).
+  // Get Base expr's rvalue.
   Visit(Base, Pred, Tmp);
-  
-  for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
 
+  for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
     const GRState* St = GetState(*I);
-    RVal BaseV = GetRVal(St, Base);
-    
-    if (LVal::IsLValType(Base->getType())) {
-    
-      assert (M->isArrow());
-      
-      RVal V = lval::FieldOffset::Make(getBasicVals(), GetRVal(St, Base),
-                                       M->getMemberDecl());
-    
-      EvalLoad(Dst, M, *I, St, V);
-    }
-    else {
-      
-      assert (!M->isArrow());
-      
-      if (BaseV.isUnknownOrUndef()) {
-        MakeNode(Dst, M, *I, SetRVal(St, M, BaseV));
-        continue;
-      }
-
-      // FIXME: Implement nonlval objects representing struct temporaries.
-      assert (isa<NonLVal>(BaseV));
-      MakeNode(Dst, M, *I, SetRVal(St, M, UnknownVal()));
-    }
+    RVal L = GetLValue(St, M);
+    if (asLValue)
+      MakeNode(Dst, M, *I, SetRVal(St, M, L));
+    else
+      EvalLoad(Dst, M, *I, St, L);
   }
 }
 
@@ -1080,7 +1057,7 @@
   NodeSet DstTmp;    
   Expr* Callee = CE->getCallee()->IgnoreParens();
 
-  VisitLVal(Callee, Pred, DstTmp);
+  Visit(Callee, Pred, DstTmp);
   
   // Finally, evaluate the function call.
   for (NodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end(); DI!=DE; ++DI) {
@@ -1412,12 +1389,11 @@
 //===----------------------------------------------------------------------===//
 
 void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
-  
   NodeSet S1;
   QualType T = CastE->getType();
   
   if (T->isReferenceType())
-    VisitLVal(Ex, Pred, S1);
+    VisitLValue(Ex, Pred, S1);
   else
     Visit(Ex, Pred, S1);
   
@@ -1562,7 +1538,7 @@
 
 
 void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
-                                      NodeSet& Dst, bool asLVal) {
+                                      NodeSet& Dst, bool asLValue) {
 
   switch (U->getOpcode()) {
       
@@ -1580,7 +1556,7 @@
         const GRState* St = GetState(*I);
         RVal location = GetRVal(St, Ex);
         
-        if (asLVal)
+        if (asLValue)
           MakeNode(Dst, U, *I, SetRVal(St, U, location));
         else
           EvalLoad(Dst, U, *I, St, location);
@@ -1642,7 +1618,7 @@
       Dst.Add(Pred);
       return;
       
-    case UnaryOperator::Plus: assert (!asLVal);  // FALL-THROUGH.
+    case UnaryOperator::Plus: assert (!asLValue);  // FALL-THROUGH.
     case UnaryOperator::Extension: {
       
       // Unary "+" is a no-op, similar to a parentheses.  We still have places
@@ -1664,10 +1640,10 @@
     
     case UnaryOperator::AddrOf: {
       
-      assert (!asLVal);
+      assert(!asLValue);
       Expr* Ex = U->getSubExpr()->IgnoreParens();
       NodeSet Tmp;
-      VisitLVal(Ex, Pred, Tmp);
+      VisitLValue(Ex, Pred, Tmp);
      
       for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {        
         const GRState* St = GetState(*I);
@@ -1683,7 +1659,7 @@
     case UnaryOperator::Minus:
     case UnaryOperator::Not: {
       
-      assert (!asLVal);
+      assert (!asLValue);
       Expr* Ex = U->getSubExpr()->IgnoreParens();
       NodeSet Tmp;
       Visit(Ex, Pred, Tmp);
@@ -1774,7 +1750,7 @@
   assert (U->isIncrementDecrementOp());
   NodeSet Tmp;
   Expr* Ex = U->getSubExpr()->IgnoreParens();
-  VisitLVal(Ex, Pred, Tmp);
+  VisitLValue(Ex, Pred, Tmp);
   
   for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
     
@@ -1824,7 +1800,7 @@
   }
   
   NodeSet Tmp;
-  VisitLVal(*I, Pred, Tmp);
+  VisitLValue(*I, Pred, Tmp);
   
   ++I;
   
@@ -1994,7 +1970,7 @@
   Expr* RHS = B->getRHS()->IgnoreParens();
   
   if (B->isAssignmentOp())
-    VisitLVal(LHS, Pred, Tmp1);
+    VisitLValue(LHS, Pred, Tmp1);
   else
     Visit(LHS, Pred, Tmp1);
 
@@ -2033,7 +2009,7 @@
           // Simulate the effects of a "store":  bind the value of the RHS
           // to the L-Value represented by the LHS.
           
-          EvalStore(Dst, B, LHS, *I2, SetRVal(St, B, RightV), LeftV, RightV);          
+          EvalStore(Dst, B, LHS, *I2, SetRVal(St, B, RightV), LeftV, RightV);
           continue;
         }
           
diff --git a/lib/Analysis/GRState.cpp b/lib/Analysis/GRState.cpp
index 0b519fc..49bc24a 100644
--- a/lib/Analysis/GRState.cpp
+++ b/lib/Analysis/GRState.cpp
@@ -52,7 +52,7 @@
 
   // Clean up the store.
   DSymbols.clear();
-  NewSt.St = StMgr->RemoveDeadBindings(St->getStore(), Loc, Liveness,
+  NewSt.St = StoreMgr->RemoveDeadBindings(St->getStore(), Loc, Liveness,
                                        RegionRoots, LSymbols, DSymbols);
 
   return ConstraintMgr->RemoveDeadBindings(getPersistentState(NewSt), 
@@ -63,7 +63,7 @@
                                              RVal V) {
   
   Store OldStore = St->getStore();
-  Store NewStore = StMgr->SetRVal(OldStore, LV, V);
+  Store NewStore = StoreMgr->SetRVal(OldStore, LV, V);
   
   if (NewStore == OldStore)
     return St;
@@ -79,10 +79,10 @@
   Store NewStore;
 
   if (Ex)
-    NewStore = StMgr->AddDecl(OldStore, VD, Ex, 
+    NewStore = StoreMgr->AddDecl(OldStore, VD, Ex, 
                               GetRVal(St, Ex), Count);
   else
-    NewStore = StMgr->AddDecl(OldStore, VD, Ex);
+    NewStore = StoreMgr->AddDecl(OldStore, VD, Ex);
                               
   if (NewStore == OldStore)
     return St;
@@ -94,7 +94,7 @@
 
 const GRState* GRStateManager::Unbind(const GRState* St, LVal LV) {
   Store OldStore = St->getStore();
-  Store NewStore = StMgr->Remove(OldStore, LV);
+  Store NewStore = StoreMgr->Remove(OldStore, LV);
   
   if (NewStore == OldStore)
     return St;
@@ -107,7 +107,7 @@
 const GRState* GRStateManager::getInitialState() {
 
   GRState StateImpl(EnvMgr.getInitialEnvironment(), 
-                    StMgr->getInitialStore(),
+                    StoreMgr->getInitialStore(),
                     GDMFactory.GetEmptyMap());
 
   return getPersistentState(StateImpl);
@@ -196,7 +196,7 @@
 void GRStateRef::print(std::ostream& Out, const char* nl, const char* sep)const{
   GRState::Printer **beg = Mgr->Printers.empty() ? 0 : &Mgr->Printers[0];
   GRState::Printer **end = !beg ? 0 : beg + Mgr->Printers.size();  
-  St->print(Out, *Mgr->StMgr, *Mgr->ConstraintMgr, beg, end, nl, sep);
+  St->print(Out, *Mgr->StoreMgr, *Mgr->ConstraintMgr, beg, end, nl, sep);
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/lib/Analysis/RValues.cpp b/lib/Analysis/RValues.cpp
index 337d479..2b57368 100644
--- a/lib/Analysis/RValues.cpp
+++ b/lib/Analysis/RValues.cpp
@@ -270,6 +270,7 @@
 // Utility methods for constructing RVals (both NonLVals and LVals).
 //===----------------------------------------------------------------------===//
 
+// Remove this method?
 RVal RVal::MakeVal(GRStateManager& SMgr, DeclRefExpr* E) {
   
   ValueDecl* D = cast<DeclRefExpr>(E)->getDecl();