Parse: Consume tokens more carefully in CheckForLParenAfterColonColon

We would consume the lparen even if it wasn't followed by an identifier
or a star-identifier pair.

This fixes PR21815.

llvm-svn: 224403
This commit is contained in:
David Majnemer 2014-12-17 01:39:22 +00:00
parent fc2201e922
commit 6ca445e0dd
2 changed files with 36 additions and 26 deletions

View File

@ -108,35 +108,37 @@ void Parser::CheckForLParenAfterColonColon() {
if (!Tok.is(tok::l_paren))
return;
SourceLocation l_parenLoc = ConsumeParen(), r_parenLoc;
Token Tok1 = getCurToken();
if (!Tok1.is(tok::identifier) && !Tok1.is(tok::star))
Token LParen = Tok;
Token NextTok = GetLookAheadToken(1);
Token StarTok = NextTok;
// Check for (identifier or (*identifier
Token IdentifierTok = StarTok.is(tok::star) ? GetLookAheadToken(2) : StarTok;
if (IdentifierTok.isNot(tok::identifier))
return;
if (Tok1.is(tok::identifier)) {
Token Tok2 = GetLookAheadToken(1);
if (Tok2.is(tok::r_paren)) {
// Eat the '('.
ConsumeParen();
Token RParen;
// Do we have a ')' ?
NextTok = StarTok.is(tok::star) ? GetLookAheadToken(2) : GetLookAheadToken(1);
if (NextTok.is(tok::r_paren)) {
RParen = NextTok;
// Eat the '*' if it is present.
if (StarTok.is(tok::star))
ConsumeToken();
PP.EnterToken(Tok1);
r_parenLoc = ConsumeParen();
}
} else if (Tok1.is(tok::star)) {
Token Tok2 = GetLookAheadToken(1);
if (Tok2.is(tok::identifier)) {
Token Tok3 = GetLookAheadToken(2);
if (Tok3.is(tok::r_paren)) {
ConsumeToken();
ConsumeToken();
PP.EnterToken(Tok2);
PP.EnterToken(Tok1);
r_parenLoc = ConsumeParen();
}
}
// Eat the identifier.
ConsumeToken();
// Add the identifier token back.
PP.EnterToken(IdentifierTok);
// Add the '*' back if it was present.
if (StarTok.is(tok::star))
PP.EnterToken(StarTok);
// Eat the ')'.
ConsumeParen();
}
Diag(l_parenLoc, diag::err_paren_after_colon_colon)
<< FixItHint::CreateRemoval(l_parenLoc)
<< FixItHint::CreateRemoval(r_parenLoc);
Diag(LParen.getLocation(), diag::err_paren_after_colon_colon)
<< FixItHint::CreateRemoval(LParen.getLocation())
<< FixItHint::CreateRemoval(RParen.getLocation());
}
/// \brief Parse global scope or nested-name-specifier if present.

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 %s -fsyntax-only -verify
// RUN: %clang_cc1 %s -fsyntax-only -verify -DPR21815
// RUN: cp %s %t
// RUN: not %clang_cc1 -x c++ -fixit %t
// RUN: %clang_cc1 -x c++ %t
@ -20,3 +20,11 @@ void foo() {
a = ::(h; // expected-error{{unexpected parenthesis after '::'}}
a = ::i;
}
#ifdef PR21815
// expected-error@+4{{C++ requires a type specifier for all declarations}}
// expected-error@+3{{expected unqualified-id}}
// expected-error@+3{{expected expression}}
// expected-error@+1{{expected ';' after top level declarator}}
a (::(
#endif