Index: clang/include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticParseKinds.td +++ clang/include/clang/Basic/DiagnosticParseKinds.td @@ -538,6 +538,8 @@ "cannot use %select{dot|arrow}0 operator on a type">; def err_expected_unqualified_id : Error< "expected %select{identifier|unqualified-id}0">; +def err_while_loop_outside_of_a_function : Error< + "while loop outside of a function">; def err_brackets_go_after_unqualified_id : Error< "brackets are not allowed here; to declare an array, " "place the brackets after the %select{identifier|name}0">; Index: clang/lib/Parse/ParseDecl.cpp =================================================================== --- clang/lib/Parse/ParseDecl.cpp +++ clang/lib/Parse/ParseDecl.cpp @@ -6344,23 +6344,27 @@ diag::err_expected_member_name_or_semi) << (D.getDeclSpec().isEmpty() ? SourceRange() : D.getDeclSpec().getSourceRange()); - } else if (getLangOpts().CPlusPlus) { - if (Tok.isOneOf(tok::period, tok::arrow)) - Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow); - else { - SourceLocation Loc = D.getCXXScopeSpec().getEndLoc(); - if (Tok.isAtStartOfLine() && Loc.isValid()) - Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id) - << getLangOpts().CPlusPlus; - else - Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), - diag::err_expected_unqualified_id) - << getLangOpts().CPlusPlus; - } } else { - Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), - diag::err_expected_either) - << tok::identifier << tok::l_paren; + if (Tok.getKind() == tok::TokenKind::kw_while) { + Diag(Tok, diag::err_while_loop_outside_of_a_function); + } else if (getLangOpts().CPlusPlus) { + if (Tok.isOneOf(tok::period, tok::arrow)) + Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow); + else { + SourceLocation Loc = D.getCXXScopeSpec().getEndLoc(); + if (Tok.isAtStartOfLine() && Loc.isValid()) + Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id) + << getLangOpts().CPlusPlus; + else + Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), + diag::err_expected_unqualified_id) + << getLangOpts().CPlusPlus; + } + } else { + Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()), + diag::err_expected_either) + << tok::identifier << tok::l_paren; + } } D.SetIdentifier(nullptr, Tok.getLocation()); D.setInvalidType(true); Index: clang/test/Parser/while-loop-outside-function.c =================================================================== --- /dev/null +++ clang/test/Parser/while-loop-outside-function.c @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// basic +while(1) {}; // expected-error {{while loop outside of a function}} + + +// location? +while(1) // expected-error {{while loop outside of a function}} +{}; + +// empty statement without semicolon +while(1) // expected-error {{while loop outside of a function}} +{} + +// some statements +while(1) // expected-error {{while loop outside of a function}} +{ + int some_var = 0; +} + +// recovery +void some_fn(); + +void some_fn() { + while(1) {}; +} Index: clang/test/Parser/while-loop-outside-function.cpp =================================================================== --- /dev/null +++ clang/test/Parser/while-loop-outside-function.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +while(true) {}; // expected-error {{while loop outside of a function}} + +// without semicolon +while(true) {} // expected-error {{while loop outside of a function}} + +while(true) // expected-error {{while loop outside of a function}} +{ + // some statements + int some_var = 3; + some_var += 2; +} + +do { // expected-error {{expected unqualified-id}} + int some_var = 1; + some_var += 3; +} +while(true); // expected-error {{while loop outside of a function}} + +void someFunction() { + while(true) {}; +} + +class SomeClass { +public: + while(true) {} // expected-error {{expected member name or ';' after declaration specifiers}} + void some_fn() { + while(true) {} + } +};