[clang] Fix crash upon stray coloncolon token in C2x mode

The parser assumes that the lexer never emits coloncolon token for C code, but this assumption no longer holds in C2x attribute namespaces. As a result, stray coloncolon tokens out of attributes cause assertion failures and hangs in release build, which this patch tries to handle.

Crash input minimal example: `T n::v`

Reviewed By: aaron.ballman

Differential Revision: https://reviews.llvm.org/D133248
This commit is contained in:
Jialun Hu 2022-10-18 21:56:13 +08:00 committed by YingChi Long
parent b0ded70ebf
commit 94e8bd002c
No known key found for this signature in database
GPG Key ID: 296C3FEFEA88ABC5
5 changed files with 14 additions and 7 deletions

View File

@ -251,6 +251,7 @@ Bug Fixes
- Address the thread identification problems in coroutines.
`Issue 47177 <https://github.com/llvm/llvm-project/issues/47177>`_
`Issue 47179 <https://github.com/llvm/llvm-project/issues/47179>`_
- Fix a crash upon stray coloncolon token in C2x mode.
Improvements to Clang's diagnostics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -866,10 +866,11 @@ public:
bool TryAnnotateCXXScopeToken(bool EnteringContext = false);
bool MightBeCXXScopeToken() {
return Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
(Tok.is(tok::annot_template_id) &&
NextToken().is(tok::coloncolon)) ||
Tok.is(tok::kw_decltype) || Tok.is(tok::kw___super);
return getLangOpts().CPlusPlus &&
(Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
(Tok.is(tok::annot_template_id) &&
NextToken().is(tok::coloncolon)) ||
Tok.is(tok::kw_decltype) || Tok.is(tok::kw___super));
}
bool TryAnnotateOptionalCXXScopeToken(bool EnteringContext = false) {
return MightBeCXXScopeToken() && TryAnnotateCXXScopeToken(EnteringContext);

View File

@ -5411,6 +5411,8 @@ bool Parser::isDeclarationSpecifier(
return isDeclarationSpecifier(AllowImplicitTypename);
case tok::coloncolon: // ::foo::bar
if (!getLangOpts().CPlusPlus)
return false;
if (NextToken().is(tok::kw_new) || // ::new
NextToken().is(tok::kw_delete)) // ::delete
return false;

View File

@ -2080,9 +2080,9 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(
}
if (!getLangOpts().CPlusPlus) {
// If we're in C, we can't have :: tokens at all (the lexer won't return
// them). If the identifier is not a type, then it can't be scope either,
// just early exit.
// If we're in C, the only place we can have :: tokens is C2x
// attribute which is parsed elsewhere. If the identifier is not a type,
// then it can't be scope either, just early exit.
return false;
}

View File

@ -141,3 +141,6 @@ void test_asm(void) {
struct [[]] S4 *s; // expected-error {{an attribute list cannot appear here}}
struct S5 {};
int c = sizeof(struct [[]] S5); // expected-error {{an attribute list cannot appear here}}
// Ensure that '::' outside of attributes does not crash and is not treated as scope
double n::v; // expected-error {{expected ';' after top level declarator}}