Eliminate CXXConditionDeclExpr with extreme prejudice.

All statements that involve conditions can now hold on to a separate
condition declaration (a VarDecl), and will use a DeclRefExpr
referring to that VarDecl for the condition expression. ForStmts now
have such a VarDecl (I'd missed those in previous commits).

Also, since this change reworks the Action interface for
if/while/switch/for, use FullExprArg for the full expressions in those
expressions, to ensure that we're emitting

Note that we are (still) not generating the right cleanups for
condition variables in for statements. That will be a follow-on
commit.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89817 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index feff59a..19a255c 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1266,13 +1266,16 @@
                                           SourceLocation ColonLoc,
                                           StmtArg SubStmt);
   virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc,
-                                       FullExprArg CondVal, StmtArg ThenVal,
+                                       FullExprArg CondVal, DeclPtrTy CondVar,
+                                       StmtArg ThenVal,
                                        SourceLocation ElseLoc, StmtArg ElseVal);
-  virtual OwningStmtResult ActOnStartOfSwitchStmt(ExprArg Cond);
+  virtual OwningStmtResult ActOnStartOfSwitchStmt(FullExprArg Cond, 
+                                                  DeclPtrTy CondVar);
   virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc,
                                                  StmtArg Switch, StmtArg Body);
   virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc,
-                                          FullExprArg Cond, StmtArg Body);
+                                          FullExprArg Cond,
+                                          DeclPtrTy CondVar, StmtArg Body);
   virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
                                        SourceLocation WhileLoc,
                                        SourceLocation CondLParen, ExprArg Cond,
@@ -1280,8 +1283,10 @@
 
   virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc,
                                         SourceLocation LParenLoc,
-                                        StmtArg First, ExprArg Second,
-                                        ExprArg Third, SourceLocation RParenLoc,
+                                        StmtArg First, FullExprArg Second,
+                                        DeclPtrTy SecondVar,
+                                        FullExprArg Third, 
+                                        SourceLocation RParenLoc,
                                         StmtArg Body);
   virtual OwningStmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
                                        SourceLocation LParenLoc,
@@ -1880,14 +1885,8 @@
                                           bool UseGlobal, bool ArrayForm,
                                           ExprArg Operand);
 
-  /// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
-  /// C++ if/switch/while/for statement.
-  /// e.g: "if (int x = f()) {...}"
-  virtual OwningExprResult ActOnCXXConditionDeclarationExpr(Scope *S,
-                                                      SourceLocation StartLoc,
-                                                      Declarator &D,
-                                                      SourceLocation EqualLoc,
-                                                      ExprArg AssignExprVal);
+  virtual DeclResult ActOnCXXConditionDeclaration(Scope *S,
+                                                  Declarator &D);
   OwningExprResult CheckConditionVariable(VarDecl *ConditionVar);
                                           
   /// ActOnUnaryTypeTrait - Parsed one of the unary type trait support
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index b5419c1..1df1173 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -4918,3 +4918,39 @@
   assert(S->getEntity() == D->getDeclContext() && "Context imbalance!");
   ExitDeclaratorContext(S);
 }
+
+/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
+/// C++ if/switch/while/for statement.
+/// e.g: "if (int x = f()) {...}"
+Action::DeclResult
+Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
+  // C++ 6.4p2:
+  // The declarator shall not specify a function or an array.
+  // The type-specifier-seq shall not contain typedef and shall not declare a
+  // new class or enumeration.
+  assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
+         "Parser allowed 'typedef' as storage class of condition decl.");
+  
+  DeclaratorInfo *DInfo = 0;
+  TagDecl *OwnedTag = 0;
+  QualType Ty = GetTypeForDeclarator(D, S, &DInfo, &OwnedTag);
+  
+  if (Ty->isFunctionType()) { // The declarator shall not specify a function...
+                              // We exit without creating a CXXConditionDeclExpr because a FunctionDecl
+                              // would be created and CXXConditionDeclExpr wants a VarDecl.
+    Diag(D.getIdentifierLoc(), diag::err_invalid_use_of_function_type)
+      << D.getSourceRange();
+    return DeclResult();
+  } else if (OwnedTag && OwnedTag->isDefinition()) {
+    // The type-specifier-seq shall not declare a new class or enumeration.
+    Diag(OwnedTag->getLocation(), diag::err_type_defined_in_condition);
+  }
+  
+  DeclPtrTy Dcl = ActOnDeclarator(S, D);
+  if (!Dcl)
+    return DeclResult();
+
+  VarDecl *VD = cast<VarDecl>(Dcl.getAs<Decl>());
+  VD->setDeclaredInCondition(true);
+  return Dcl;
+}
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 40e5707..3b18b3a 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -943,56 +943,6 @@
                                            OperatorDelete, Ex, StartLoc));
 }
 
-
-/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
-/// C++ if/switch/while/for statement.
-/// e.g: "if (int x = f()) {...}"
-Action::OwningExprResult
-Sema::ActOnCXXConditionDeclarationExpr(Scope *S, SourceLocation StartLoc,
-                                       Declarator &D,
-                                       SourceLocation EqualLoc,
-                                       ExprArg AssignExprVal) {
-  assert(AssignExprVal.get() && "Null assignment expression");
-
-  // C++ 6.4p2:
-  // The declarator shall not specify a function or an array.
-  // The type-specifier-seq shall not contain typedef and shall not declare a
-  // new class or enumeration.
-
-  assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
-         "Parser allowed 'typedef' as storage class of condition decl.");
-
-  // FIXME: Store DeclaratorInfo in the expression.
-  DeclaratorInfo *DInfo = 0;
-  TagDecl *OwnedTag = 0;
-  QualType Ty = GetTypeForDeclarator(D, S, &DInfo, &OwnedTag);
-
-  if (Ty->isFunctionType()) { // The declarator shall not specify a function...
-    // We exit without creating a CXXConditionDeclExpr because a FunctionDecl
-    // would be created and CXXConditionDeclExpr wants a VarDecl.
-    return ExprError(Diag(StartLoc, diag::err_invalid_use_of_function_type)
-      << SourceRange(StartLoc, EqualLoc));
-  } else if (Ty->isArrayType()) { // ...or an array.
-    Diag(StartLoc, diag::err_invalid_use_of_array_type)
-      << SourceRange(StartLoc, EqualLoc);
-  } else if (OwnedTag && OwnedTag->isDefinition()) {
-    // The type-specifier-seq shall not declare a new class or enumeration.
-    Diag(OwnedTag->getLocation(), diag::err_type_defined_in_condition);
-  }
-
-  DeclPtrTy Dcl = ActOnDeclarator(S, D);
-  if (!Dcl)
-    return ExprError();
-  AddInitializerToDecl(Dcl, move(AssignExprVal), /*DirectInit=*/false);
-
-  // Mark this variable as one that is declared within a conditional.
-  // We know that the decl had to be a VarDecl because that is the only type of
-  // decl that can be assigned and the grammar requires an '='.
-  VarDecl *VD = cast<VarDecl>(Dcl.getAs<Decl>());
-  VD->setDeclaredInCondition(true);
-  return Owned(new (Context) CXXConditionDeclExpr(StartLoc, EqualLoc, VD));
-}
-
 /// \brief Check the use of the given variable as a C++ condition in an if,
 /// while, do-while, or switch statement.
 Action::OwningExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar) {
@@ -1009,18 +959,9 @@
                           diag::err_invalid_use_of_array_type)
                      << ConditionVar->getSourceRange());
 
-  // FIXME: Switch to building a DeclRefExpr, once we've eliminated the
-  // need for CXXConditionDeclExpr.
-#if 0
   return Owned(DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar,
                                    ConditionVar->getLocation(), 
                                 ConditionVar->getType().getNonReferenceType()));
-#else
-  return Owned(new (Context) CXXConditionDeclExpr(
-                                     ConditionVar->getSourceRange().getBegin(),
-                                     ConditionVar->getSourceRange().getEnd(),
-                                     ConditionVar));
-#endif                                                  
 }
 
 /// CheckCXXBooleanCondition - Returns true if a conversion to bool is invalid.
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 61d48cb..be9a09b 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -236,25 +236,24 @@
 }
 
 Action::OwningStmtResult
-Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal,
+Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, DeclPtrTy CondVar,
                   StmtArg ThenVal, SourceLocation ElseLoc,
                   StmtArg ElseVal) {
   OwningExprResult CondResult(CondVal.release());
 
-  Expr *condExpr = CondResult.takeAs<Expr>();
-  assert(condExpr && "ActOnIfStmt(): missing expression");
-  
   VarDecl *ConditionVar = 0;
-  if (CXXConditionDeclExpr *Cond = dyn_cast<CXXConditionDeclExpr>(condExpr)) {
-    ConditionVar = Cond->getVarDecl();
-    condExpr = DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar,
-                                   ConditionVar->getLocation(), 
-                                 ConditionVar->getType().getNonReferenceType());
-    // FIXME: Leaks the old condExpr
+  if (CondVar.get()) {
+    ConditionVar = CondVar.getAs<VarDecl>();
+    CondResult = CheckConditionVariable(ConditionVar);
+    if (CondResult.isInvalid())
+      return StmtError();
   }
+  Expr *ConditionExpr = CondResult.takeAs<Expr>();
+  if (!ConditionExpr)
+    return StmtError();
   
-  if (CheckBooleanCondition(condExpr, IfLoc)) {
-    CondResult = condExpr;
+  if (CheckBooleanCondition(ConditionExpr, IfLoc)) {
+    CondResult = ConditionExpr;
     return StmtError();
   }
 
@@ -274,23 +273,27 @@
   DiagnoseUnusedExprResult(elseStmt);
 
   CondResult.release();
-  return Owned(new (Context) IfStmt(IfLoc, ConditionVar, condExpr, thenStmt,
-                                    ElseLoc, elseStmt));
+  return Owned(new (Context) IfStmt(IfLoc, ConditionVar, ConditionExpr, 
+                                    thenStmt, ElseLoc, elseStmt));
 }
 
 Action::OwningStmtResult
-Sema::ActOnStartOfSwitchStmt(ExprArg cond) {
-  Expr *condExpr = cond.takeAs<Expr>();
+Sema::ActOnStartOfSwitchStmt(FullExprArg cond, DeclPtrTy CondVar) {
+  OwningExprResult CondResult(cond.release());
+  
   VarDecl *ConditionVar = 0;
-  if (CXXConditionDeclExpr *Cond = dyn_cast<CXXConditionDeclExpr>(condExpr)) {
-    ConditionVar = Cond->getVarDecl();
-    condExpr = DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar,
-                                   ConditionVar->getLocation(), 
-                                 ConditionVar->getType().getNonReferenceType());
-    // FIXME: Leaks the old condExpr
+  if (CondVar.get()) {
+    ConditionVar = CondVar.getAs<VarDecl>();
+    CondResult = CheckConditionVariable(ConditionVar);
+    if (CondResult.isInvalid())
+      return StmtError();
   }
+  Expr *ConditionExpr = CondResult.takeAs<Expr>();
+  if (!ConditionExpr)
+    return StmtError();
 
-  SwitchStmt *SS = new (Context) SwitchStmt(ConditionVar, condExpr);
+  CondResult.release();
+  SwitchStmt *SS = new (Context) SwitchStmt(ConditionVar, ConditionExpr);
   getSwitchStack().push_back(SS);
   return Owned(SS);
 }
@@ -715,30 +718,31 @@
 }
 
 Action::OwningStmtResult
-Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond, StmtArg Body) {
-  ExprArg CondArg(Cond.release());
-  Expr *condExpr = CondArg.takeAs<Expr>();
-  assert(condExpr && "ActOnWhileStmt(): missing expression");
-
+Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond, 
+                     DeclPtrTy CondVar, StmtArg Body) {
+  OwningExprResult CondResult(Cond.release());
+  
   VarDecl *ConditionVar = 0;
-  if (CXXConditionDeclExpr *Cond = dyn_cast<CXXConditionDeclExpr>(condExpr)) {
-    ConditionVar = Cond->getVarDecl();
-    condExpr = DeclRefExpr::Create(Context, 0, SourceRange(), ConditionVar,
-                                   ConditionVar->getLocation(), 
-                                 ConditionVar->getType().getNonReferenceType());
-    // FIXME: Leaks the old condExpr
+  if (CondVar.get()) {
+    ConditionVar = CondVar.getAs<VarDecl>();
+    CondResult = CheckConditionVariable(ConditionVar);
+    if (CondResult.isInvalid())
+      return StmtError();
   }
-
-  if (CheckBooleanCondition(condExpr, WhileLoc)) {
-    CondArg = condExpr;
+  Expr *ConditionExpr = CondResult.takeAs<Expr>();
+  if (!ConditionExpr)
+    return StmtError();
+  
+  if (CheckBooleanCondition(ConditionExpr, WhileLoc)) {
+    CondResult = ConditionExpr;
     return StmtError();
   }
 
   Stmt *bodyStmt = Body.takeAs<Stmt>();
   DiagnoseUnusedExprResult(bodyStmt);
 
-  CondArg.release();
-  return Owned(new (Context) WhileStmt(ConditionVar, condExpr, bodyStmt, 
+  CondResult.release();
+  return Owned(new (Context) WhileStmt(ConditionVar, ConditionExpr, bodyStmt, 
                                        WhileLoc));
 }
 
@@ -764,12 +768,10 @@
 
 Action::OwningStmtResult
 Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
-                   StmtArg first, ExprArg second, ExprArg third,
+                   StmtArg first, FullExprArg second, DeclPtrTy secondVar,
+                   FullExprArg third,
                    SourceLocation RParenLoc, StmtArg body) {
   Stmt *First  = static_cast<Stmt*>(first.get());
-  Expr *Second = second.takeAs<Expr>();
-  Expr *Third  = static_cast<Expr*>(third.get());
-  Stmt *Body  = static_cast<Stmt*>(body.get());
 
   if (!getLangOptions().CPlusPlus) {
     if (DeclStmt *DS = dyn_cast_or_null<DeclStmt>(First)) {
@@ -787,20 +789,33 @@
       }
     }
   }
+
+  OwningExprResult SecondResult(second.release());
+  VarDecl *ConditionVar = 0;
+  if (secondVar.get()) {
+    ConditionVar = secondVar.getAs<VarDecl>();
+    SecondResult = CheckConditionVariable(ConditionVar);
+    if (SecondResult.isInvalid())
+      return StmtError();
+  }
+  
+  Expr *Second = SecondResult.takeAs<Expr>();
   if (Second && CheckBooleanCondition(Second, ForLoc)) {
-    second = Second;
+    SecondResult = Second;
     return StmtError();
   }
 
+  Expr *Third  = third.release().takeAs<Expr>();
+  Stmt *Body  = static_cast<Stmt*>(body.get());
+  
   DiagnoseUnusedExprResult(First);
   DiagnoseUnusedExprResult(Third);
   DiagnoseUnusedExprResult(Body);
 
   first.release();
-  third.release();
   body.release();
-  return Owned(new (Context) ForStmt(First, Second, Third, Body, ForLoc,
-                                     LParenLoc, RParenLoc));
+  return Owned(new (Context) ForStmt(First, Second, ConditionVar, Third, Body, 
+                                     ForLoc, LParenLoc, RParenLoc));
 }
 
 Action::OwningStmtResult
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 202e16e..1071aeb 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -95,7 +95,8 @@
   typedef Sema::ExprArg ExprArg;
   typedef Sema::MultiExprArg MultiExprArg;
   typedef Sema::MultiStmtArg MultiStmtArg;
-
+  typedef Sema::DeclPtrTy DeclPtrTy;
+  
   /// \brief Initializes a new tree transformer.
   TreeTransform(Sema &SemaRef) : SemaRef(SemaRef) { }
 
@@ -665,17 +666,19 @@
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide different behavior.
   OwningStmtResult RebuildIfStmt(SourceLocation IfLoc, Sema::FullExprArg Cond,
-                                 StmtArg Then, SourceLocation ElseLoc,
-                                 StmtArg Else) {
-    return getSema().ActOnIfStmt(IfLoc, Cond, move(Then), ElseLoc, move(Else));
+                                 VarDecl *CondVar, StmtArg Then, 
+                                 SourceLocation ElseLoc, StmtArg Else) {
+    return getSema().ActOnIfStmt(IfLoc, Cond, DeclPtrTy::make(CondVar), 
+                                 move(Then), ElseLoc, move(Else));
   }
 
   /// \brief Start building a new switch statement.
   ///
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide different behavior.
-  OwningStmtResult RebuildSwitchStmtStart(ExprArg Cond) {
-    return getSema().ActOnStartOfSwitchStmt(move(Cond));
+  OwningStmtResult RebuildSwitchStmtStart(Sema::FullExprArg Cond, 
+                                          VarDecl *CondVar) {
+    return getSema().ActOnStartOfSwitchStmt(Cond, DeclPtrTy::make(CondVar));
   }
 
   /// \brief Attach the body to the switch statement.
@@ -694,8 +697,10 @@
   /// Subclasses may override this routine to provide different behavior.
   OwningStmtResult RebuildWhileStmt(SourceLocation WhileLoc,
                                     Sema::FullExprArg Cond,
+                                    VarDecl *CondVar,
                                     StmtArg Body) {
-    return getSema().ActOnWhileStmt(WhileLoc, Cond, move(Body));
+    return getSema().ActOnWhileStmt(WhileLoc, Cond, DeclPtrTy::make(CondVar),
+                                    move(Body));
   }
 
   /// \brief Build a new do-while statement.
@@ -717,10 +722,12 @@
   /// Subclasses may override this routine to provide different behavior.
   OwningStmtResult RebuildForStmt(SourceLocation ForLoc,
                                   SourceLocation LParenLoc,
-                                  StmtArg Init, ExprArg Cond, ExprArg Inc,
+                                  StmtArg Init, Sema::FullExprArg Cond, 
+                                  VarDecl *CondVar, Sema::FullExprArg Inc,
                                   SourceLocation RParenLoc, StmtArg Body) {
-    return getSema().ActOnForStmt(ForLoc, LParenLoc, move(Init), move(Cond),
-                                  move(Inc), RParenLoc, move(Body));
+    return getSema().ActOnForStmt(ForLoc, LParenLoc, move(Init), Cond, 
+                                  DeclPtrTy::make(CondVar),
+                                  Inc, RParenLoc, move(Body));
   }
 
   /// \brief Build a new goto statement.
@@ -1374,18 +1381,6 @@
                                                0, RParenLoc);
   }
 
-  /// \brief Build a new C++ conditional declaration expression.
-  ///
-  /// By default, performs semantic analysis to build the new expression.
-  /// Subclasses may override this routine to provide different behavior.
-  OwningExprResult RebuildCXXConditionDeclExpr(SourceLocation StartLoc,
-                                               SourceLocation EqLoc,
-                                               VarDecl *Var) {
-    return SemaRef.Owned(new (SemaRef.Context) CXXConditionDeclExpr(StartLoc,
-                                                                    EqLoc,
-                                                                    Var));
-  }
-
   /// \brief Build a new C++ "new" expression.
   ///
   /// By default, performs semantic analysis to build the new expression.
@@ -3071,13 +3066,12 @@
                    getDerived().TransformDefinition(S->getConditionVariable()));
     if (!ConditionVar)
       return SemaRef.StmtError();
-    
-    Cond = getSema().CheckConditionVariable(ConditionVar);
-  } else
+  } else {
     Cond = getDerived().TransformExpr(S->getCond());
   
-  if (Cond.isInvalid())
-    return SemaRef.StmtError();
+    if (Cond.isInvalid())
+      return SemaRef.StmtError();
+  }
   
   Sema::FullExprArg FullCond(getSema().FullExpr(Cond));
 
@@ -3093,11 +3087,13 @@
 
   if (!getDerived().AlwaysRebuild() &&
       FullCond->get() == S->getCond() &&
+      ConditionVar == S->getConditionVariable() &&
       Then.get() == S->getThen() &&
       Else.get() == S->getElse())
     return SemaRef.Owned(S->Retain());
 
-  return getDerived().RebuildIfStmt(S->getIfLoc(), FullCond, move(Then),
+  return getDerived().RebuildIfStmt(S->getIfLoc(), FullCond, ConditionVar,
+                                    move(Then),
                                     S->getElseLoc(), move(Else));
 }
 
@@ -3113,15 +3109,18 @@
                    getDerived().TransformDefinition(S->getConditionVariable()));
     if (!ConditionVar)
       return SemaRef.StmtError();
-    
-    Cond = getSema().CheckConditionVariable(ConditionVar);
-  } else
+  } else {
     Cond = getDerived().TransformExpr(S->getCond());
-  if (Cond.isInvalid())
-    return SemaRef.StmtError();
+    
+    if (Cond.isInvalid())
+      return SemaRef.StmtError();
+  }
 
+  Sema::FullExprArg FullCond(getSema().FullExpr(Cond));
+  
   // Rebuild the switch statement.
-  OwningStmtResult Switch = getDerived().RebuildSwitchStmtStart(move(Cond));
+  OwningStmtResult Switch = getDerived().RebuildSwitchStmtStart(FullCond,
+                                                                ConditionVar);
   if (Switch.isInvalid())
     return SemaRef.StmtError();
 
@@ -3147,12 +3146,12 @@
                    getDerived().TransformDefinition(S->getConditionVariable()));
     if (!ConditionVar)
       return SemaRef.StmtError();
-    
-    Cond = getSema().CheckConditionVariable(ConditionVar);
-  } else
+  } else {
     Cond = getDerived().TransformExpr(S->getCond());
-  if (Cond.isInvalid())
-    return SemaRef.StmtError();
+    
+    if (Cond.isInvalid())
+      return SemaRef.StmtError();
+  }
 
   Sema::FullExprArg FullCond(getSema().FullExpr(Cond));
 
@@ -3163,10 +3162,12 @@
 
   if (!getDerived().AlwaysRebuild() &&
       FullCond->get() == S->getCond() &&
+      ConditionVar == S->getConditionVariable() &&
       Body.get() == S->getBody())
     return SemaRef.Owned(S->Retain());
 
-  return getDerived().RebuildWhileStmt(S->getWhileLoc(), FullCond, move(Body));
+  return getDerived().RebuildWhileStmt(S->getWhileLoc(), FullCond, ConditionVar,
+                                       move(Body));
 }
 
 template<typename Derived>
@@ -3201,9 +3202,20 @@
     return SemaRef.StmtError();
 
   // Transform the condition
-  OwningExprResult Cond = getDerived().TransformExpr(S->getCond());
-  if (Cond.isInvalid())
-    return SemaRef.StmtError();
+  OwningExprResult Cond(SemaRef);
+  VarDecl *ConditionVar = 0;
+  if (S->getConditionVariable()) {
+    ConditionVar 
+      = cast_or_null<VarDecl>(
+                   getDerived().TransformDefinition(S->getConditionVariable()));
+    if (!ConditionVar)
+      return SemaRef.StmtError();
+  } else {
+    Cond = getDerived().TransformExpr(S->getCond());
+    
+    if (Cond.isInvalid())
+      return SemaRef.StmtError();
+  }
 
   // Transform the increment
   OwningExprResult Inc = getDerived().TransformExpr(S->getInc());
@@ -3223,7 +3235,9 @@
     return SemaRef.Owned(S->Retain());
 
   return getDerived().RebuildForStmt(S->getForLoc(), S->getLParenLoc(),
-                                     move(Init), move(Cond), move(Inc),
+                                     move(Init), getSema().FullExpr(Cond),
+                                     ConditionVar,
+                                     getSema().FullExpr(Inc),
                                      S->getRParenLoc(), move(Body));
 }
 
@@ -4418,24 +4432,6 @@
 
 template<typename Derived>
 Sema::OwningExprResult
-TreeTransform<Derived>::TransformCXXConditionDeclExpr(CXXConditionDeclExpr *E,
-                                                      bool isAddressOfOperand) {
-  VarDecl *Var
-    = cast_or_null<VarDecl>(getDerived().TransformDefinition(E->getVarDecl()));
-  if (!Var)
-    return SemaRef.ExprError();
-
-  if (!getDerived().AlwaysRebuild() &&
-      Var == E->getVarDecl())
-    return SemaRef.Owned(E->Retain());
-
-  return getDerived().RebuildCXXConditionDeclExpr(E->getStartLoc(),
-                                                  /*FIXME:*/E->getStartLoc(),
-                                                  Var);
-}
-
-template<typename Derived>
-Sema::OwningExprResult
 TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E,
                                             bool isAddressOfOperand) {
   // Transform the type that we're allocating