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.

llvm-svn: 121960
diff --git a/clang/lib/Analysis/AnalysisContext.cpp b/clang/lib/Analysis/AnalysisContext.cpp
index 5307074..4305507 100644
--- a/clang/lib/Analysis/AnalysisContext.cpp
+++ b/clang/lib/Analysis/AnalysisContext.cpp
@@ -152,8 +152,7 @@
 }
 
 void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
-  Profile(ID, getAnalysisContext(), getParent(), CallSite.getPointer(),
-          CallSite.getInt(), Block, Index);
+  Profile(ID, getAnalysisContext(), getParent(), CallSite, Block, Index);
 }
 
 void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) {
@@ -189,15 +188,15 @@
 const StackFrameContext*
 LocationContextManager::getStackFrame(AnalysisContext *ctx,
                                       const LocationContext *parent,
-                                      const Stmt *s, bool asLValue,
+                                      const Stmt *s,
                                       const CFGBlock *blk, unsigned idx) {
   llvm::FoldingSetNodeID ID;
-  StackFrameContext::Profile(ID, ctx, parent, s, asLValue, blk, idx);
+  StackFrameContext::Profile(ID, ctx, parent, s, blk, idx);
   void *InsertPos;
   StackFrameContext *L =
    cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
   if (!L) {
-    L = new StackFrameContext(ctx, parent, s, asLValue, blk, idx);
+    L = new StackFrameContext(ctx, parent, s, blk, idx);
     Contexts.InsertNode(L, InsertPos);
   }
   return L;
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 35d9386..0f32614 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -32,7 +32,6 @@
   if (VarDecl* VD = dyn_cast<VarDecl>(D))
     if (Expr* Ex = VD->getInit())
       return Ex->getSourceRange().getEnd();
-
   return D->getLocation();
 }
 
@@ -49,22 +48,13 @@
 ///  the builder has an option not to add a subexpression as a
 ///  block-level expression.
 ///
-///  The lvalue bit captures whether or not a subexpression needs to
-///  be processed as an lvalue.  That information needs to be recorded
-///  in the CFG for block-level expressions so that analyses do the
-///  right thing when traversing the CFG (since such subexpressions
-///  will be seen before their parent expression is processed).
 class AddStmtChoice {
 public:
-  enum Kind { NotAlwaysAdd = 0,
-              AlwaysAdd = 1,
-              AsLValueNotAlwaysAdd = 2,
-              AsLValueAlwaysAdd = 3 };
+  enum Kind { NotAlwaysAdd = 0, AlwaysAdd = 1 };
 
   AddStmtChoice(Kind a_kind = NotAlwaysAdd) : kind(a_kind) {}
 
   bool alwaysAdd() const { return kind & AlwaysAdd; }
-  bool asLValue() const { return kind >= AsLValueNotAlwaysAdd; }
 
   /// Return a copy of this object, except with the 'always-add' bit
   ///  set as specified.
@@ -73,13 +63,6 @@
                                      Kind(kind & ~AlwaysAdd));
   }
 
-  /// Return a copy of this object, except with the 'as-lvalue' bit
-  ///  set as specified.
-  AddStmtChoice withAsLValue(bool asLVal) const {
-    return AddStmtChoice(asLVal ? Kind(kind | AsLValueNotAlwaysAdd) :
-                                  Kind(kind & ~AsLValueNotAlwaysAdd));
-  }
-
 private:
   Kind kind;
 };
@@ -372,9 +355,9 @@
   void addLocalScopeAndDtors(Stmt* S);
 
   // Interface to CFGBlock - adding CFGElements.
-  void AppendStmt(CFGBlock *B, Stmt *S,
+  void appendStmt(CFGBlock *B, Stmt *S,
                   AddStmtChoice asc = AddStmtChoice::AlwaysAdd) {
-    B->appendStmt(S, cfg->getBumpVectorContext(), asc.asLValue());
+    B->appendStmt(S, cfg->getBumpVectorContext());
   }
   void appendInitializer(CFGBlock *B, CXXBaseOrMemberInitializer *I) {
     B->appendInitializer(I, cfg->getBumpVectorContext());
@@ -568,12 +551,12 @@
   appendInitializer(Block, I);
 
   if (Init) {
-    AddStmtChoice asc = AddStmtChoice().withAsLValue(IsReference);
-    if (HasTemporaries)
+    if (HasTemporaries) {
       // For expression with temporaries go directly to subexpression to omit
       // generating destructors for the second time.
-      return Visit(cast<ExprWithCleanups>(Init)->getSubExpr(), asc);
-    return Visit(Init, asc);
+      return Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
+    }
+    return Visit(Init);
   }
 
   return Block;
@@ -825,16 +808,6 @@
 
     case Stmt::ContinueStmtClass:
       return VisitContinueStmt(cast<ContinueStmt>(S));
-    
-    case Stmt::CStyleCastExprClass: {
-      CastExpr *castExpr = cast<CastExpr>(S);
-      if (castExpr->getCastKind() == CK_LValueToRValue) {
-        // temporary workaround
-        S = castExpr->getSubExpr();
-        goto tryAgain;
-      }
-      return VisitStmt(S, asc);
-    }
 
     case Stmt::CXXCatchStmtClass:
       return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
@@ -881,15 +854,8 @@
     case Stmt::IfStmtClass:
       return VisitIfStmt(cast<IfStmt>(S));
 
-    case Stmt::ImplicitCastExprClass: {
-      ImplicitCastExpr *castExpr = cast<ImplicitCastExpr>(S);
-      if (castExpr->getCastKind() == CK_LValueToRValue) {
-        // temporary workaround
-        S = castExpr->getSubExpr();
-        goto tryAgain;
-      }
-      return VisitImplicitCastExpr(castExpr, asc);
-    }
+    case Stmt::ImplicitCastExprClass:
+      return VisitImplicitCastExpr(cast<ImplicitCastExpr>(S), asc);
 
     case Stmt::IndirectGotoStmtClass:
       return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
@@ -945,7 +911,7 @@
 CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
   if (asc.alwaysAdd()) {
     autoCreateBlock();
-    AppendStmt(Block, S, asc);
+    appendStmt(Block, S, asc);
   }
 
   return VisitChildren(S);
@@ -967,28 +933,27 @@
 
   if (asc.alwaysAdd()) {
     autoCreateBlock();
-    AppendStmt(Block, A, asc);
+    appendStmt(Block, A, asc);
   }
 
   return Block;
 }
 
 CFGBlock *CFGBuilder::VisitUnaryOperator(UnaryOperator *U,
-					 AddStmtChoice asc) {
+           AddStmtChoice asc) {
   if (asc.alwaysAdd()) {
     autoCreateBlock();
-    AppendStmt(Block, U, asc);
+    appendStmt(Block, U, asc);
   }
 
-  bool asLVal = U->isIncrementDecrementOp();
-  return Visit(U->getSubExpr(), AddStmtChoice().withAsLValue(asLVal));
+  return Visit(U->getSubExpr(), AddStmtChoice());
 }
 
 CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
                                           AddStmtChoice asc) {
   if (B->isLogicalOp()) { // && or ||
     CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
-    AppendStmt(ConfluenceBlock, B, asc);
+    appendStmt(ConfluenceBlock, B, asc);
 
     if (badCFG)
       return 0;
@@ -1033,7 +998,7 @@
 
   if (B->getOpcode() == BO_Comma) { // ,
     autoCreateBlock();
-    AppendStmt(Block, B, asc);
+    appendStmt(Block, B, asc);
     addStmt(B->getRHS());
     return addStmt(B->getLHS());
   }
@@ -1041,16 +1006,15 @@
   if (B->isAssignmentOp()) {
     if (asc.alwaysAdd()) {
       autoCreateBlock();
-      AppendStmt(Block, B, asc);
+      appendStmt(Block, B, asc);
     }
-
-    Visit(B->getLHS(), AddStmtChoice::AsLValueNotAlwaysAdd);
+    Visit(B->getLHS());
     return Visit(B->getRHS());
   }
 
   if (asc.alwaysAdd()) {
     autoCreateBlock();
-    AppendStmt(Block, B, asc);
+    appendStmt(Block, B, asc);
   }
 
   CFGBlock *RBlock = Visit(B->getRHS());
@@ -1064,7 +1028,7 @@
 CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) {
   if (asc.alwaysAdd()) {
     autoCreateBlock();
-    AppendStmt(Block, E, asc);
+    appendStmt(Block, E, asc);
   }
   return Block;
 }
@@ -1142,7 +1106,7 @@
   }
 
   Block = createBlock(!NoReturn);
-  AppendStmt(Block, C, asc);
+  appendStmt(Block, C, asc);
 
   if (NoReturn) {
     // Wire this to the exit block directly.
@@ -1162,7 +1126,7 @@
 CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,
                                       AddStmtChoice asc) {
   CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
-  AppendStmt(ConfluenceBlock, C, asc);
+  appendStmt(ConfluenceBlock, C, asc);
   if (badCFG)
     return 0;
 
@@ -1212,7 +1176,7 @@
   // Create the confluence block that will "merge" the results of the ternary
   // expression.
   CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
-  AppendStmt(ConfluenceBlock, C, asc);
+  appendStmt(ConfluenceBlock, C, asc);
   if (badCFG)
     return 0;
 
@@ -1310,7 +1274,7 @@
 
   if (!VD) {
     autoCreateBlock();
-    AppendStmt(Block, DS);
+    appendStmt(Block, DS);
     return Block;
   }
 
@@ -1332,16 +1296,15 @@
   }
 
   autoCreateBlock();
-  AppendStmt(Block, DS);
+  appendStmt(Block, DS);
 
   if (Init) {
-    AddStmtChoice asc = AddStmtChoice().withAsLValue(IsReference);
     if (HasTemporaries)
       // For expression with temporaries go directly to subexpression to omit
       // generating destructors for the second time.
-      Visit(cast<ExprWithCleanups>(Init)->getSubExpr(), asc);
+      Visit(cast<ExprWithCleanups>(Init)->getSubExpr());
     else
-      Visit(Init, asc);
+      Visit(Init);
   }
 
   // If the type of VD is a VLA, then we must process its size expressions.
@@ -1459,7 +1422,7 @@
   if (VarDecl *VD = I->getConditionVariable()) {
     if (Expr *Init = VD->getInit()) {
       autoCreateBlock();
-      AppendStmt(Block, I, AddStmtChoice::AlwaysAdd);
+      appendStmt(Block, I, AddStmtChoice::AlwaysAdd);
       addStmt(Init);
     }
   }
@@ -1594,7 +1557,7 @@
     if (VarDecl *VD = F->getConditionVariable()) {
       if (Expr *Init = VD->getInit()) {
         autoCreateBlock();
-        AppendStmt(Block, F, AddStmtChoice::AlwaysAdd);
+        appendStmt(Block, F, AddStmtChoice::AlwaysAdd);
         EntryConditionBlock = addStmt(Init);
         assert(Block == EntryConditionBlock);
       }
@@ -1694,10 +1657,9 @@
 CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) {
   if (asc.alwaysAdd()) {
     autoCreateBlock();
-    AppendStmt(Block, M, asc);
+    appendStmt(Block, M, asc);
   }
-  return Visit(M->getBase(),
-               AddStmtChoice().withAsLValue(!M->isArrow()));
+  return Visit(M->getBase());
 }
 
 CFGBlock* CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) {
@@ -1753,7 +1715,7 @@
   // The last statement in the block should be the ObjCForCollectionStmt, which
   // performs the actual binding to 'element' and determines if there are any
   // more items in the collection.
-  AppendStmt(ExitConditionBlock, S);
+  appendStmt(ExitConditionBlock, S);
   Block = ExitConditionBlock;
 
   // Walk the 'element' expression to see if there are any side-effects.  We
@@ -1820,7 +1782,7 @@
 
   // Add the @synchronized to the CFG.
   autoCreateBlock();
-  AppendStmt(Block, S, AddStmtChoice::AlwaysAdd);
+  appendStmt(Block, S, AddStmtChoice::AlwaysAdd);
 
   // Inline the sync expression.
   return addStmt(S->getSynchExpr());
@@ -1878,7 +1840,7 @@
     if (VarDecl *VD = W->getConditionVariable()) {
       if (Expr *Init = VD->getInit()) {
         autoCreateBlock();
-        AppendStmt(Block, W, AddStmtChoice::AlwaysAdd);
+        appendStmt(Block, W, AddStmtChoice::AlwaysAdd);
         EntryConditionBlock = addStmt(Init);
         assert(Block == EntryConditionBlock);
       }
@@ -2130,7 +2092,7 @@
 
   if (asc.alwaysAdd()) {
     autoCreateBlock();
-    AppendStmt(Block, E);
+    appendStmt(Block, E);
   }
 
   // VLA types have expressions that must be evaluated.
@@ -2148,7 +2110,7 @@
 CFGBlock* CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) {
   if (asc.alwaysAdd()) {
     autoCreateBlock();
-    AppendStmt(Block, SE);
+    appendStmt(Block, SE);
   }
   return VisitCompoundStmt(SE->getSubStmt());
 }
@@ -2226,7 +2188,7 @@
   if (VarDecl *VD = Terminator->getConditionVariable()) {
     if (Expr *Init = VD->getInit()) {
       autoCreateBlock();
-      AppendStmt(Block, Terminator, AddStmtChoice::AlwaysAdd);
+      appendStmt(Block, Terminator, AddStmtChoice::AlwaysAdd);
       addStmt(Init);
     }
   }
@@ -2429,7 +2391,7 @@
                                                 AddStmtChoice asc) {
   if (asc.alwaysAdd()) {
     autoCreateBlock();
-    AppendStmt(Block, E, asc);
+    appendStmt(Block, E, asc);
 
     // We do not want to propagate the AlwaysAdd property.
     asc = asc.withAlwaysAdd(false);
@@ -2441,7 +2403,7 @@
                                             AddStmtChoice asc) {
   autoCreateBlock();
   if (!C->isElidable())
-    AppendStmt(Block, C, asc.withAlwaysAdd(true));
+    appendStmt(Block, C, asc.withAlwaysAdd(true));
 
   return VisitChildren(C);
 }
@@ -2450,7 +2412,7 @@
                                                  AddStmtChoice asc) {
   if (asc.alwaysAdd()) {
     autoCreateBlock();
-    AppendStmt(Block, E, asc);
+    appendStmt(Block, E, asc);
     // We do not want to propagate the AlwaysAdd property.
     asc = asc.withAlwaysAdd(false);
   }
@@ -2460,14 +2422,14 @@
 CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
                                                   AddStmtChoice asc) {
   autoCreateBlock();
-  AppendStmt(Block, C, asc.withAlwaysAdd(true));
+  appendStmt(Block, C, asc.withAlwaysAdd(true));
   return VisitChildren(C);
 }
 
 CFGBlock *CFGBuilder::VisitCXXMemberCallExpr(CXXMemberCallExpr *C,
                                              AddStmtChoice asc) {
   autoCreateBlock();
-  AppendStmt(Block, C, asc.withAlwaysAdd(true));
+  appendStmt(Block, C, asc.withAlwaysAdd(true));
   return VisitChildren(C);
 }
 
@@ -2475,11 +2437,9 @@
                                             AddStmtChoice asc) {
   if (asc.alwaysAdd()) {
     autoCreateBlock();
-    AppendStmt(Block, E, asc);
-    // We do not want to propagate the AlwaysAdd property.
-    asc = asc.withAlwaysAdd(false);
+    appendStmt(Block, E, asc);
   }
-  return Visit(E->getSubExpr(), asc);
+  return Visit(E->getSubExpr(), AddStmtChoice());
 }
 
 CFGBlock* CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt* I) {
@@ -3082,9 +3042,6 @@
       OS << " (BindTemporary)";
     }
 
-    if (CS.asLValue())
-        OS << " (asLValue)";
-
     // Expressions need a newline.
     if (isa<Expr>(S))
       OS << '\n';
diff --git a/clang/lib/Analysis/PseudoConstantAnalysis.cpp b/clang/lib/Analysis/PseudoConstantAnalysis.cpp
index ff43fc2..25b04fc 100644
--- a/clang/lib/Analysis/PseudoConstantAnalysis.cpp
+++ b/clang/lib/Analysis/PseudoConstantAnalysis.cpp
@@ -86,6 +86,9 @@
     const Stmt* Head = WorkList.front();
     WorkList.pop_front();
 
+    if (const Expr *Ex = dyn_cast<Expr>(Head))
+      Head = Ex->IgnoreParenCasts();
+
     switch (Head->getStmtClass()) {
     // Case 1: Assignment operators modifying VarDecls
     case Stmt::BinaryOperatorClass: {
@@ -225,8 +228,8 @@
       continue;
     }
 
-      default:
-        break;
+    default:
+      break;
     } // switch (head->getStmtClass())
 
     // Add all substatements to the worklist
diff --git a/clang/lib/Analysis/ReachableCode.cpp b/clang/lib/Analysis/ReachableCode.cpp
index 1abfde2..b958580 100644
--- a/clang/lib/Analysis/ReachableCode.cpp
+++ b/clang/lib/Analysis/ReachableCode.cpp
@@ -42,6 +42,9 @@
   else
     return SourceLocation();
 
+  if (const Expr *Ex = dyn_cast<Expr>(S))
+    S = Ex->IgnoreParenImpCasts();
+
   switch (S->getStmtClass()) {
     case Expr::BinaryOperatorClass: {
       const BinaryOperator *BO = cast<BinaryOperator>(S);
@@ -101,9 +104,6 @@
       R1 = CE->getSubExpr()->getSourceRange();
       return CE->getTypeBeginLoc();
     }
-    case Expr::ImplicitCastExprClass:
-      ++sn;
-      goto top;
     case Stmt::CXXTryStmtClass: {
       return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc();
     }