diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-11-25 00:27:52 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-11-25 00:27:52 +0000 |
commit | 99e9b4d172f6877e6ba5ebe75bb8238721f5e01c (patch) | |
tree | 16c143b06b39022258614b713ed5999a7d7679c0 | |
parent | d1a7846699a82f85ff3ce6b2e383409537c3f5c5 (diff) |
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
27 files changed, 388 insertions, 329 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 61cb9587d6..7cf9aabc6d 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -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; } diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 63b153a17e..ce29d84c5c 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -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 { diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index b7505e1bc7..14bffd0fd7 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -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]; } diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index dd8a685a95..316521b4e4 100644 --- a/include/clang/AST/StmtNodes.def +++ b/include/clang/AST/StmtNodes.def @@ -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) diff --git a/include/clang/Frontend/StmtXML.def b/include/clang/Frontend/StmtXML.def index 332aad2dd2..2f0da9e7b1 100644 --- a/include/clang/Frontend/StmtXML.def +++ b/include/clang/Frontend/StmtXML.def @@ -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 diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 3db90c6574..4b09cabfaa 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -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 diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index b1375d7d65..30c6b90d1f 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -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); diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 9f08271694..e4de703029 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -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: diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 8591a4d8bd..0e724a8d5c 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -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, diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index a7cfed9788..7a02a451d8 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -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 << "::"; diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp index 2699cdfc4f..201724e861 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -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()); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 2c7ea9b60e..853715cce2 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -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); diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 6fddcf6b04..be571fac71 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -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"); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index a42fa51265..4fde0dd864 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -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); diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp index ea2c979c52..00734a0854 100644 --- a/lib/Frontend/PCHReaderStmt.cpp +++ b/lib/Frontend/PCHReaderStmt.cpp @@ -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++])); diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp index 5138776a90..27b83ed6cb 100644 --- a/lib/Frontend/PCHWriterStmt.cpp +++ b/lib/Frontend/PCHWriterStmt.cpp @@ -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); diff --git a/lib/Frontend/PrintParserCallbacks.cpp b/lib/Frontend/PrintParserCallbacks.cpp index deb5498b90..c5dc979f65 100644 --- a/lib/Frontend/PrintParserCallbacks.cpp +++ b/lib/Frontend/PrintParserCallbacks.cpp @@ -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(); diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp index 4a3c0bf1c6..b98417fc31 100644 --- a/lib/Frontend/StmtXML.cpp +++ b/lib/Frontend/StmtXML.cpp @@ -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); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 56484720db..157d8837a9 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -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. diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 294f872988..2022fa51cf 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -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); |