diff options
Diffstat (limited to 'clang/lib/Parse/ParseStmt.cpp')
| -rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 63 |
1 files changed, 40 insertions, 23 deletions
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 574293f5181..ba7c808838e 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -1570,11 +1570,11 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { ExprResult Value; - bool ForEach = false, ForRange = false; + bool ForEach = false; StmtResult FirstPart; Sema::ConditionResult SecondPart; ExprResult Collection; - ForRangeInit ForRangeInit; + ForRangeInfo ForRangeInfo; FullExprArg ThirdPart(Actions); if (Tok.is(tok::code_completion)) { @@ -1600,20 +1600,19 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { SourceLocation Loc = ConsumeToken(); MaybeParseCXX11Attributes(attrs); - ForRangeInit.ColonLoc = ConsumeToken(); + ForRangeInfo.ColonLoc = ConsumeToken(); if (Tok.is(tok::l_brace)) - ForRangeInit.RangeExpr = ParseBraceInitializer(); + ForRangeInfo.RangeExpr = ParseBraceInitializer(); else - ForRangeInit.RangeExpr = ParseExpression(); + ForRangeInfo.RangeExpr = ParseExpression(); Diag(Loc, diag::err_for_range_identifier) << ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus17) ? FixItHint::CreateInsertion(Loc, "auto &&") : FixItHint()); - FirstPart = Actions.ActOnCXXForRangeIdentifier(getCurScope(), Loc, Name, - attrs, attrs.Range.getEnd()); - ForRange = true; + ForRangeInfo.LoopVar = Actions.ActOnCXXForRangeIdentifier( + getCurScope(), Loc, Name, attrs, attrs.Range.getEnd()); } else if (isForInitDeclaration()) { // for (int X = 4; ParenBraceBracketBalancer BalancerRAIIObj(*this); @@ -1630,13 +1629,13 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; DeclGroupPtrTy DG = ParseSimpleDeclaration( DeclaratorContext::ForContext, DeclEnd, attrs, false, - MightBeForRangeStmt ? &ForRangeInit : nullptr); + MightBeForRangeStmt ? &ForRangeInfo : nullptr); FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); - if (ForRangeInit.ParsedForRangeDecl()) { - Diag(ForRangeInit.ColonLoc, getLangOpts().CPlusPlus11 ? + if (ForRangeInfo.ParsedForRangeDecl()) { + Diag(ForRangeInfo.ColonLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_for_range : diag::ext_for_range); - - ForRange = true; + ForRangeInfo.LoopVar = FirstPart; + FirstPart = StmtResult(); } else if (Tok.is(tok::semi)) { // for (int x = 4; ConsumeToken(); } else if ((ForEach = isTokIdentifier_in())) { @@ -1699,17 +1698,33 @@ 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 && !ForRangeInfo.ParsedForRangeDecl() && + !SecondPart.isInvalid()) { // 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 { - if (getLangOpts().CPlusPlus) + if (getLangOpts().CPlusPlus) { + // C++2a: We've parsed an init-statement; we might have a + // for-range-declaration next. + bool MightBeForRangeStmt = !ForRangeInfo.ParsedForRangeDecl(); + ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt); SecondPart = - ParseCXXCondition(nullptr, ForLoc, Sema::ConditionKind::Boolean); - else { + ParseCXXCondition(nullptr, ForLoc, Sema::ConditionKind::Boolean, + MightBeForRangeStmt ? &ForRangeInfo : nullptr); + + if (ForRangeInfo.ParsedForRangeDecl()) { + Diag(FirstPart.get() ? FirstPart.get()->getBeginLoc() + : ForRangeInfo.ColonLoc, + getLangOpts().CPlusPlus2a + ? diag::warn_cxx17_compat_for_range_init_stmt + : diag::ext_for_range_init_stmt) + << (FirstPart.get() ? FirstPart.get()->getSourceRange() + : SourceRange()); + } + } else { ExprResult SecondExpr = ParseExpression(); if (SecondExpr.isInvalid()) SecondPart = Sema::ConditionError(); @@ -1719,7 +1734,10 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { Sema::ConditionKind::Boolean); } } + } + // Parse the third part of the for statement. + if (!ForEach && !ForRangeInfo.ParsedForRangeDecl()) { if (Tok.isNot(tok::semi)) { if (!SecondPart.isInvalid()) Diag(Tok, diag::err_expected_semi_for); @@ -1732,7 +1750,6 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { ConsumeToken(); } - // Parse the third part of the for specifier. if (Tok.isNot(tok::r_paren)) { // for (...;...;) ExprResult Third = ParseExpression(); // FIXME: The C++11 standard doesn't actually say that this is a @@ -1745,7 +1762,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { // C++ Coroutines [stmt.iter]: // 'co_await' can only be used for a range-based for statement. - if (CoawaitLoc.isValid() && !ForRange) { + if (CoawaitLoc.isValid() && !ForRangeInfo.ParsedForRangeDecl()) { Diag(CoawaitLoc, diag::err_for_co_await_not_range_for); CoawaitLoc = SourceLocation(); } @@ -1756,12 +1773,12 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { StmtResult ForRangeStmt; StmtResult ForEachStmt; - if (ForRange) { + if (ForRangeInfo.ParsedForRangeDecl()) { ExprResult CorrectedRange = - Actions.CorrectDelayedTyposInExpr(ForRangeInit.RangeExpr.get()); + Actions.CorrectDelayedTyposInExpr(ForRangeInfo.RangeExpr.get()); ForRangeStmt = Actions.ActOnCXXForRangeStmt( getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(), - ForRangeInit.ColonLoc, CorrectedRange.get(), + ForRangeInfo.LoopVar.get(), ForRangeInfo.ColonLoc, CorrectedRange.get(), T.getCloseLocation(), Sema::BFRK_Build); // Similarly, we need to do the semantic analysis for a for-range @@ -1816,7 +1833,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { return Actions.FinishObjCForCollectionStmt(ForEachStmt.get(), Body.get()); - if (ForRange) + if (ForRangeInfo.ParsedForRangeDecl()) return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get()); return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(), |

