]> granicus.if.org Git - clang/commitdiff
Eliminate CXXConditionDeclExpr with extreme prejudice.
authorDouglas Gregor <dgregor@apple.com>
Wed, 25 Nov 2009 00:27:52 +0000 (00:27 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 25 Nov 2009 00:27:52 +0000 (00:27 +0000)
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

27 files changed:
include/clang/AST/Expr.h
include/clang/AST/ExprCXX.h
include/clang/AST/Stmt.h
include/clang/AST/StmtNodes.def
include/clang/Frontend/StmtXML.def
include/clang/Parse/Action.h
include/clang/Parse/Parser.h
lib/AST/Expr.cpp
lib/AST/ExprCXX.cpp
lib/AST/StmtPrinter.cpp
lib/AST/StmtProfile.cpp
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CGStmt.cpp
lib/CodeGen/CodeGenFunction.h
lib/Frontend/PCHReaderStmt.cpp
lib/Frontend/PCHWriterStmt.cpp
lib/Frontend/PrintParserCallbacks.cpp
lib/Frontend/StmtXML.cpp
lib/Parse/ParseExprCXX.cpp
lib/Parse/ParseStmt.cpp
lib/Sema/Sema.h
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaStmt.cpp
lib/Sema/TreeTransform.h
test/CodeGenCXX/condition.cpp
test/SemaCXX/condition.cpp

index 61cb9587d6cae4507d1b479b9177ff15da2067f7..7cf9aabc6d6f82b3708f4c69dce43d1e1f4a4f54 100644 (file)
@@ -540,8 +540,7 @@ public:
   }
   
   static bool classof(const Stmt *T) {
-    return T->getStmtClass() == DeclRefExprClass ||
-           T->getStmtClass() == CXXConditionDeclExprClass;
+    return T->getStmtClass() == DeclRefExprClass;
   }
   static bool classof(const DeclRefExpr *) { return true; }
 
index 63b153a17e946cadd62bb6d72d340e11a6768f14..ce29d84c5ca24d5369e1195fbc331c3255d09a48 100644 (file)
@@ -671,37 +671,6 @@ public:
   virtual child_iterator child_end();
 };
 
-/// CXXConditionDeclExpr - Condition declaration of a if/switch/while/for
-/// statement, e.g: "if (int x = f()) {...}".
-/// The main difference with DeclRefExpr is that CXXConditionDeclExpr owns the
-/// decl that it references.
-///
-class CXXConditionDeclExpr : public DeclRefExpr {
-public:
-  CXXConditionDeclExpr(SourceLocation startLoc,
-                       SourceLocation eqLoc, VarDecl *var)
-    : DeclRefExpr(CXXConditionDeclExprClass, var,
-                  var->getType().getNonReferenceType(), startLoc) {}
-
-  SourceLocation getStartLoc() const { return getLocation(); }
-
-  VarDecl *getVarDecl() { return cast<VarDecl>(getDecl()); }
-  const VarDecl *getVarDecl() const { return cast<VarDecl>(getDecl()); }
-
-  virtual SourceRange getSourceRange() const {
-    return SourceRange(getStartLoc(), getVarDecl()->getInit()->getLocEnd());
-  }
-
-  static bool classof(const Stmt *T) {
-    return T->getStmtClass() == CXXConditionDeclExprClass;
-  }
-  static bool classof(const CXXConditionDeclExpr *) { return true; }
-
-  // Iterators
-  virtual child_iterator child_begin();
-  virtual child_iterator child_end();
-};
-
 /// CXXNewExpr - A new expression for memory allocation and constructor calls,
 /// e.g: "new CXXNewExpr(foo)".
 class CXXNewExpr : public Expr {
index b7505e1bc770ac65bbd65952ce142d95426ec821..14bffd0fd765e1437a3ca058c5b4eb4db1fc33ac 100644 (file)
@@ -855,26 +855,38 @@ public:
 class ForStmt : public Stmt {
   enum { INIT, COND, INC, BODY, END_EXPR };
   Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt.
+  VarDecl *CondVar;
   SourceLocation ForLoc;
   SourceLocation LParenLoc, RParenLoc;
 
 public:
-  ForStmt(Stmt *Init, Expr *Cond, Expr *Inc, Stmt *Body, SourceLocation FL,
-          SourceLocation LP, SourceLocation RP)
-    : Stmt(ForStmtClass) {
+  ForStmt(Stmt *Init, Expr *Cond, VarDecl *CondVar, Expr *Inc, Stmt *Body, 
+          SourceLocation FL, SourceLocation LP, SourceLocation RP)
+    : Stmt(ForStmtClass), CondVar(CondVar), ForLoc(FL), LParenLoc(LP), 
+      RParenLoc(RP) 
+  {
     SubExprs[INIT] = Init;
     SubExprs[COND] = reinterpret_cast<Stmt*>(Cond);
     SubExprs[INC] = reinterpret_cast<Stmt*>(Inc);
     SubExprs[BODY] = Body;
-    ForLoc = FL;
-    LParenLoc = LP;
-    RParenLoc = RP;
   }
 
   /// \brief Build an empty for statement.
   explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { }
 
   Stmt *getInit() { return SubExprs[INIT]; }
+  
+  /// \brief Retrieve the variable declared in this "for" statement, if any.
+  ///
+  /// In the following example, "y" is the condition variable.
+  /// \code
+  /// for (int x = random(); int y = mangle(x); ++x) {
+  ///   // ...
+  /// }
+  /// \endcode
+  VarDecl *getConditionVariable() const { return CondVar; }
+  void setConditionVariable(VarDecl *V) { CondVar = V; }
+  
   Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); }
   Expr *getInc()  { return reinterpret_cast<Expr*>(SubExprs[INC]); }
   Stmt *getBody() { return SubExprs[BODY]; }
index dd8a685a95046226fe8f978cfc023244a74d1a93..316521b4e4a8b865f89d4736c839982640caa3dd 100644 (file)
@@ -121,7 +121,6 @@ EXPR(CXXThisExpr            , Expr)
 EXPR(CXXThrowExpr           , Expr)
 EXPR(CXXDefaultArgExpr      , Expr)
 EXPR(CXXZeroInitValueExpr   , Expr)
-EXPR(CXXConditionDeclExpr   , DeclRefExpr)
 EXPR(CXXNewExpr             , Expr)
 EXPR(CXXDeleteExpr          , Expr)
 EXPR(CXXPseudoDestructorExpr, Expr)
index 332aad2dd212ea5c6c88b83394e69bd18c443e8f..2f0da9e7b117fe60e5b7baab3f35de80b8f3069e 100644 (file)
@@ -495,13 +495,6 @@ NODE_XML(CXXDefaultArgExpr, "CXXDefaultArgExpr")
   ATTRIBUTE_XML(getParam(), "ref")                      // id of the parameter declaration (the expression is a subnode of the declaration)
 END_NODE_XML
 
-NODE_XML(CXXConditionDeclExpr, "CXXConditionDeclExpr")
-  ATTRIBUTE_FILE_LOCATION_XML
-  TYPE_ATTRIBUTE_XML(getType())
-  SUB_NODE_XML(VarDecl)                                 // a CXXConditionDeclExpr owns the declaration
-END_NODE_XML
-
-
 //===----------------------------------------------------------------------===//
 #undef NODE_XML
 #undef ID_ATTRIBUTE_XML
index 3db90c6574c36c58c33e149ae395b904101762d5..4b09cabfaad73dc636c1a39b3cd0d31a397a45e4 100644 (file)
@@ -705,14 +705,39 @@ public:
     return StmtEmpty();
   }
 
+  /// \brief Parsed an "if" statement.
+  ///
+  /// \param IfLoc the location of the "if" keyword.
+  ///
+  /// \param CondVal if the "if" condition was parsed as an expression, 
+  /// the expression itself.
+  ///
+  /// \param CondVar if the "if" condition was parsed as a condition variable,
+  /// the condition variable itself.
+  ///
+  /// \param ThenVal the "then" statement.
+  ///
+  /// \param ElseLoc the location of the "else" keyword.
+  ///
+  /// \param ElseVal the "else" statement.
   virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc,
-                                       FullExprArg CondVal, StmtArg ThenVal,
+                                       FullExprArg CondVal, 
+                                       DeclPtrTy CondVar,
+                                       StmtArg ThenVal,
                                        SourceLocation ElseLoc,
                                        StmtArg ElseVal) {
     return StmtEmpty();
   }
 
-  virtual OwningStmtResult ActOnStartOfSwitchStmt(ExprArg Cond) {
+  /// \brief Parsed the start of a "switch" statement.
+  ///
+  /// \param Cond if the "switch" condition was parsed as an expression, 
+  /// the expression itself.
+  ///
+  /// \param CondVar if the "switch" condition was parsed as a condition 
+  /// variable, the condition variable itself.
+  virtual OwningStmtResult ActOnStartOfSwitchStmt(FullExprArg Cond,
+                                                  DeclPtrTy CondVar) {
     return StmtEmpty();
   }
 
@@ -721,8 +746,18 @@ public:
     return StmtEmpty();
   }
 
+  /// \brief Parsed a "while" statement.
+  ///
+  /// \param Cond if the "while" condition was parsed as an expression, 
+  /// the expression itself.
+  ///
+  /// \param CondVar if the "while" condition was parsed as a condition 
+  /// variable, the condition variable itself.
+  ///
+  /// \param Body the body of the "while" loop.
   virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc,
-                                          FullExprArg Cond, StmtArg Body) {
+                                          FullExprArg Cond, DeclPtrTy CondVar,
+                                          StmtArg Body) {
     return StmtEmpty();
   }
   virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
@@ -732,13 +767,36 @@ public:
                                        SourceLocation CondRParen) {
     return StmtEmpty();
   }
+
+  /// \brief Parsed a "for" statement.
+  ///
+  /// \param ForLoc the location of the "for" keyword.
+  ///
+  /// \param LParenLoc the location of the left parentheses.
+  ///
+  /// \param First the statement used to initialize the for loop.
+  ///
+  /// \param Second the condition to be checked during each iteration, if
+  /// that condition was parsed as an expression.
+  ///
+  /// \param SecondArg the condition variable to be checked during each 
+  /// iterator, if that condition was parsed as a variable declaration.
+  ///
+  /// \param Third the expression that will be evaluated to "increment" any
+  /// values prior to the next iteration.
+  ///
+  /// \param RParenLoc the location of the right parentheses.
+  ///
+  /// \param Body the body of the "body" loop.
   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) {
     return StmtEmpty();
   }
+  
   virtual OwningStmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc,
                                        SourceLocation LParenLoc,
                                        StmtArg First, ExprArg Second,
@@ -1382,15 +1440,22 @@ public:
     return ExprEmpty();
   }
 
-  /// 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) {
-    return ExprEmpty();
+  /// \brief Parsed a condition declaration in a C++ if, switch, or while
+  /// statement.
+  /// 
+  /// This callback will be invoked after parsing the declaration of "x" in
+  ///
+  /// \code
+  /// if (int x = f()) {
+  ///   // ...
+  /// }
+  /// \endcode
+  ///
+  /// \param S the scope of the if, switch, or while statement.
+  ///
+  /// \param D the declarator that that describes the variable being declared.
+  virtual DeclResult ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
+    return DeclResult();
   }
 
   /// ActOnCXXNew - Parsed a C++ 'new' expression. UseGlobal is true if the
index b1375d7d653272253ef74c3e37126f9170a13a0e..30c6b90d1fad64e3f00915ced82121e58bda0b98 100644 (file)
@@ -934,8 +934,8 @@ private:
                                             SourceLocation Start);
 
   //===--------------------------------------------------------------------===//
-  // C++ if/switch/while/for condition expression.
-  OwningExprResult ParseCXXCondition();
+  // C++ if/switch/while condition expression.
+  bool ParseCXXCondition(OwningExprResult &ExprResult, DeclPtrTy &DeclResult);
 
   //===--------------------------------------------------------------------===//
   // C++ types
@@ -1001,10 +1001,8 @@ private:
   OwningStmtResult ParseCompoundStatement(AttributeList *Attr,
                                           bool isStmtExpr = false);
   OwningStmtResult ParseCompoundStatementBody(bool isStmtExpr = false);
-  bool ParseParenExprOrCondition(OwningExprResult &CondExp,
-                                 bool OnlyAllowCondition = false,
-                                 SourceLocation *LParenLoc = 0,
-                                 SourceLocation *RParenLoc = 0);
+  bool ParseParenExprOrCondition(OwningExprResult &ExprResult,
+                                 DeclPtrTy &DeclResult);
   OwningStmtResult ParseIfStatement(AttributeList *Attr);
   OwningStmtResult ParseSwitchStatement(AttributeList *Attr);
   OwningStmtResult ParseWhileStatement(AttributeList *Attr);
index 9f082716948817cee05ec784967749a9620f2931..e4de703029fcd7021eee7b237bdd2e4f9eab270d 100644 (file)
@@ -1130,8 +1130,6 @@ Expr::isLvalueResult Expr::isLvalueInternal(ASTContext &Ctx) const {
     return LV_Valid;
   case CXXDefaultArgExprClass:
     return cast<CXXDefaultArgExpr>(this)->getExpr()->isLvalue(Ctx);
-  case CXXConditionDeclExprClass:
-    return LV_Valid;
   case CStyleCastExprClass:
   case CXXFunctionalCastExprClass:
   case CXXStaticCastExprClass:
@@ -1516,7 +1514,6 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) {
   case Expr::CXXNullPtrLiteralExprClass:
   case Expr::CXXThisExprClass:
   case Expr::CXXThrowExprClass:
-  case Expr::CXXConditionDeclExprClass: // FIXME: is this correct?
   case Expr::CXXNewExprClass:
   case Expr::CXXDeleteExprClass:
   case Expr::CXXPseudoDestructorExprClass:
index 8591a4d8bd7f38248564e14f647c7e822b100abc..0e724a8d5c2a733a6ae5b44db5e518e89762f4ee 100644 (file)
@@ -72,14 +72,6 @@ Stmt::child_iterator CXXZeroInitValueExpr::child_end() {
   return child_iterator();
 }
 
-// CXXConditionDeclExpr
-Stmt::child_iterator CXXConditionDeclExpr::child_begin() {
-  return getVarDecl();
-}
-Stmt::child_iterator CXXConditionDeclExpr::child_end() {
-  return child_iterator();
-}
-
 // CXXNewExpr
 CXXNewExpr::CXXNewExpr(bool globalNew, FunctionDecl *operatorNew,
                        Expr **placementArgs, unsigned numPlaceArgs,
index a7cfed9788430c4e143c2250ab4a08e72355bfbc..7a02a451d8d35dac0be132e3c2ef75b5550b787b 100644 (file)
@@ -1055,11 +1055,6 @@ void StmtPrinter::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *Node) {
   OS << Node->getType().getAsString() << "()";
 }
 
-void
-StmtPrinter::VisitCXXConditionDeclExpr(CXXConditionDeclExpr *E) {
-  PrintRawDecl(E->getVarDecl());
-}
-
 void StmtPrinter::VisitCXXNewExpr(CXXNewExpr *E) {
   if (E->isGlobalNew())
     OS << "::";
index 2699cdfc4fd611e0ee5558b2788864898aac1588..201724e8617b953dc3acbfa6ccb11fd813fe0eb0 100644 (file)
@@ -108,14 +108,17 @@ void StmtProfiler::VisitLabelStmt(LabelStmt *S) {
 
 void StmtProfiler::VisitIfStmt(IfStmt *S) {
   VisitStmt(S);
+  VisitDecl(S->getConditionVariable());
 }
 
 void StmtProfiler::VisitSwitchStmt(SwitchStmt *S) {
   VisitStmt(S);
+  VisitDecl(S->getConditionVariable());
 }
 
 void StmtProfiler::VisitWhileStmt(WhileStmt *S) {
   VisitStmt(S);
+  VisitDecl(S->getConditionVariable());
 }
 
 void StmtProfiler::VisitDoStmt(DoStmt *S) {
@@ -481,10 +484,6 @@ void StmtProfiler::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *S) {
   VisitExpr(S);
 }
 
-void StmtProfiler::VisitCXXConditionDeclExpr(CXXConditionDeclExpr *S) {
-  VisitDeclRefExpr(S);
-}
-
 void StmtProfiler::VisitCXXDeleteExpr(CXXDeleteExpr *S) {
   VisitExpr(S);
   ID.AddBoolean(S->isGlobalDelete());
index 2c7ea9b60ea4ad7474b9b3e621f2aa704de84139..853715cce2047fbfa51922b3114f87f12b571d0d 100644 (file)
@@ -258,8 +258,6 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
   case Expr::BlockDeclRefExprClass:
     return EmitBlockDeclRefLValue(cast<BlockDeclRefExpr>(E));
 
-  case Expr::CXXConditionDeclExprClass:
-    return EmitCXXConditionDeclLValue(cast<CXXConditionDeclExpr>(E));
   case Expr::CXXTemporaryObjectExprClass:
   case Expr::CXXConstructExprClass:
     return EmitCXXConstructLValue(cast<CXXConstructExpr>(E));
@@ -1476,12 +1474,6 @@ LValue CodeGenFunction::EmitVAArgExprLValue(const VAArgExpr *E) {
   return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
 }
 
-LValue
-CodeGenFunction::EmitCXXConditionDeclLValue(const CXXConditionDeclExpr *E) {
-  EmitLocalBlockVarDecl(*E->getVarDecl());
-  return EmitDeclRefLValue(E);
-}
-
 LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) {
   llvm::Value *Temp = CreateTempAlloca(ConvertTypeForMem(E->getType()), "tmp");
   EmitCXXConstructExpr(Temp, E);
index 6fddcf6b0414d93eb96789035b353c63c259dcdc..be571fac717bb040dbfca1d36b6a38cdd271e1c6 100644 (file)
@@ -479,6 +479,7 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S) {
 void CodeGenFunction::EmitForStmt(const ForStmt &S) {
   // FIXME: What do we do if the increment (f.e.) contains a stmt expression,
   // which contains a continue/break?
+  CleanupScope ForScope(*this);
 
   // Evaluate the first part before the loop.
   if (S.getInit())
@@ -490,9 +491,18 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S) {
 
   EmitBlock(CondBlock);
 
+  // Create a cleanup scope 
+  CleanupScope ConditionScope(*this);
+  
   // Evaluate the condition if present.  If not, treat it as a
   // non-zero-constant according to 6.8.5.3p2, aka, true.
   if (S.getCond()) {
+    // If the for statement has a condition scope, emit the local variable
+    // declaration.
+    // FIXME: The cleanup points for this are all wrong.
+    if (S.getConditionVariable())
+      EmitLocalBlockVarDecl(*S.getConditionVariable());
+    
     // As long as the condition is true, iterate the loop.
     llvm::BasicBlock *ForBody = createBasicBlock("for.body");
 
index a42fa51265e0aa9139e87fab6e71c92e0f9679b8..4fde0dd864fce6fb338a017ad1d32cecb24ed3ea 100644 (file)
@@ -916,7 +916,6 @@ public:
 
   LValue EmitBlockDeclRefLValue(const BlockDeclRefExpr *E);
 
-  LValue EmitCXXConditionDeclLValue(const CXXConditionDeclExpr *E);
   LValue EmitCXXConstructLValue(const CXXConstructExpr *E);
   LValue EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E);
   LValue EmitCXXExprWithTemporariesLValue(const CXXExprWithTemporaries *E);
index ea2c979c52cb77fb204ed8affb87da9af4758583..00734a0854a4f7346dcc0768e2434e57a329c135 100644 (file)
@@ -231,6 +231,7 @@ unsigned PCHStmtReader::VisitForStmt(ForStmt *S) {
   VisitStmt(S);
   S->setInit(StmtStack[StmtStack.size() - 4]);
   S->setCond(cast_or_null<Expr>(StmtStack[StmtStack.size() - 3]));
+  S->setConditionVariable(cast_or_null<VarDecl>(Reader.GetDecl(Record[Idx++])));
   S->setInc(cast_or_null<Expr>(StmtStack[StmtStack.size() - 2]));
   S->setBody(StmtStack.back());
   S->setForLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
index 5138776a9060c7d7a3ee23122dd808ec3223b580..27b83ed6cbb256c9aa13fdcc320dea751b8d90a3 100644 (file)
@@ -214,6 +214,7 @@ void PCHStmtWriter::VisitForStmt(ForStmt *S) {
   VisitStmt(S);
   Writer.WriteSubStmt(S->getInit());
   Writer.WriteSubStmt(S->getCond());
+  Writer.AddDeclRef(S->getConditionVariable(), Record);
   Writer.WriteSubStmt(S->getInc());
   Writer.WriteSubStmt(S->getBody());
   Writer.AddSourceLocation(S->getForLoc(), Record);
index deb5498b906ed21ba15bcba1c8a4bad15224fdcd..c5dc979f654b3616ba1f2a7fc27eb8107d554c8b 100644 (file)
@@ -305,14 +305,16 @@ namespace {
     }
 
     virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc,
-                                         FullExprArg CondVal, StmtArg ThenVal,
+                                         FullExprArg CondVal, DeclPtrTy CondVar,
+                                         StmtArg ThenVal,
                                          SourceLocation ElseLoc,
                                          StmtArg ElseVal) {
       Out << __FUNCTION__ << "\n";
       return StmtEmpty();
     }
 
-    virtual OwningStmtResult ActOnStartOfSwitchStmt(ExprArg Cond) {
+    virtual OwningStmtResult ActOnStartOfSwitchStmt(FullExprArg Cond, 
+                                                    DeclPtrTy CondVar) {
       Out << __FUNCTION__ << "\n";
       return StmtEmpty();
     }
@@ -325,7 +327,8 @@ namespace {
     }
 
     virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc,
-                                            FullExprArg Cond, StmtArg Body) {
+                                            FullExprArg Cond, DeclPtrTy CondVar,
+                                            StmtArg Body) {
       Out << __FUNCTION__ << "\n";
       return StmtEmpty();
     }
@@ -338,8 +341,10 @@ namespace {
     }
     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) {
       Out << __FUNCTION__ << "\n";
       return StmtEmpty();
index 4a3c0bf1c60f019c3732dc0d32a1938ccb69ef46..b98417fc3190f302b97313ad90076deacd251487 100644 (file)
@@ -61,8 +61,6 @@ namespace  {
             Doc.PrintDecl(*DI);
           }
         } else {
-          if (CXXConditionDeclExpr* CCDE = dyn_cast<CXXConditionDeclExpr>(S))
-            Doc.PrintDecl(CCDE->getVarDecl());
           for (Stmt::child_iterator i = S->child_begin(), e = S->child_end();
                i != e; ++i)
             DumpSubTree(*i);
index 56484720db2d37b951664ef87494283524979828..157d8837a934b192a2e8c523aae2fb403a6de450 100644 (file)
@@ -549,7 +549,7 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
                                            CommaLocs.data(), RParenLoc);
 }
 
-/// ParseCXXCondition - if/switch/while/for condition expression.
+/// ParseCXXCondition - if/switch/while condition expression.
 ///
 ///       condition:
 ///         expression
@@ -557,11 +557,20 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
 /// [GNU]   type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
 ///             '=' assignment-expression
 ///
-Parser::OwningExprResult Parser::ParseCXXCondition() {
-  if (!isCXXConditionDeclaration())
-    return ParseExpression(); // expression
-
-  SourceLocation StartLoc = Tok.getLocation();
+/// \param ExprResult if the condition was parsed as an expression, the
+/// parsed expression.
+///
+/// \param DeclResult if the condition was parsed as a declaration, the
+/// parsed declaration.
+///
+/// \returns true if there was a parsing, false otherwise.
+bool Parser::ParseCXXCondition(OwningExprResult &ExprResult,
+                               DeclPtrTy &DeclResult) {
+  if (!isCXXConditionDeclaration()) {
+    ExprResult = ParseExpression(); // expression
+    DeclResult = DeclPtrTy();
+    return ExprResult.isInvalid();
+  }
 
   // type-specifier-seq
   DeclSpec DS;
@@ -577,7 +586,7 @@ Parser::OwningExprResult Parser::ParseCXXCondition() {
     OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
     if (AsmLabel.isInvalid()) {
       SkipUntil(tok::semi);
-      return ExprError();
+      return true;
     }
     DeclaratorInfo.setAsmLabel(AsmLabel.release());
     DeclaratorInfo.SetRangeEnd(Loc);
@@ -590,17 +599,24 @@ Parser::OwningExprResult Parser::ParseCXXCondition() {
     DeclaratorInfo.AddAttributes(AttrList, Loc);
   }
 
+  // Type-check the declaration itself.
+  Action::DeclResult Dcl = Actions.ActOnCXXConditionDeclaration(CurScope, 
+                                                                DeclaratorInfo);
+  DeclResult = Dcl.get();
+  ExprResult = ExprError();
+  
   // '=' assignment-expression
-  if (Tok.isNot(tok::equal))
-    return ExprError(Diag(Tok, diag::err_expected_equal_after_declarator));
-  SourceLocation EqualLoc = ConsumeToken();
-  OwningExprResult AssignExpr(ParseAssignmentExpression());
-  if (AssignExpr.isInvalid())
-    return ExprError();
-
-  return Actions.ActOnCXXConditionDeclarationExpr(CurScope, StartLoc,
-                                                  DeclaratorInfo,EqualLoc,
-                                                  move(AssignExpr));
+  if (Tok.is(tok::equal)) {
+    SourceLocation EqualLoc = ConsumeToken();
+    OwningExprResult AssignExpr(ParseAssignmentExpression());
+    if (!AssignExpr.isInvalid()) 
+      Actions.AddInitializerToDecl(DeclResult, move(AssignExpr));
+  } else {
+    // FIXME: C++0x allows a braced-init-list
+    Diag(Tok, diag::err_expected_equal_after_declarator);
+  }
+  
+  return false;
 }
 
 /// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
index 294f8729884f562589670a5f456d5991348acca6..2022fa51cfde5a8df34ab47aa34a4ccfd3daf195 100644 (file)
@@ -517,22 +517,22 @@ Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
 /// should try to recover harder.  It returns false if the condition is
 /// successfully parsed.  Note that a successful parse can still have semantic
 /// errors in the condition.
-bool Parser::ParseParenExprOrCondition(OwningExprResult &CondExp,
-                                       bool OnlyAllowCondition,
-                                       SourceLocation *LParenLocPtr,
-                                       SourceLocation *RParenLocPtr) {
+bool Parser::ParseParenExprOrCondition(OwningExprResult &ExprResult,
+                                       DeclPtrTy &DeclResult) {
+  bool ParseError = false;
+  
   SourceLocation LParenLoc = ConsumeParen();
-  if (LParenLocPtr) *LParenLocPtr = LParenLoc;
-
-  if (getLang().CPlusPlus)
-    CondExp = ParseCXXCondition();
-  else
-    CondExp = ParseExpression();
+  if (getLang().CPlusPlus) 
+    ParseError = ParseCXXCondition(ExprResult, DeclResult);
+  else {
+    ExprResult = ParseExpression();
+    DeclResult = DeclPtrTy();
+  }
 
   // If the parser was confused by the condition and we don't have a ')', try to
   // recover by skipping ahead to a semi and bailing out.  If condexp is
   // semantically invalid but we have well formed code, keep going.
-  if (CondExp.isInvalid() && Tok.isNot(tok::r_paren)) {
+  if (ExprResult.isInvalid() && !DeclResult.get() && Tok.isNot(tok::r_paren)) {
     SkipUntil(tok::semi);
     // Skipping may have stopped if it found the containing ')'.  If so, we can
     // continue parsing the if statement.
@@ -541,8 +541,7 @@ bool Parser::ParseParenExprOrCondition(OwningExprResult &CondExp,
   }
 
   // Otherwise the condition is valid or the rparen is present.
-  SourceLocation RPLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
-  if (RParenLocPtr) *RParenLocPtr = RPLoc;
+  MatchRHSPunctuation(tok::r_paren, LParenLoc);
   return false;
 }
 
@@ -583,7 +582,8 @@ Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
 
   // Parse the condition.
   OwningExprResult CondExp(Actions);
-  if (ParseParenExprOrCondition(CondExp))
+  DeclPtrTy CondVar;
+  if (ParseParenExprOrCondition(CondExp, CondVar))
     return StmtError();
 
   FullExprArg FullCondExp(Actions.FullExpr(CondExp));
@@ -650,7 +650,7 @@ Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
 
   // If the condition was invalid, discard the if statement.  We could recover
   // better by replacing it with a valid expr, but don't do that yet.
-  if (CondExp.isInvalid())
+  if (CondExp.isInvalid() && !CondVar.get())
     return StmtError();
 
   // If the then or else stmt is invalid and the other is valid (and present),
@@ -669,7 +669,7 @@ Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
   if (ElseStmt.isInvalid())
     ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
 
-  return Actions.ActOnIfStmt(IfLoc, FullCondExp, move(ThenStmt),
+  return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, move(ThenStmt),
                              ElseLoc, move(ElseStmt));
 }
 
@@ -709,12 +709,15 @@ Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
 
   // Parse the condition.
   OwningExprResult Cond(Actions);
-  if (ParseParenExprOrCondition(Cond))
+  DeclPtrTy CondVar;
+  if (ParseParenExprOrCondition(Cond, CondVar))
     return StmtError();
 
+  FullExprArg FullCond(Actions.FullExpr(Cond));
+  
   OwningStmtResult Switch(Actions);
-  if (!Cond.isInvalid())
-    Switch = Actions.ActOnStartOfSwitchStmt(move(Cond));
+  if (!Cond.isInvalid() || CondVar.get())
+    Switch = Actions.ActOnStartOfSwitchStmt(FullCond, CondVar);
 
   // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if
   // there is no compound stmt.  C90 does not have this clause.  We only do this
@@ -743,7 +746,7 @@ Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
 
   SwitchScope.Exit();
 
-  if (Cond.isInvalid())
+  if (Cond.isInvalid() && !CondVar.get())
     return StmtError();
 
   return Actions.ActOnFinishSwitchStmt(SwitchLoc, move(Switch), move(Body));
@@ -789,7 +792,8 @@ Parser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) {
 
   // Parse the condition.
   OwningExprResult Cond(Actions);
-  if (ParseParenExprOrCondition(Cond))
+  DeclPtrTy CondVar;
+  if (ParseParenExprOrCondition(Cond, CondVar))
     return StmtError();
 
   FullExprArg FullCond(Actions.FullExpr(Cond));
@@ -815,10 +819,10 @@ Parser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) {
   InnerScope.Exit();
   WhileScope.Exit();
 
-  if (Cond.isInvalid() || Body.isInvalid())
+  if ((Cond.isInvalid() && !CondVar.get()) || Body.isInvalid())
     return StmtError();
 
-  return Actions.ActOnWhileStmt(WhileLoc, FullCond, move(Body));
+  return Actions.ActOnWhileStmt(WhileLoc, FullCond, CondVar, move(Body));
 }
 
 /// ParseDoStatement
@@ -943,7 +947,8 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
   bool ForEach = false;
   OwningStmtResult FirstPart(Actions);
   OwningExprResult SecondPart(Actions), ThirdPart(Actions);
-
+  DeclPtrTy SecondVar;
+  
   if (Tok.is(tok::code_completion)) {
     Actions.CodeCompleteOrdinaryName(CurScope);
     ConsumeToken();
@@ -1001,13 +1006,17 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
     if (Tok.is(tok::semi)) {  // for (...;;
       // no second part.
     } else {
-      SecondPart =getLang().CPlusPlus ? ParseCXXCondition() : ParseExpression();
+      if (getLang().CPlusPlus)
+        ParseCXXCondition(SecondPart, SecondVar);
+      else
+        SecondPart = ParseExpression();
     }
 
     if (Tok.is(tok::semi)) {
       ConsumeToken();
     } else {
-      if (!SecondPart.isInvalid()) Diag(Tok, diag::err_expected_semi_for);
+      if (!SecondPart.isInvalid() || SecondVar.get()) 
+        Diag(Tok, diag::err_expected_semi_for);
       SkipUntil(tok::semi);
     }
 
@@ -1046,8 +1055,9 @@ Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
 
   if (!ForEach)
     return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart),
-                              move(SecondPart), move(ThirdPart),
-                              RParenLoc, move(Body));
+                                Actions.FullExpr(SecondPart), SecondVar,
+                                Actions.FullExpr(ThirdPart), RParenLoc, 
+                                move(Body));
 
   return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
                                             move(FirstPart),
index feff59a0264952d56dd77c70c259c78610f38af6..19a255ce6ae30543c4285875437bd0abb164580d 100644 (file)
@@ -1266,13 +1266,16 @@ public:
                                           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 @@ public:
 
   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 @@ public:
                                           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
index b5419c1c907e50643fd1dc1f7f3429294a04350e..1df11731215d417313c064c6ec3814f90e6d1c97 100644 (file)
@@ -4918,3 +4918,39 @@ void Sema::ActOnCXXExitDeclInitializer(Scope *S, DeclPtrTy Dcl) {
   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;
+}
index 40e5707028baaa83472ca2eaf8bf6003f06e884a..3b18b3a1ba9b63e1866b6a1ea3bc34bd5ca0647b 100644 (file)
@@ -943,56 +943,6 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
                                            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 @@ Action::OwningExprResult Sema::CheckConditionVariable(VarDecl *ConditionVar) {
                           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.
index 61d48cb63eb40f6188c4dde9a8085b37edd04b0a..be9a09bc1dcdbe7be74b19a121b68a590b1be843 100644 (file)
@@ -236,25 +236,24 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, IdentifierInfo *II,
 }
 
 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 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal,
   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 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,
 }
 
 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 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, StmtArg Body,
 
 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 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc,
       }
     }
   }
+
+  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
index 202e16e31e36d18fa6d5a7317c7968f6572af449..1071aebe17721eb8e1f0557fae82371dfda579c1 100644 (file)
@@ -95,7 +95,8 @@ public:
   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 @@ public:
   /// 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 @@ public:
   /// 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 @@ public:
   /// 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 @@ public:
                                                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 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
                    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 @@ TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
 
   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 @@ TreeTransform<Derived>::TransformSwitchStmt(SwitchStmt *S) {
                    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 @@ TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) {
                    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 @@ TreeTransform<Derived>::TransformWhileStmt(WhileStmt *S) {
 
   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 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
     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 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
     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));
 }
 
@@ -4416,24 +4430,6 @@ TreeTransform<Derived>::TransformCXXZeroInitValueExpr(CXXZeroInitValueExpr *E,
                                                   E->getRParenLoc());
 }
 
-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,
index 0bb9121f7f3c2ff54c3df77740bc710912944102..198c93b664c0cab73d366cf7a966f3d591988c26 100644 (file)
@@ -89,3 +89,17 @@ void while_destruct(int z) {
   // CHECK: store i32 22
   z = 22;
 }
+
+void for_destruct(int z) {
+  // CHECK: define void @_Z12for_destruct
+  // CHECK: call void @_ZN1XC1Ev
+  for(X x = X(); z; ++z)
+    // CHECK: for.body:
+    // CHECK: store i32 23
+    z = 23;
+    // CHECK: for.inc:
+  // CHECK: for.end
+  // CHECK: call void @_ZN1XD1Ev
+  // CHECK: store i32 24
+  z = 24;
+}
index 7c9cee59da6f28b7c7d37cead1108197bce693b3..b2645d4fe0fa682e6671fac265fe6995de5dfdb7 100644 (file)
@@ -33,3 +33,11 @@ void test() {
   for (; int x=0; ) { int x; } // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}}
   switch (int x=0) { default: int x; } // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}}
 }
+
+int* get_int_ptr();
+
+void test2() {
+  float *ip;
+  if (int *ip = ip) {
+  }
+}