]> granicus.if.org Git - clang/commitdiff
Parse: Consume tokens more carefully in CheckForLParenAfterColonColon
authorDavid Majnemer <david.majnemer@gmail.com>
Wed, 17 Dec 2014 01:39:22 +0000 (01:39 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Wed, 17 Dec 2014 01:39:22 +0000 (01:39 +0000)
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

lib/Parse/ParseExprCXX.cpp
test/Parser/colon-colon-parentheses.cpp

index 613246ef7121facdb173b76c6540beec828d5152..dad1f0da2ef306c4a3ef839bbbd0dfc4f91e0845 100644 (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();
-      }
-    }
-  }
-
-  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.
index 55948fdb0051cdf3521e8383129e8d1f4a43244c..e031ce2e9045162f4f59328060a8087de15a812a 100644 (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