From: David Majnemer Date: Wed, 17 Dec 2014 01:39:22 +0000 (+0000) Subject: Parse: Consume tokens more carefully in CheckForLParenAfterColonColon X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=eadec62aaac4c96da5d94e6cfdbeafc5f83f5171;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@224403 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 613246ef71..dad1f0da2e 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -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(); - } - } - } - - Diag(l_parenLoc, diag::err_paren_after_colon_colon) - << FixItHint::CreateRemoval(l_parenLoc) - << FixItHint::CreateRemoval(r_parenLoc); + // 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(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. diff --git a/test/Parser/colon-colon-parentheses.cpp b/test/Parser/colon-colon-parentheses.cpp index 55948fdb00..e031ce2e90 100644 --- a/test/Parser/colon-colon-parentheses.cpp +++ b/test/Parser/colon-colon-parentheses.cpp @@ -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