diff options
Diffstat (limited to 'clang/lib/Parse/ParseStmt.cpp')
| -rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 96 |
1 files changed, 69 insertions, 27 deletions
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index bf1978c22ee9..62361c066a3f 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -37,23 +37,25 @@ using namespace clang; //===----------------------------------------------------------------------===// StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc, - ParsedStmtContext StmtCtx) { + ParsedStmtContext StmtCtx, + LabelDecl *PrecedingLabel) { StmtResult Res; // We may get back a null statement if we found a #pragma. Keep going until // we get an actual statement. StmtVector Stmts; do { - Res = ParseStatementOrDeclaration(Stmts, StmtCtx, TrailingElseLoc); + Res = ParseStatementOrDeclaration(Stmts, StmtCtx, TrailingElseLoc, + PrecedingLabel); } while (!Res.isInvalid() && !Res.get()); return Res; } -StmtResult -Parser::ParseStatementOrDeclaration(StmtVector &Stmts, - ParsedStmtContext StmtCtx, - SourceLocation *TrailingElseLoc) { +StmtResult Parser::ParseStatementOrDeclaration(StmtVector &Stmts, + ParsedStmtContext StmtCtx, + SourceLocation *TrailingElseLoc, + LabelDecl *PrecedingLabel) { ParenBraceBracketBalancer BalancerRAIIObj(*this); @@ -73,7 +75,8 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, MaybeParseMicrosoftAttributes(GNUOrMSAttrs); StmtResult Res = ParseStatementOrDeclarationAfterAttributes( - Stmts, StmtCtx, TrailingElseLoc, CXX11Attrs, GNUOrMSAttrs); + Stmts, StmtCtx, TrailingElseLoc, CXX11Attrs, GNUOrMSAttrs, + PrecedingLabel); MaybeDestroyTemplateIds(); takeAndConcatenateAttrs(CXX11Attrs, std::move(GNUOrMSAttrs)); @@ -130,7 +133,7 @@ private: StmtResult Parser::ParseStatementOrDeclarationAfterAttributes( StmtVector &Stmts, ParsedStmtContext StmtCtx, SourceLocation *TrailingElseLoc, ParsedAttributes &CXX11Attrs, - ParsedAttributes &GNUAttrs) { + ParsedAttributes &GNUAttrs, LabelDecl *PrecedingLabel) { const char *SemiError = nullptr; StmtResult Res; SourceLocation GNUAttributeLoc; @@ -278,16 +281,16 @@ Retry: case tok::kw_if: // C99 6.8.4.1: if-statement return ParseIfStatement(TrailingElseLoc); case tok::kw_switch: // C99 6.8.4.2: switch-statement - return ParseSwitchStatement(TrailingElseLoc); + return ParseSwitchStatement(TrailingElseLoc, PrecedingLabel); case tok::kw_while: // C99 6.8.5.1: while-statement - return ParseWhileStatement(TrailingElseLoc); + return ParseWhileStatement(TrailingElseLoc, PrecedingLabel); case tok::kw_do: // C99 6.8.5.2: do-statement - Res = ParseDoStatement(); + Res = ParseDoStatement(PrecedingLabel); SemiError = "do/while"; break; case tok::kw_for: // C99 6.8.5.3: for-statement - return ParseForStatement(TrailingElseLoc); + return ParseForStatement(TrailingElseLoc, PrecedingLabel); case tok::kw_goto: // C99 6.8.6.1: goto-statement Res = ParseGotoStatement(); @@ -483,7 +486,8 @@ Retry: case tok::annot_pragma_loop_hint: ProhibitAttributes(CXX11Attrs); ProhibitAttributes(GNUAttrs); - return ParsePragmaLoopHint(Stmts, StmtCtx, TrailingElseLoc, CXX11Attrs); + return ParsePragmaLoopHint(Stmts, StmtCtx, TrailingElseLoc, CXX11Attrs, + PrecedingLabel); case tok::annot_pragma_dump: ProhibitAttributes(CXX11Attrs); @@ -697,6 +701,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &Attrs, // identifier ':' statement SourceLocation ColonLoc = ConsumeToken(); + LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(), + IdentTok.getLocation()); + // Read label attributes, if present. StmtResult SubStmt; if (Tok.is(tok::kw___attribute)) { @@ -716,7 +723,8 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &Attrs, StmtVector Stmts; ParsedAttributes EmptyCXX11Attrs(AttrFactory); SubStmt = ParseStatementOrDeclarationAfterAttributes( - Stmts, StmtCtx, nullptr, EmptyCXX11Attrs, TempAttrs); + Stmts, StmtCtx, /*TrailingElseLoc=*/nullptr, EmptyCXX11Attrs, + TempAttrs, LD); if (!TempAttrs.empty() && !SubStmt.isInvalid()) SubStmt = Actions.ActOnAttributedStmt(TempAttrs, SubStmt.get()); } @@ -730,7 +738,7 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &Attrs, // If we've not parsed a statement yet, parse one now. if (SubStmt.isUnset()) - SubStmt = ParseStatement(nullptr, StmtCtx); + SubStmt = ParseStatement(nullptr, StmtCtx, LD); // Broken substmt shouldn't prevent the label from being added to the AST. if (SubStmt.isInvalid()) @@ -738,8 +746,6 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &Attrs, DiagnoseLabelFollowedByDecl(*this, SubStmt.get()); - LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(), - IdentTok.getLocation()); Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs); Attrs.clear(); @@ -1620,7 +1626,8 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { ThenStmt.get(), ElseLoc, ElseStmt.get()); } -StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) { +StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc, + LabelDecl *PrecedingLabel) { assert(Tok.is(tok::kw_switch) && "Not a switch stmt!"); SourceLocation SwitchLoc = ConsumeToken(); // eat the 'switch'. @@ -1686,6 +1693,7 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) { // condition and a new scope for substatement in C++. // getCurScope()->AddFlags(Scope::BreakScope); + getCurScope()->setPrecedingLabel(PrecedingLabel); ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); // We have incremented the mangling number for the SwitchScope and the @@ -1703,7 +1711,8 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) { return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.get(), Body.get()); } -StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) { +StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc, + LabelDecl *PrecedingLabel) { assert(Tok.is(tok::kw_while) && "Not a while stmt!"); SourceLocation WhileLoc = Tok.getLocation(); ConsumeToken(); // eat the 'while'. @@ -1748,6 +1757,7 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) { // combinations, so diagnose that here in OpenACC mode. SemaOpenACC::LoopInConstructRAII LCR{getActions().OpenACC()}; getActions().OpenACC().ActOnWhileStmt(WhileLoc); + getCurScope()->setPrecedingLabel(PrecedingLabel); // 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 @@ -1779,7 +1789,7 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) { return Actions.ActOnWhileStmt(WhileLoc, LParen, Cond, RParen, Body.get()); } -StmtResult Parser::ParseDoStatement() { +StmtResult Parser::ParseDoStatement(LabelDecl *PrecedingLabel) { assert(Tok.is(tok::kw_do) && "Not a do stmt!"); SourceLocation DoLoc = ConsumeToken(); // eat the 'do'. @@ -1797,6 +1807,7 @@ StmtResult Parser::ParseDoStatement() { // combinations, so diagnose that here in OpenACC mode. SemaOpenACC::LoopInConstructRAII LCR{getActions().OpenACC()}; getActions().OpenACC().ActOnDoStmt(DoLoc); + getCurScope()->setPrecedingLabel(PrecedingLabel); // C99 6.8.5p5 - In C99, the body of the do statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this @@ -1815,6 +1826,9 @@ StmtResult Parser::ParseDoStatement() { // Pop the body scope if needed. InnerScope.Exit(); + // Reset this to disallow break/continue out of the condition. + getCurScope()->setPrecedingLabel(nullptr); + if (Tok.isNot(tok::kw_while)) { if (!Body.isInvalid()) { Diag(Tok, diag::err_expected_while); @@ -1876,7 +1890,8 @@ bool Parser::isForRangeIdentifier() { return false; } -StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { +StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc, + LabelDecl *PrecedingLabel) { assert(Tok.is(tok::kw_for) && "Not a for stmt!"); SourceLocation ForLoc = ConsumeToken(); // eat the 'for'. @@ -2208,6 +2223,10 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { getActions().OpenACC().ActOnForStmtBegin( ForLoc, FirstPart.get(), SecondPart.get().second, ThirdPart.get()); + // Set this only right before parsing the body to disallow break/continue in + // the other parts. + getCurScope()->setPrecedingLabel(PrecedingLabel); + // C99 6.8.5p5 - In C99, the body of the for 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. @@ -2288,14 +2307,35 @@ StmtResult Parser::ParseGotoStatement() { return Res; } +StmtResult Parser::ParseBreakOrContinueStatement(bool IsContinue) { + SourceLocation KwLoc = ConsumeToken(); // Eat the keyword. + SourceLocation LabelLoc; + LabelDecl *Target = nullptr; + if (Tok.is(tok::identifier)) { + Target = + Actions.LookupExistingLabel(Tok.getIdentifierInfo(), Tok.getLocation()); + LabelLoc = ConsumeToken(); + if (!getLangOpts().NamedLoops) + // TODO: Make this a compatibility/extension warning instead once the + // syntax of this feature is finalised. + Diag(LabelLoc, diag::err_c2y_labeled_break_continue) << IsContinue; + if (!Target) { + Diag(LabelLoc, diag::err_break_continue_label_not_found) << IsContinue; + return StmtError(); + } + } + + if (IsContinue) + return Actions.ActOnContinueStmt(KwLoc, getCurScope(), Target, LabelLoc); + return Actions.ActOnBreakStmt(KwLoc, getCurScope(), Target, LabelLoc); +} + StmtResult Parser::ParseContinueStatement() { - SourceLocation ContinueLoc = ConsumeToken(); // eat the 'continue'. - return Actions.ActOnContinueStmt(ContinueLoc, getCurScope()); + return ParseBreakOrContinueStatement(/*IsContinue=*/true); } StmtResult Parser::ParseBreakStatement() { - SourceLocation BreakLoc = ConsumeToken(); // eat the 'break'. - return Actions.ActOnBreakStmt(BreakLoc, getCurScope()); + return ParseBreakOrContinueStatement(/*IsContinue=*/false); } StmtResult Parser::ParseReturnStatement() { @@ -2339,7 +2379,8 @@ StmtResult Parser::ParseReturnStatement() { StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, ParsedStmtContext StmtCtx, SourceLocation *TrailingElseLoc, - ParsedAttributes &Attrs) { + ParsedAttributes &Attrs, + LabelDecl *PrecedingLabel) { // Create temporary attribute list. ParsedAttributes TempAttrs(AttrFactory); @@ -2363,7 +2404,8 @@ StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); StmtResult S = ParseStatementOrDeclarationAfterAttributes( - Stmts, StmtCtx, TrailingElseLoc, Attrs, EmptyDeclSpecAttrs); + Stmts, StmtCtx, TrailingElseLoc, Attrs, EmptyDeclSpecAttrs, + PrecedingLabel); Attrs.takeAllFrom(TempAttrs); |
