Start migration of static analyzer to using the
implicit lvalue-to-rvalue casts that John McCall
recently introduced.  This causes a whole bunch
of logic in the analyzer for handling lvalues
to vanish.  It does, however, raise a few issues
in the analyzer w.r.t to modeling various constructs
(e.g., field accesses to compound literals).

The .c/.m analysis test cases that fail are
due to a missing lvalue-to-rvalue cast that
will get introduced into the AST.  The .cpp
failures were more than I could investigate in
one go, and the patch was already getting huge.
I have XFAILED some of these tests, and they
should obviously be further investigated.

Some highlights of this patch include:

- CFG no longer requires an lvalue bit for
  CFGElements
- StackFrameContext doesn't need an 'asLValue'
  flag
- The "VisitLValue" path from GRExprEngine has
  been eliminated.

Besides the test case failures (XFAILed), there
are surely other bugs that are fallout from
this change.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121960 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp
index efe8fbf..247435f 100644
--- a/lib/Checker/GRExprEngine.cpp
+++ b/lib/Checker/GRExprEngine.cpp
@@ -57,47 +57,6 @@
   return Ctx.Selectors.getSelector(0, &II);
 }
 
-
-static QualType GetCalleeReturnType(const CallExpr *CE) {
-  const Expr *Callee = CE->getCallee();
-  QualType T = Callee->getType();
-  if (const PointerType *PT = T->getAs<PointerType>()) {
-    const FunctionType *FT = PT->getPointeeType()->getAs<FunctionType>();
-    T = FT->getResultType();
-  }
-  else {
-    const BlockPointerType *BT = T->getAs<BlockPointerType>();
-    T = BT->getPointeeType()->getAs<FunctionType>()->getResultType();
-  }
-  return T;
-}
-
-static bool CalleeReturnsReference(const CallExpr *CE) {
-  return (bool) GetCalleeReturnType(CE)->getAs<ReferenceType>();
-}
-
-static bool ReceiverReturnsReference(const ObjCMessageExpr *ME) {
-  const ObjCMethodDecl *MD = ME->getMethodDecl();
-  if (!MD)
-    return false;
-  return MD->getResultType()->getAs<ReferenceType>();
-}
-
-#ifndef NDEBUG
-static bool ReceiverReturnsReferenceOrRecord(const ObjCMessageExpr *ME) {
-  const ObjCMethodDecl *MD = ME->getMethodDecl();
-  if (!MD)
-    return false;
-  QualType T = MD->getResultType();
-  return T->getAs<RecordType>() || T->getAs<ReferenceType>();
-}
-
-static bool CalleeReturnsReferenceOrRecord(const CallExpr *CE) {
-  QualType T = GetCalleeReturnType(CE);
-  return T->getAs<ReferenceType>() || T->getAs<RecordType>();
-}
-#endif
-
 //===----------------------------------------------------------------------===//
 // Checker worklist routines.
 //===----------------------------------------------------------------------===//
@@ -556,7 +515,6 @@
                                   GRStmtNodeBuilder& builder) {
   switch (E.getKind()) {
   case CFGElement::Statement:
-  case CFGElement::StatementAsLValue:
     ProcessStmt(E.getAs<CFGStmt>(), builder);
     break;
   case CFGElement::Initializer:
@@ -648,17 +606,13 @@
   bool HasAutoGenerated = false;
 
   for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
-
     ExplodedNodeSet Dst;
 
     // Set the cleaned state.
     Builder->SetCleanedState(*I == EntryNode ? CleanedState : GetState(*I));
 
     // Visit the statement.
-    if (S.asLValue())
-      VisitLValue(cast<Expr>(CurrentStmt), *I, Dst);
-    else
-      Visit(CurrentStmt, *I, Dst);
+    Visit(CurrentStmt, *I, Dst);
 
     // Do we need to auto-generate a node?  We only need to do this to generate
     // a node with a "cleaned" state; GRCoreEngine will actually handle
@@ -780,7 +734,7 @@
 
   // Expressions to ignore.
   if (const Expr *Ex = dyn_cast<Expr>(S))
-    S = Ex->IgnoreParenLValueCasts();
+    S = Ex->IgnoreParens();
   
   // FIXME: add metadata to the CFG so that we can disable
   //  this check when we KNOW that there is no block-level subexpression.
@@ -880,16 +834,18 @@
       break;
 
     case Stmt::ArraySubscriptExprClass:
-      VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst, false);
+      VisitLvalArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst);
       break;
 
     case Stmt::AsmStmtClass:
       VisitAsmStmt(cast<AsmStmt>(S), Pred, Dst);
       break;
 
-    case Stmt::BlockDeclRefExprClass:
-      VisitBlockDeclRefExpr(cast<BlockDeclRefExpr>(S), Pred, Dst, false);
+    case Stmt::BlockDeclRefExprClass: {
+      const BlockDeclRefExpr *BE = cast<BlockDeclRefExpr>(S);
+      VisitCommonDeclRefExpr(BE, BE->getDecl(), Pred, Dst);
       break;
+    }
 
     case Stmt::BlockExprClass:
       VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);
@@ -897,7 +853,6 @@
 
     case Stmt::BinaryOperatorClass: {
       const BinaryOperator* B = cast<BinaryOperator>(S);
-
       if (B->isLogicalOp()) {
         VisitLogicalExpr(B, Pred, Dst);
         break;
@@ -911,18 +866,18 @@
       if (AMgr.shouldEagerlyAssume() &&
           (B->isRelationalOp() || B->isEqualityOp())) {
         ExplodedNodeSet Tmp;
-        VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp, false);
+        VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
         evalEagerlyAssume(Dst, Tmp, cast<Expr>(S));
       }
       else
-        VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst, false);
+        VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
 
       break;
     }
 
     case Stmt::CallExprClass: {
       const CallExpr* C = cast<CallExpr>(S);
-      VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst, false);
+      VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst);
       break;
     }
 
@@ -930,7 +885,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, false);
+      VisitCXXConstructExpr(C, 0, Pred, Dst);
       break;
     }
 
@@ -967,11 +922,11 @@
     }
 
     case Stmt::CompoundAssignOperatorClass:
-      VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst, false);
+      VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
       break;
 
     case Stmt::CompoundLiteralExprClass:
-      VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst, false);
+      VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst);
       break;
 
     case Stmt::ConditionalOperatorClass: { // '?' operator
@@ -984,9 +939,11 @@
       VisitCXXThisExpr(cast<CXXThisExpr>(S), Pred, Dst);
       break;
 
-    case Stmt::DeclRefExprClass:
-      VisitDeclRefExpr(cast<DeclRefExpr>(S), Pred, Dst, false);
+    case Stmt::DeclRefExprClass: {
+      const DeclRefExpr *DE = cast<DeclRefExpr>(S);
+      VisitCommonDeclRefExpr(DE, DE->getDecl(), Pred, Dst);
       break;
+    }
 
     case Stmt::DeclStmtClass:
       VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
@@ -1006,7 +963,7 @@
     case Stmt::CXXConstCastExprClass:
     case Stmt::CXXFunctionalCastExprClass: {
       const CastExpr* C = cast<CastExpr>(S);
-      VisitCast(C, C->getSubExpr(), Pred, Dst, false);
+      VisitCast(C, C->getSubExpr(), Pred, Dst);
       break;
     }
 
@@ -1021,11 +978,10 @@
       break;
 
     case Stmt::MemberExprClass:
-      VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst, false);
+      VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst);
       break;
-
     case Stmt::ObjCIvarRefExprClass:
-      VisitObjCIvarRefExpr(cast<ObjCIvarRefExpr>(S), Pred, Dst, false);
+      VisitLvalObjCIvarRefExpr(cast<ObjCIvarRefExpr>(S), Pred, Dst);
       break;
 
     case Stmt::ObjCForCollectionStmtClass:
@@ -1033,7 +989,7 @@
       break;
 
     case Stmt::ObjCMessageExprClass:
-      VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), Pred, Dst, false);
+      VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), Pred, Dst);
       break;
 
     case Stmt::ObjCAtThrowStmtClass: {
@@ -1078,9 +1034,12 @@
       break;
     }
 
-    case Stmt::StringLiteralClass:
-      VisitLValue(cast<StringLiteral>(S), Pred, Dst);
-      break;
+    case Stmt::StringLiteralClass: {
+      const GRState* state = GetState(Pred);
+      SVal V = state->getLValue(cast<StringLiteral>(S));
+      MakeNode(Dst, S, Pred, state->BindExpr(S, V));
+      return;
+    }
 
     case Stmt::SwitchStmtClass:
       // This case isn't for branch processing, but for handling the
@@ -1092,11 +1051,11 @@
       const UnaryOperator *U = cast<UnaryOperator>(S);
       if (AMgr.shouldEagerlyAssume()&&(U->getOpcode() == UO_LNot)) {
         ExplodedNodeSet Tmp;
-        VisitUnaryOperator(U, Pred, Tmp, false);
+        VisitUnaryOperator(U, Pred, Tmp);
         evalEagerlyAssume(Dst, Tmp, U);
       }
       else
-        VisitUnaryOperator(U, Pred, Dst, false);
+        VisitUnaryOperator(U, Pred, Dst);
       break;
     }
 
@@ -1108,171 +1067,6 @@
   }
 }
 
-void GRExprEngine::VisitLValue(const Expr* Ex, ExplodedNode* Pred,
-                               ExplodedNodeSet& Dst) {
-
-  PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
-                                Ex->getLocStart(),
-                                "Error evaluating statement");
-
-  // Expressions to ignore.
-  Ex = Ex->IgnoreParenLValueCasts();
-
-  if (Ex != CurrentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(Ex)){
-    Dst.Add(Pred);
-    return;
-  }
-
-  switch (Ex->getStmtClass()) {
-    // C++ stuff we don't support yet.
-    case Stmt::CXXMemberCallExprClass:
-    case Stmt::CXXScalarValueInitExprClass: {
-      SaveAndRestore<bool> OldSink(Builder->BuildSinks);
-      Builder->BuildSinks = true;
-      MakeNode(Dst, Ex, Pred, GetState(Pred));
-      break;
-    }
-
-    case Stmt::ArraySubscriptExprClass:
-      VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(Ex), Pred, Dst, true);
-      return;
-
-    case Stmt::BinaryOperatorClass:
-    case Stmt::CompoundAssignOperatorClass:
-      VisitBinaryOperator(cast<BinaryOperator>(Ex), Pred, Dst, true);
-      return;
-
-    case Stmt::BlockDeclRefExprClass:
-      VisitBlockDeclRefExpr(cast<BlockDeclRefExpr>(Ex), Pred, Dst, true);
-      return;
-
-    case Stmt::CallExprClass:
-    case Stmt::CXXOperatorCallExprClass: {
-      const CallExpr *C = cast<CallExpr>(Ex);
-      assert(CalleeReturnsReferenceOrRecord(C));
-      VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst, true);
-      break;
-    }
-
-    case Stmt::ExprWithCleanupsClass: {
-      const ExprWithCleanups *expr = cast<ExprWithCleanups>(Ex);
-      VisitLValue(expr->getSubExpr(), Pred, Dst);
-      break;
-    }
-
-    case Stmt::CXXBindTemporaryExprClass: {
-      const CXXBindTemporaryExpr *expr = cast<CXXBindTemporaryExpr>(Ex);
-      VisitLValue(expr->getSubExpr(), Pred, Dst);
-      break;
-    }
-
-    case Stmt::CXXConstructExprClass: {
-      const CXXConstructExpr *expr = cast<CXXConstructExpr>(Ex);
-      VisitCXXConstructExpr(expr, 0, Pred, Dst, true);
-      break;
-    }
-
-    case Stmt::CXXFunctionalCastExprClass: {
-      const CXXFunctionalCastExpr *expr = cast<CXXFunctionalCastExpr>(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;
-
-    case Stmt::DeclRefExprClass:
-      VisitDeclRefExpr(cast<DeclRefExpr>(Ex), Pred, Dst, true);
-      return;
-
-    case Stmt::ImplicitCastExprClass:
-    case Stmt::CStyleCastExprClass: {
-      const CastExpr *C = cast<CastExpr>(Ex);
-      QualType T = Ex->getType();
-      VisitCast(C, C->getSubExpr(), Pred, Dst, true);
-      break;
-    }
-
-    case Stmt::MemberExprClass:
-      VisitMemberExpr(cast<MemberExpr>(Ex), Pred, Dst, true);
-      return;
-
-    case Stmt::ObjCIvarRefExprClass:
-      VisitObjCIvarRefExpr(cast<ObjCIvarRefExpr>(Ex), Pred, Dst, true);
-      return;
-
-    case Stmt::ObjCMessageExprClass: {
-      const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(Ex);
-      assert(ReceiverReturnsReferenceOrRecord(ME));
-      VisitObjCMessageExpr(ME, Pred, Dst, true);
-      return;
-    }
-
-    case Stmt::ObjCIsaExprClass:
-      // FIXME: Do something more intelligent with 'x->isa = ...'.
-      //  For now, just ignore the assignment.
-      return;
-
-    case Stmt::ObjCPropertyRefExprClass:
-      // FIXME: Property assignments are lvalues, but not really "locations".
-      //  e.g.:  self.x = something;
-      //  Here the "self.x" really can translate to a method call (setter) when
-      //  the assignment is made.  Moreover, the entire assignment expression
-      //  evaluate to whatever "something" is, not calling the "getter" for
-      //  the property (which would make sense since it can have side effects).
-      //  We'll probably treat this as a location, but not one that we can
-      //  take the address of.  Perhaps we need a new SVal class for cases
-      //  like thsis?
-      //  Note that we have a similar problem for bitfields, since they don't
-      //  have "locations" in the sense that we can take their address.
-      Dst.Add(Pred);
-      return;
-
-    case Stmt::StringLiteralClass: {
-      const GRState* state = GetState(Pred);
-      SVal V = state->getLValue(cast<StringLiteral>(Ex));
-      MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V));
-      return;
-    }
-
-    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::CXXBoolLiteralExprClass:
-    case Stmt::IntegerLiteralClass:
-    case Stmt::CharacterLiteralClass:
-    case Stmt::FloatingLiteralClass:
-    case Stmt::ImaginaryLiteralClass:
-      CreateCXXTemporaryObject(Ex, Pred, Dst);
-      return;
-
-    default: {
-      // Arbitrary subexpressions can return aggregate temporaries that
-      // can be used in a lvalue context.  We need to enhance our support
-      // of such temporaries in both the environment and the store, so right
-      // now we just do a regular visit.
-
-      // NOTE: Do not use 'isAggregateType()' here as CXXRecordDecls that
-      //  are non-pod are not aggregates.
-      assert ((Ex->getType()->isRecordType() ||
-               Ex->getType()->isArrayType()) &&
-              "Other kinds of expressions with non-aggregate/union/class types"
-              " do not have lvalues.");
-
-      Visit(Ex, Pred, Dst);
-    }
-  }
-}
-
 //===----------------------------------------------------------------------===//
 // Block entrance.  (Update counters).
 //===----------------------------------------------------------------------===//
@@ -1769,86 +1563,59 @@
   CheckerVisit(BE, Dst, Tmp, PostVisitStmtCallback);
 }
 
-void GRExprEngine::VisitDeclRefExpr(const DeclRefExpr *Ex, ExplodedNode *Pred,
-                                    ExplodedNodeSet &Dst, bool asLValue) {
-  VisitCommonDeclRefExpr(Ex, Ex->getDecl(), Pred, Dst, asLValue);
-}
-
-void GRExprEngine::VisitBlockDeclRefExpr(const BlockDeclRefExpr *Ex,
-                                         ExplodedNode *Pred,
-                                    ExplodedNodeSet &Dst, bool asLValue) {
-  VisitCommonDeclRefExpr(Ex, Ex->getDecl(), Pred, Dst, asLValue);
-}
-
 void GRExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
                                           ExplodedNode *Pred,
-                                          ExplodedNodeSet &Dst, bool asLValue) {
-
+                                          ExplodedNodeSet &Dst) {
   const GRState *state = GetState(Pred);
 
   if (const VarDecl* VD = dyn_cast<VarDecl>(D)) {
-
+    assert(Ex->isLValue());
     SVal V = state->getLValue(VD, Pred->getLocationContext());
 
-    if (asLValue) {
-      // For references, the 'lvalue' is the pointer address stored in the
-      // reference region.
-      if (VD->getType()->isReferenceType()) {
-        if (const MemRegion *R = V.getAsRegion())
-          V = state->getSVal(R);
-        else
-          V = UnknownVal();
-      }
-
-      MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V),
-               ProgramPoint::PostLValueKind);
+    // For references, the 'lvalue' is the pointer address stored in the
+    // reference region.
+    if (VD->getType()->isReferenceType()) {
+      if (const MemRegion *R = V.getAsRegion())
+        V = state->getSVal(R);
+      else
+        V = UnknownVal();
     }
-    else
-      evalLoad(Dst, Ex, Pred, state, V);
 
+    MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V),
+             ProgramPoint::PostLValueKind);
     return;
-  } else if (const EnumConstantDecl* ED = dyn_cast<EnumConstantDecl>(D)) {
-    assert(!asLValue && "EnumConstantDecl does not have lvalue.");
-
+  }
+  if (const EnumConstantDecl* ED = dyn_cast<EnumConstantDecl>(D)) {
+    assert(!Ex->isLValue());
     SVal V = svalBuilder.makeIntVal(ED->getInitVal());
     MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V));
     return;
-
-  } else if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {
-    // This code is valid regardless of the value of 'isLValue'.
+  }
+  if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {
     SVal V = svalBuilder.getFunctionPointer(FD);
     MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V),
              ProgramPoint::PostLValueKind);
     return;
   }
-
   assert (false &&
           "ValueDecl support for this ValueDecl not implemented.");
 }
 
 /// VisitArraySubscriptExpr - Transfer function for array accesses
-void GRExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr* A,
-                                           ExplodedNode* Pred,
-                                           ExplodedNodeSet& Dst, bool asLValue){
+void GRExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr* A,
+                                               ExplodedNode* Pred,
+                                               ExplodedNodeSet& Dst){
 
   const Expr* Base = A->getBase()->IgnoreParens();
   const Expr* Idx  = A->getIdx()->IgnoreParens();
+  
+  // Evaluate the base.
   ExplodedNodeSet Tmp;
-
-  if (Base->getType()->isVectorType()) {
-    // For vector types get its lvalue.
-    // FIXME: This may not be correct.  Is the rvalue of a vector its location?
-    //  In fact, I think this is just a hack.  We need to get the right
-    // semantics.
-    VisitLValue(Base, Pred, Tmp);
-  }
-  else
-    Visit(Base, Pred, Tmp);   // Get Base's rvalue, which should be an LocVal.
+  Visit(Base, Pred, Tmp);
 
   for (ExplodedNodeSet::iterator I1=Tmp.begin(), E1=Tmp.end(); I1!=E1; ++I1) {
     ExplodedNodeSet Tmp2;
     Visit(Idx, *I1, Tmp2);     // Evaluate the index.
-
     ExplodedNodeSet Tmp3;
     CheckerVisit(A, Tmp3, Tmp2, PreVisitStmtCallback);
 
@@ -1856,40 +1623,41 @@
       const GRState* state = GetState(*I2);
       SVal V = state->getLValue(A->getType(), state->getSVal(Idx),
                                 state->getSVal(Base));
-
-      if (asLValue)
-        MakeNode(Dst, A, *I2, state->BindExpr(A, V),
-                 ProgramPoint::PostLValueKind);
-      else
-        evalLoad(Dst, A, *I2, state, V);
+      assert(A->isLValue());
+      MakeNode(Dst, A, *I2, state->BindExpr(A, V), ProgramPoint::PostLValueKind);
     }
   }
 }
 
 /// VisitMemberExpr - Transfer function for member expressions.
 void GRExprEngine::VisitMemberExpr(const MemberExpr* M, ExplodedNode* Pred,
-                                   ExplodedNodeSet& Dst, bool asLValue) {
+                                    ExplodedNodeSet& Dst) {
 
-  Expr* Base = M->getBase()->IgnoreParens();
-  ExplodedNodeSet Tmp;
+  Expr *baseExpr = M->getBase()->IgnoreParens();
+  ExplodedNodeSet dstBase;
+  Visit(baseExpr, Pred, dstBase);
 
-  if (M->isArrow())
-    Visit(Base, Pred, Tmp);        // p->f = ...  or   ... = p->f
-  else
-    VisitLValue(Base, Pred, Tmp);  // x.f = ...   or   ... = x.f
-
-  FieldDecl *Field = dyn_cast<FieldDecl>(M->getMemberDecl());
-  if (!Field) // FIXME: skipping member expressions for non-fields
+  FieldDecl *field = dyn_cast<FieldDecl>(M->getMemberDecl());
+  if (!field) // FIXME: skipping member expressions for non-fields
     return;
 
-  for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
+  for (ExplodedNodeSet::iterator I = dstBase.begin(), E = dstBase.end();
+    I != E; ++I) {
     const GRState* state = GetState(*I);
+    SVal baseExprVal = state->getSVal(baseExpr);
+    if (isa<nonloc::LazyCompoundVal>(baseExprVal) ||
+        isa<nonloc::CompoundVal>(baseExprVal)) {
+      MakeNode(Dst, M, *I, state->BindExpr(M, UnknownVal()));
+      continue;
+    }
+
     // FIXME: Should we insert some assumption logic in here to determine
     // if "Base" is a valid piece of memory?  Before we put this assumption
     // later when using FieldOffset lvals (which we no longer have).
-    SVal L = state->getLValue(Field, state->getSVal(Base));
 
-    if (asLValue)
+    // For all other cases, compute an lvalue.    
+    SVal L = state->getLValue(field, baseExprVal);
+    if (M->isLValue())
       MakeNode(Dst, M, *I, state->BindExpr(M, L), ProgramPoint::PostLValueKind);
     else
       evalLoad(Dst, M, *I, state, L);
@@ -2111,7 +1879,7 @@
     const StackFrameContext *stackFrame = 
       AMgr.getStackFrame(AMgr.getAnalysisContext(FD), 
                          Pred->getLocationContext(),
-                         CE, false, Builder->getBlock(), Builder->getIndex());
+                         CE, Builder->getBlock(), Builder->getIndex());
     // Now we have the definition of the callee, create a CallEnter node.
     CallEnter Loc(CE, stackFrame, Pred->getLocationContext());
 
@@ -2127,7 +1895,7 @@
       return false;
     const StackFrameContext *stackFrame = 
       AMgr.getStackFrame(C, Pred->getLocationContext(),
-                         CE, false, Builder->getBlock(), Builder->getIndex());
+                         CE, Builder->getBlock(), Builder->getIndex());
     CallEnter Loc(CE, stackFrame, Pred->getLocationContext());
     ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
     Dst.Add(N);
@@ -2140,7 +1908,7 @@
 void GRExprEngine::VisitCall(const CallExpr* CE, ExplodedNode* Pred,
                              CallExpr::const_arg_iterator AI,
                              CallExpr::const_arg_iterator AE,
-                             ExplodedNodeSet& Dst, bool asLValue) {
+                             ExplodedNodeSet& Dst) {
 
   // Determine the type of function we're calling (if available).
   const FunctionProtoType *Proto = NULL;
@@ -2213,29 +1981,7 @@
 
   // Finally, perform the post-condition check of the CallExpr and store
   // the created nodes in 'Dst'.
-  // If the callee returns a reference and we want an rvalue, skip this check
-  // and do the load.
-  if (!(!asLValue && CalleeReturnsReference(CE))) {
-    CheckerVisit(CE, Dst, DstTmp3, PostVisitStmtCallback);
-    return;
-  }
-
-  // Handle the case where the called function returns a reference but
-  // we expect an rvalue.  For such cases, convert the reference to
-  // an rvalue.
-  // FIXME: This conversion doesn't actually happen unless the result
-  //  of CallExpr is consumed by another expression.
-  ExplodedNodeSet DstTmp4;
-  CheckerVisit(CE, DstTmp4, DstTmp3, PostVisitStmtCallback);
-  QualType LoadTy = CE->getType();
-
-  static int *ConvertToRvalueTag = 0;
-  for (ExplodedNodeSet::iterator NI = DstTmp4.begin(), NE = DstTmp4.end();
-       NI!=NE; ++NI) {
-    const GRState *state = GetState(*NI);
-    evalLoad(Dst, CE, *NI, state, state->getSVal(CE),
-             &ConvertToRvalueTag, LoadTy);
-  }
+  CheckerVisit(CE, Dst, DstTmp3, PostVisitStmtCallback);
 }
 
 //===----------------------------------------------------------------------===//
@@ -2306,23 +2052,24 @@
 // Transfer function: Objective-C ivar references.
 //===----------------------------------------------------------------------===//
 
-void GRExprEngine::VisitObjCIvarRefExpr(const ObjCIvarRefExpr* Ex, 
-                                        ExplodedNode* Pred,
-                                        ExplodedNodeSet& Dst, bool asLValue) {
+void GRExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr* Ex, 
+                                            ExplodedNode* Pred,
+                                            ExplodedNodeSet& Dst) {
 
-  const Expr* Base = cast<Expr>(Ex->getBase());
-  ExplodedNodeSet Tmp;
-  Visit(Base, Pred, Tmp);
+  // Visit the base expression, which is needed for computing the lvalue
+  // of the ivar.
+  ExplodedNodeSet dstBase;
+  const Expr *baseExpr = Ex->getBase();
+  Visit(baseExpr, Pred, dstBase);
 
-  for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
-    const GRState* state = GetState(*I);
-    SVal BaseVal = state->getSVal(Base);
-    SVal location = state->getLValue(Ex->getDecl(), BaseVal);
-
-    if (asLValue)
-      MakeNode(Dst, Ex, *I, state->BindExpr(Ex, location));
-    else
-      evalLoad(Dst, Ex, *I, state, location);
+  // Using the base, compute the lvalue of the instance variable.
+  for (ExplodedNodeSet::iterator I = dstBase.begin(), E = dstBase.end();
+       I!=E; ++I) {
+    ExplodedNode *nodeBase = *I;
+    const GRState *state = GetState(nodeBase);
+    SVal baseVal = state->getSVal(baseExpr);
+    SVal location = state->getLValue(Ex->getDecl(), baseVal);
+    MakeNode(Dst, Ex, *I, state->BindExpr(Ex, location));
   }
 }
 
@@ -2370,8 +2117,7 @@
   }
 
   ExplodedNodeSet Tmp;
-  VisitLValue(cast<Expr>(elem), Pred, Tmp);
-
+  Visit(cast<Expr>(elem), Pred, Tmp);
   for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
     const GRState* state = GetState(*I);
     VisitObjCForCollectionStmtAux(S, *I, Dst, state->getSVal(elem));
@@ -2442,7 +2188,7 @@
 
 void GRExprEngine::VisitObjCMessageExpr(const ObjCMessageExpr* ME, 
                                         ExplodedNode* Pred,
-                                        ExplodedNodeSet& Dst, bool asLValue){
+                                        ExplodedNodeSet& Dst){
 
   // Create a worklist to process both the arguments.
   llvm::SmallVector<ObjCMsgWLItem, 20> WL;
@@ -2589,27 +2335,7 @@
 
   // Finally, perform the post-condition check of the ObjCMessageExpr and store
   // the created nodes in 'Dst'.
-  if (!(!asLValue && ReceiverReturnsReference(ME))) {
-    CheckerVisit(ME, Dst, dstEval, PostVisitStmtCallback);
-    return;
-  }
-
-  // Handle the case where the message expression returns a reference but
-  // we expect an rvalue.  For such cases, convert the reference to
-  // an rvalue.
-  // FIXME: This conversion doesn't actually happen unless the result
-  //  of ObjCMessageExpr is consumed by another expression.
-  ExplodedNodeSet DstRValueConvert;
-  CheckerVisit(ME, DstRValueConvert, dstEval, PostVisitStmtCallback);
-  QualType LoadTy = ME->getType();
-
-  static int *ConvertToRvalueTag = 0;
-  for (ExplodedNodeSet::iterator NI = DstRValueConvert.begin(),
-       NE = DstRValueConvert.end(); NI != NE; ++NI) {
-    const GRState *state = GetState(*NI);
-    evalLoad(Dst, ME, *NI, state, state->getSVal(ME),
-             &ConvertToRvalueTag, LoadTy);
-  }
+  CheckerVisit(ME, Dst, dstEval, PostVisitStmtCallback);
 }
 
 //===----------------------------------------------------------------------===//
@@ -2617,24 +2343,30 @@
 //===----------------------------------------------------------------------===//
 
 void GRExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, 
-                             ExplodedNode *Pred, ExplodedNodeSet &Dst, 
-                             bool asLValue) {
+                             ExplodedNode *Pred, ExplodedNodeSet &Dst) {
+  
   ExplodedNodeSet S1;
+  Visit(Ex, Pred, S1);
+  ExplodedNodeSet S2;
+  CheckerVisit(CastE, S2, S1, PreVisitStmtCallback);
+  
+  if (CastE->getCastKind() == CK_LValueToRValue) {
+    for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I!=E; ++I) {
+      ExplodedNode *subExprNode = *I;
+      const GRState *state = GetState(subExprNode);
+      evalLoad(Dst, CastE, subExprNode, state, state->getSVal(Ex));
+    }
+    return;
+  }
+  
+  // All other casts.  
   QualType T = CastE->getType();
   QualType ExTy = Ex->getType();
 
   if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE))
     T = ExCast->getTypeAsWritten();
-
-  if (ExTy->isArrayType() || ExTy->isFunctionType() || T->isReferenceType() ||
-      asLValue)
-    VisitLValue(Ex, Pred, S1);
-  else
-    Visit(Ex, Pred, S1);
-
-  ExplodedNodeSet S2;
-  CheckerVisit(CastE, S2, S1, PreVisitStmtCallback);
-
+ 
+#if 0
   // If we are evaluating the cast in an lvalue context, we implicitly want
   // the cast to evaluate to a location.
   if (asLValue) {
@@ -2642,10 +2374,10 @@
     T = Ctx.getPointerType(Ctx.getCanonicalType(T));
     ExTy = Ctx.getPointerType(Ctx.getCanonicalType(ExTy));
   }
+#endif
 
   switch (CastE->getCastKind()) {
   case CK_ToVoid:
-    assert(!asLValue);
     for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I)
       Dst.Add(*I);
     return;
@@ -2738,8 +2470,7 @@
 
 void GRExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr* CL,
                                             ExplodedNode* Pred,
-                                            ExplodedNodeSet& Dst,
-                                            bool asLValue) {
+                                            ExplodedNodeSet& Dst) {
   const InitListExpr* ILE 
     = cast<InitListExpr>(CL->getInitializer()->IgnoreParens());
   ExplodedNodeSet Tmp;
@@ -2751,7 +2482,7 @@
     const LocationContext *LC = (*I)->getLocationContext();
     state = state->bindCompoundLiteral(CL, LC, ILV);
 
-    if (asLValue) {
+    if (CL->isLValue()) {
       MakeNode(Dst, CL, *I, state->BindExpr(CL, state->getLValue(CL, LC)));
     }
     else
@@ -2775,12 +2506,8 @@
   //  time a function is called those values may not be current.
   ExplodedNodeSet Tmp;
 
-  if (InitEx) {
-    if (VD->getType()->isReferenceType())
-      VisitLValue(InitEx, Pred, Tmp);
-    else
-      Visit(InitEx, Pred, Tmp);
-  }
+  if (InitEx)
+    Visit(InitEx, Pred, Tmp);
   else
     Tmp.Add(Pred);
 
@@ -2962,7 +2689,7 @@
       // First, visit the sub-expression to find its region.
       const Expr *Arg = Ex->getArgumentExpr();
       ExplodedNodeSet Tmp;
-      VisitLValue(Arg, Pred, Tmp);
+      Visit(Arg, Pred, Tmp);
 
       for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
         const GRState* state = GetState(*I);
@@ -3020,36 +2747,14 @@
 
 void GRExprEngine::VisitUnaryOperator(const UnaryOperator* U, 
                                       ExplodedNode* Pred,
-                                      ExplodedNodeSet& Dst, bool asLValue) {
+                                      ExplodedNodeSet& Dst) {
 
   switch (U->getOpcode()) {
 
     default:
       break;
 
-    case UO_Deref: {
-
-      const Expr* Ex = U->getSubExpr()->IgnoreParens();
-      ExplodedNodeSet Tmp;
-      Visit(Ex, Pred, Tmp);
-
-      for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
-
-        const GRState* state = GetState(*I);
-        SVal location = state->getSVal(Ex);
-
-        if (asLValue)
-          MakeNode(Dst, U, *I, state->BindExpr(U, location),
-                   ProgramPoint::PostLValueKind);
-        else
-          evalLoad(Dst, U, *I, state, location);
-      }
-
-      return;
-    }
-
     case UO_Real: {
-
       const Expr* Ex = U->getSubExpr()->IgnoreParens();
       ExplodedNodeSet Tmp;
       Visit(Ex, Pred, Tmp);
@@ -3095,7 +2800,10 @@
       return;
     }
       
-    case UO_Plus: assert(!asLValue);  // FALL-THROUGH.
+    case UO_Plus:
+      assert(!U->isLValue());
+      // FALL-THROUGH.
+    case UO_Deref:
     case UO_Extension: {
 
       // Unary "+" is a no-op, similar to a parentheses.  We still have places
@@ -3105,11 +2813,7 @@
 
       const Expr* Ex = U->getSubExpr()->IgnoreParens();
       ExplodedNodeSet Tmp;
-
-      if (asLValue)
-        VisitLValue(Ex, Pred, Tmp);
-      else
-        Visit(Ex, Pred, Tmp);
+      Visit(Ex, Pred, Tmp);
 
       for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
         const GRState* state = GetState(*I);
@@ -3120,27 +2824,23 @@
     }
 
     case UO_AddrOf: {
-
-      assert(!asLValue);
+      assert(!U->isLValue());
       const Expr* Ex = U->getSubExpr()->IgnoreParens();
       ExplodedNodeSet Tmp;
-      VisitLValue(Ex, Pred, Tmp);
-
+      Visit(Ex, Pred, Tmp);
       for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
         const GRState* state = GetState(*I);
         SVal V = state->getSVal(Ex);
         state = state->BindExpr(U, V);
         MakeNode(Dst, U, *I, state);
       }
-
       return;
     }
 
     case UO_LNot:
     case UO_Minus:
     case UO_Not: {
-
-      assert (!asLValue);
+      assert (!U->isLValue());
       const Expr* Ex = U->getSubExpr()->IgnoreParens();
       ExplodedNodeSet Tmp;
       Visit(Ex, Pred, Tmp);
@@ -3214,11 +2914,10 @@
   }
 
   // Handle ++ and -- (both pre- and post-increment).
-
   assert (U->isIncrementDecrementOp());
   ExplodedNodeSet Tmp;
   const Expr* Ex = U->getSubExpr()->IgnoreParens();
-  VisitLValue(Ex, Pred, Tmp);
+  Visit(Ex, Pred, Tmp);
 
   for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
 
@@ -3307,8 +3006,7 @@
   }
 
   ExplodedNodeSet Tmp;
-  VisitLValue(*I, Pred, Tmp);
-
+  Visit(*I, Pred, Tmp);
   ++I;
 
   for (ExplodedNodeSet::iterator NI = Tmp.begin(), NE = Tmp.end();NI != NE;++NI)
@@ -3404,17 +3102,12 @@
 
 void GRExprEngine::VisitBinaryOperator(const BinaryOperator* B,
                                        ExplodedNode* Pred,
-                                       ExplodedNodeSet& Dst, bool asLValue) {
-
+                                       ExplodedNodeSet& Dst) {
   ExplodedNodeSet Tmp1;
   Expr* LHS = B->getLHS()->IgnoreParens();
   Expr* RHS = B->getRHS()->IgnoreParens();
 
-  if (B->isAssignmentOp())
-    VisitLValue(LHS, Pred, Tmp1);
-  else
-    Visit(LHS, Pred, Tmp1);
-
+  Visit(LHS, Pred, Tmp1);
   ExplodedNodeSet Tmp3;
 
   for (ExplodedNodeSet::iterator I1=Tmp1.begin(), E1=Tmp1.end(); I1!=E1; ++I1) {
@@ -3446,7 +3139,7 @@
           RightV = svalBuilder.getConjuredSymbolVal(NULL, B->getRHS(), Count);
         }
 
-        SVal ExprVal = asLValue ? LeftV : RightV;
+        SVal ExprVal = B->isLValue() ? LeftV : RightV;
 
         // Simulate the effects of a "store":  bind the value of the RHS
         // to the L-Value represented by the LHS.