aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Trieu <rtrieu@google.com>2012-11-02 01:08:58 +0000
committerRichard Trieu <rtrieu@google.com>2012-11-02 01:08:58 +0000
commit919b9557b4f0155dfaaea309493ff2a702fca676 (patch)
treed309422d083e6ca13d49abb53165015b66d4a09d
parentaee56faf90c04a75d9c432a92a8fdd2c875559a7 (diff)
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
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td2
-rw-r--r--include/clang/Parse/Parser.h2
-rw-r--r--lib/Parse/ParseExprCXX.cpp45
-rw-r--r--test/Parser/colon-colon-parentheses.cpp22
4 files changed, 70 insertions, 1 deletions
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 846f37ab40..235b2da62f 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -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<
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 20b13baf69..e16aeadb08 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1327,6 +1327,8 @@ private:
bool *MayBePseudoDestructor = 0,
bool IsTypename = false);
+ void CheckForLParenAfterColonColon();
+
//===--------------------------------------------------------------------===//
// C++0x 5.1.2: Lambda expressions
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 63fcf34be3..2f615e150a 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -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))
diff --git a/test/Parser/colon-colon-parentheses.cpp b/test/Parser/colon-colon-parentheses.cpp
new file mode 100644
index 0000000000..e837bd9f43
--- /dev/null
+++ b/test/Parser/colon-colon-parentheses.cpp
@@ -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;
+}