diff options
Diffstat (limited to 'clang/lib/Parse/ParseStmt.cpp')
| -rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 80 |
1 files changed, 46 insertions, 34 deletions
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index c849554238e..8173d09cbbe 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -1052,28 +1052,29 @@ StmtResult 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(Sema::ConditionResult &Cond, +bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult, + Decl *&DeclResult, SourceLocation Loc, - Sema::ConditionKind CK) { + bool ConvertToBoolean) { BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); if (getLangOpts().CPlusPlus) - Cond = ParseCXXCondition(Loc, CK); + ParseCXXCondition(ExprResult, DeclResult, Loc, ConvertToBoolean); else { - ExprResult CondExpr = ParseExpression(); + ExprResult = ParseExpression(); + DeclResult = nullptr; // If required, convert to a boolean value. - if (CondExpr.isInvalid()) - Cond = Sema::ConditionError(); - else - Cond = Actions.ActOnCondition(getCurScope(), Loc, CondExpr.get(), CK); + if (!ExprResult.isInvalid() && ConvertToBoolean) + ExprResult + = Actions.ActOnBooleanCondition(getCurScope(), Loc, ExprResult.get()); } // 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 (Cond.isInvalid() && Tok.isNot(tok::r_paren)) { + if (ExprResult.isInvalid() && !DeclResult && 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. @@ -1131,10 +1132,13 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX); // Parse the condition. - Sema::ConditionResult Cond; - if (ParseParenExprOrCondition(Cond, IfLoc, Sema::ConditionKind::Boolean)) + ExprResult CondExp; + Decl *CondVar = nullptr; + if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true)) return StmtError(); + FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get(), IfLoc)); + // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this // if the body isn't a compound statement to avoid push/pop in common cases. @@ -1217,8 +1221,8 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { if (ElseStmt.isInvalid()) ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc); - return Actions.ActOnIfStmt(IfLoc, Cond, ThenStmt.get(), ElseLoc, - ElseStmt.get()); + return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, ThenStmt.get(), + ElseLoc, ElseStmt.get()); } /// ParseSwitchStatement @@ -1255,11 +1259,13 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) { ParseScope SwitchScope(this, ScopeFlags); // Parse the condition. - Sema::ConditionResult Cond; - if (ParseParenExprOrCondition(Cond, SwitchLoc, Sema::ConditionKind::Switch)) + ExprResult Cond; + Decl *CondVar = nullptr; + if (ParseParenExprOrCondition(Cond, CondVar, SwitchLoc, false)) return StmtError(); - StmtResult Switch = Actions.ActOnStartOfSwitchStmt(SwitchLoc, Cond); + StmtResult Switch + = Actions.ActOnStartOfSwitchStmt(SwitchLoc, Cond.get(), CondVar); if (Switch.isInvalid()) { // Skip the switch body. @@ -1341,10 +1347,13 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) { ParseScope WhileScope(this, ScopeFlags); // Parse the condition. - Sema::ConditionResult Cond; - if (ParseParenExprOrCondition(Cond, WhileLoc, Sema::ConditionKind::Boolean)) + ExprResult Cond; + Decl *CondVar = nullptr; + if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true)) return StmtError(); + FullExprArg FullCond(Actions.MakeFullExpr(Cond.get(), WhileLoc)); + // C99 6.8.5p5 - In C99, the body of the while statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this // if the body isn't a compound statement to avoid push/pop in common cases. @@ -1365,10 +1374,10 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) { InnerScope.Exit(); WhileScope.Exit(); - if (Cond.isInvalid() || Body.isInvalid()) + if ((Cond.isInvalid() && !CondVar) || Body.isInvalid()) return StmtError(); - return Actions.ActOnWhileStmt(WhileLoc, Cond, Body.get()); + return Actions.ActOnWhileStmt(WhileLoc, FullCond, CondVar, Body.get()); } /// ParseDoStatement @@ -1526,10 +1535,12 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { bool ForEach = false, ForRange = false; StmtResult FirstPart; - Sema::ConditionResult SecondPart; + bool SecondPartIsInvalid = false; + FullExprArg SecondPart(Actions); ExprResult Collection; ForRangeInit ForRangeInit; FullExprArg ThirdPart(Actions); + Decl *SecondVar = nullptr; if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), @@ -1634,7 +1645,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { Diag(Tok, diag::err_for_range_expected_decl) << FirstPart.get()->getSourceRange(); SkipUntil(tok::r_paren, StopBeforeMatch); - SecondPart = Sema::ConditionError(); + SecondPartIsInvalid = true; } else { if (!Value.isInvalid()) { Diag(Tok, diag::err_expected_semi_for); @@ -1649,28 +1660,29 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { // Parse the second part of the for specifier. getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope); - if (!ForEach && !ForRange && !SecondPart.isInvalid()) { + if (!ForEach && !ForRange) { + assert(!SecondPart.get() && "Shouldn't have a second expression yet."); // Parse the second part of the for specifier. if (Tok.is(tok::semi)) { // for (...;; // no second part. } else if (Tok.is(tok::r_paren)) { // missing both semicolons. } else { + ExprResult Second; if (getLangOpts().CPlusPlus) - SecondPart = ParseCXXCondition(ForLoc, Sema::ConditionKind::Boolean); + ParseCXXCondition(Second, SecondVar, ForLoc, true); else { - ExprResult SecondExpr = ParseExpression(); - if (SecondExpr.isInvalid()) - SecondPart = Sema::ConditionError(); - else - SecondPart = - Actions.ActOnCondition(getCurScope(), ForLoc, SecondExpr.get(), - Sema::ConditionKind::Boolean); + Second = ParseExpression(); + if (!Second.isInvalid()) + Second = Actions.ActOnBooleanCondition(getCurScope(), ForLoc, + Second.get()); } + SecondPartIsInvalid = Second.isInvalid(); + SecondPart = Actions.MakeFullExpr(Second.get(), ForLoc); } if (Tok.isNot(tok::semi)) { - if (!SecondPart.isInvalid()) + if (!SecondPartIsInvalid || SecondVar) Diag(Tok, diag::err_expected_semi_for); else // Skip until semicolon or rparen, don't consume it. @@ -1769,8 +1781,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get()); return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(), - SecondPart, ThirdPart, T.getCloseLocation(), - Body.get()); + SecondPart, SecondVar, ThirdPart, + T.getCloseLocation(), Body.get()); } /// ParseGotoStatement |

