Index: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td @@ -347,8 +347,6 @@ def warn_cxx98_compat_static_assert : Warning< "static_assert declarations are incompatible with C++98">, InGroup, DefaultIgnore; -def err_paren_after_colon_colon : Error< - "unexpected parenthesis after '::'">; def err_function_definition_not_allowed : Error< "function definition is not allowed here">; def err_expected_end_of_enumerator : Error< Index: cfe/trunk/include/clang/Parse/Parser.h =================================================================== --- cfe/trunk/include/clang/Parse/Parser.h +++ cfe/trunk/include/clang/Parse/Parser.h @@ -1530,8 +1530,6 @@ bool IsTypename = false, IdentifierInfo **LastII = nullptr); - void CheckForLParenAfterColonColon(); - //===--------------------------------------------------------------------===// // C++0x 5.1.2: Lambda expressions Index: cfe/trunk/lib/Parse/ParseExprCXX.cpp =================================================================== --- cfe/trunk/lib/Parse/ParseExprCXX.cpp +++ cfe/trunk/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: cfe/trunk/test/Parser/colon-colon-parentheses.cpp =================================================================== --- cfe/trunk/test/Parser/colon-colon-parentheses.cpp +++ cfe/trunk/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'}}