When finding a '(' after '::', emit error with hint to remove '(' and matching

')', if found.  Don't crash.
Fixes PR11852.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167268 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Richard Trieu 2012-11-02 01:08:58 +00:00
Родитель aee56faf90
Коммит 919b9557b4
4 изменённых файлов: 70 добавлений и 1 удалений

Просмотреть файл

@ -348,6 +348,8 @@ def ext_c11_static_assert : Extension<
def warn_cxx98_compat_static_assert : Warning<
"static_assert declarations are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def err_paren_after_colon_colon : Error<
"unexpected parentheses after '::'">;
/// Objective-C parser diagnostics
def err_expected_minus_or_plus : Error<

Просмотреть файл

@ -1327,6 +1327,8 @@ private:
bool *MayBePseudoDestructor = 0,
bool IsTypename = false);
void CheckForLParenAfterColonColon();
//===--------------------------------------------------------------------===//
// C++0x 5.1.2: Lambda expressions

Просмотреть файл

@ -96,6 +96,45 @@ void Parser::CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectType,
/*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 it found.
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))
return;
if (Tok1.is(tok::identifier)) {
Token Tok2 = GetLookAheadToken(1);
if (Tok2.is(tok::r_paren)) {
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);
}
/// \brief Parse global scope or nested-name-specifier if present.
///
/// Parses a C++ global scope specifier ('::') or nested-name-specifier (which
@ -160,7 +199,9 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// '::' - Global scope qualifier.
if (Actions.ActOnCXXGlobalScopeSpecifier(getCurScope(), ConsumeToken(), SS))
return true;
CheckForLParenAfterColonColon();
HasScopeSpecifier = true;
}
@ -371,6 +412,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
"NextToken() not working properly!");
SourceLocation CCLoc = ConsumeToken();
CheckForLParenAfterColonColon();
HasScopeSpecifier = true;
if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), II, IdLoc, CCLoc,
ObjectType, EnteringContext, SS))

Просмотреть файл

@ -0,0 +1,22 @@
// RUN: %clang_cc1 %s -fsyntax-only -verify
// RUN: cp %s %t
// RUN: not %clang_cc1 -x c++ -fixit %t
// RUN: %clang_cc1 -x c++ %t
struct S { static int a,b,c;};
int S::(a); // expected-error{{unexpected parentheses after '::'}}
int S::(b; // expected-error{{unexpected parentheses after '::'}}
int S::c;
int S::(*d); // expected-error{{unexpected parentheses after '::'}}
int S::(*e; // expected-error{{unexpected parentheses after '::'}}
int S::*f;
int g = S::(a); // expected-error{{unexpected parentheses after '::'}}
int h = S::(b; // expected-error{{unexpected parentheses after '::'}}
int i = S::c;
void foo() {
int a;
a = ::(g); // expected-error{{unexpected parentheses after '::'}}
a = ::(h; // expected-error{{unexpected parentheses after '::'}}
a = ::i;
}