rnk created this revision.
rnk added reviewers: rsmith, rtrieu.
rnk added a subscriber: cfe-commits.

The code pattern used to implement the token rewriting hack doesn't
interact well with token caching in the pre-processor. As a result,
clang would crash on 'int f(::(id));' while doing a tenative parse of
the contents of the outer parentheses. The original code from PR11852
still doesn't crash the compiler.

This error recovery also often does the wrong thing with member function
pointers. The test case from the original PR doesn't recover the right
way either:

  void S::(*pf)() = S::f; // should be 'void (S::*pf)()'

Instead we were recovering as 'void S::*pf()', which is still wrong.

If we still think that users mistakenly parenthesize identifiers in
nested name specifiers, we should change clang to intentionally parse
that form with an error, rather than doing a token rewrite.

Fixes PR26623, but I think there will be many more bugs of this nature
due to other token rewriting attempts.


https://reviews.llvm.org/D25882

Files:
  include/clang/Parse/Parser.h
  lib/Parse/ParseExprCXX.cpp
  test/Parser/colon-colon-parentheses.cpp

Index: test/Parser/colon-colon-parentheses.cpp
===================================================================
--- test/Parser/colon-colon-parentheses.cpp
+++ test/Parser/colon-colon-parentheses.cpp
@@ -1,30 +1,36 @@
-// 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
+// RUN: %clang_cc1 %s -verify -fno-spell-checking
 
 struct S { static int a,b,c;};
-int S::(a);  // expected-error{{unexpected parenthesis after '::'}}
-int S::(b;  // expected-error{{unexpected parenthesis after '::'}}
+int S::(a);  // expected-error{{expected unqualified-id}}
+int S::(b;  // expected-error{{expected unqualified-id}}
+        );
 int S::c;
-int S::(*d);  // expected-error{{unexpected parenthesis after '::'}}
-int S::(*e;  // expected-error{{unexpected parenthesis after '::'}}
+int S::(*d);  // expected-error{{expected unqualified-id}}
+int S::(*e;  // expected-error{{expected unqualified-id}}
+        );
 int S::*f;
-int g = S::(a);  // expected-error{{unexpected parenthesis after '::'}}
-int h = S::(b;  // expected-error{{unexpected parenthesis after '::'}}
+int g = S::(a);  // expected-error {{expected unqualified-id}} expected-error {{use of undeclared identifier 'a'}}
+int h = S::(b;  // expected-error {{expected unqualified-id}} expected-error {{use of undeclared identifier 'b'}}
+            );
 int i = S::c;
 
 void foo() {
   int a;
-  a = ::(g);  // expected-error{{unexpected parenthesis after '::'}}
-  a = ::(h;  // expected-error{{unexpected parenthesis after '::'}}
+  a = ::(g);  // expected-error{{expected unqualified-id}}
+  a = ::(h;  // expected-error{{expected unqualified-id}}
   a = ::i;
 }
 
-#ifdef PR21815
+// The following tests used to be crash bugs.
+
+// PR21815
 // expected-error@+2{{C++ requires a type specifier for all declarations}}
 // expected-error@+1{{expected unqualified-id}}
 a (::( ));
 
 ::((c )); // expected-error{{expected unqualified-id}}
-#endif
+
+// PR26623
+int f1(::(B) p); // expected-error {{expected unqualified-id}} expected-error {{use of undeclared identifier 'B'}}
+
+int f2(::S::(C) p); // expected-error {{expected unqualified-id}} expected-error {{use of undeclared identifier 'C'}}
Index: lib/Parse/ParseExprCXX.cpp
===================================================================
--- lib/Parse/ParseExprCXX.cpp
+++ lib/Parse/ParseExprCXX.cpp
@@ -100,48 +100,6 @@
              /*AtDigraph*/false);
 }
 
-/// \brief Emits an error for a left parentheses after a double colon.
-///
-/// When a '(' is found after a '::', emit an error.  Attempt to fix the token
-/// stream by removing the '(', and the matching ')' if found.
-void Parser::CheckForLParenAfterColonColon() {
-  if (!Tok.is(tok::l_paren))
-    return;
-
-  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;
-  // Eat the '('.
-  ConsumeParen();
-  Token RParen;
-  RParen.setLocation(SourceLocation());
-  // 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();
-    // 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.
 ///
 /// Parses a C++ global scope specifier ('::') or nested-name-specifier (which
@@ -237,8 +195,6 @@
       if (Actions.ActOnCXXGlobalScopeSpecifier(ConsumeToken(), SS))
         return true;
 
-      CheckForLParenAfterColonColon();
-
       HasScopeSpecifier = true;
     }
   }
@@ -491,8 +447,6 @@
       Token ColonColon = Tok;
       SourceLocation CCLoc = ConsumeToken();
 
-      CheckForLParenAfterColonColon();
-
       bool IsCorrectedToColon = false;
       bool *CorrectionFlagPtr = ColonIsSacred ? &IsCorrectedToColon : nullptr;
       if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), IdInfo,
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -1529,8 +1529,6 @@
                                       bool IsTypename = false,
                                       IdentifierInfo **LastII = nullptr);
 
-  void CheckForLParenAfterColonColon();
-
   //===--------------------------------------------------------------------===//
   // C++0x 5.1.2: Lambda expressions
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to