diff options
author | Richard Trieu <rtrieu@google.com> | 2012-11-02 01:08:58 +0000 |
---|---|---|
committer | Richard Trieu <rtrieu@google.com> | 2012-11-02 01:08:58 +0000 |
commit | 919b9557b4f0155dfaaea309493ff2a702fca676 (patch) | |
tree | d309422d083e6ca13d49abb53165015b66d4a09d /lib/Parse/ParseExprCXX.cpp | |
parent | aee56faf90c04a75d9c432a92a8fdd2c875559a7 (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
Diffstat (limited to 'lib/Parse/ParseExprCXX.cpp')
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 45 |
1 files changed, 44 insertions, 1 deletions
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)) |