diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/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">; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp --- a/clang/lib/Parse/ParseDecl.cpp +++ b/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); diff --git a/clang/test/Parser/while-loop-outside-function.c b/clang/test/Parser/while-loop-outside-function.c new file mode 100644 --- /dev/null +++ b/clang/test/Parser/while-loop-outside-function.c @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +while // expected-error {{while loop outside of a function}} +(1) {}; + +// without semicolon +while // expected-error {{while loop outside of a function}} +(1) {} + +int overload_return(); // expected-note {{previous declaration is here}} + +void overload_return() // expected-error {{conflicting types for 'overload_return'}} +{ + while(1) {}; + while(1); +} + +while // expected-error {{while loop outside of a function}} +(1); + +void correct(); + +void correct() { + while(1) {}; + while(1); +} diff --git a/clang/test/Parser/while-loop-outside-function.cpp b/clang/test/Parser/while-loop-outside-function.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Parser/while-loop-outside-function.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +while // expected-error {{while loop outside of a function}} +(true) {}; + +// without semicolon +while // expected-error {{while loop outside of a function}} +(true) {} + +do { // expected-error {{expected unqualified-id}} + int some_var = 1; + some_var += 3; +} +while // expected-error {{while loop outside of a function}} +(true); + +void someFunction() { + while(true) {}; +} + +class SomeClass { +public: + while(true) {} // expected-error {{expected member name or ';' after declaration specifiers}} + void some_fn() { + while(true) {} + } +};