@@ -271,7 +271,23 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
271271 return ParseForStatement (TrailingElseLoc, PrecedingLabel);
272272 }
273273
274- return ParseExpansionStatement (TrailingElseLoc, PrecedingLabel);
274+ SourceLocation TemplateLoc = ConsumeToken ();
275+ return ParseExpansionStatement (TrailingElseLoc, PrecedingLabel,
276+ TemplateLoc);
277+ }
278+
279+ // Since 'template for' is a thing, users might reasonably try to write
280+ // 'template while' or something like that; diagnose that here for better
281+ // QOI (and basically just ignore the 'template' token for error recovery).
282+ if (NextToken ().isOneOf (tok::kw_while, tok::kw_do)) {
283+ bool IsWhile = NextToken ().is (tok::kw_while);
284+ Diag (Tok.getLocation (), diag::err_expansion_stmt_invalid_kw)
285+ << (IsWhile ? " while" : " do" );
286+
287+ ConsumeToken ();
288+ if (IsWhile)
289+ return ParseWhileStatement (TrailingElseLoc, PrecedingLabel);
290+ return ParseDoStatement (PrecedingLabel);
275291 }
276292
277293 SourceLocation DeclEnd;
@@ -304,6 +320,19 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
304320 SemiError = " do/while" ;
305321 break ;
306322 case tok::kw_for: // C99 6.8.5.3: for-statement
323+ // Correct 'for template' to 'template for'.
324+ if (NextToken ().is (tok::kw_template)) {
325+ Diag (Tok.getLocation (), diag::err_for_template)
326+ << FixItHint::CreateReplacement (
327+ SourceRange (Tok.getLocation (), NextToken ().getEndLoc ()),
328+ " template for" );
329+ Tok.setKind (tok::kw_template);
330+ SourceLocation TemplateLoc = ConsumeToken ();
331+ Tok.setKind (tok::kw_for);
332+ return ParseExpansionStatement (TrailingElseLoc, PrecedingLabel,
333+ TemplateLoc);
334+ }
335+
307336 return ParseForStatement (TrailingElseLoc, PrecedingLabel);
308337
309338 case tok::kw_goto: // C99 6.8.6.1: goto-statement
@@ -2706,9 +2735,9 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) {
27062735}
27072736
27082737StmtResult Parser::ParseExpansionStatement (SourceLocation *TrailingElseLoc,
2709- LabelDecl *PrecedingLabel) {
2710- assert (Tok. is (tok::kw_template) && NextToken (). is (tok::kw_for));
2711- SourceLocation TemplateLoc = ConsumeToken ( );
2738+ LabelDecl *PrecedingLabel,
2739+ SourceLocation TemplateLoc) {
2740+ assert (Tok. is (tok::kw_for) );
27122741 DiagCompat (TemplateLoc, diag_compat::expansion_statements);
27132742
27142743 CXXExpansionStmtDecl *ExpansionDecl =
0 commit comments