[clang] better error message for while loops outside of control flow

report an error when encountering 'while' token parsing declarator

```
clang/test/Parser/while-loop-outside-function.c:3:1: error: while loop outside of a function
while // expected-error {{while loop outside of a function}}
^
clang/test/Parser/while-loop-outside-function.c:7:1: error: while loop outside of a function
while // expected-error {{while loop outside of a function}}
^
```

Fixes: https://github.com/llvm/llvm-project/issues/34462

Differential Revision: https://reviews.llvm.org/D129573
This commit is contained in:
inclyc 2022-07-13 00:12:12 +08:00
parent 1ef32e7828
commit edaae251cc
No known key found for this signature in database
GPG Key ID: 7C44FE7AD4EF9C49
4 changed files with 75 additions and 16 deletions

View File

@ -538,6 +538,8 @@ def err_invalid_operator_on_type : Error<
"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">;

View File

@ -6344,23 +6344,27 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
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);

View File

@ -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);
}

View File

@ -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) {}
}
};