diff options
author | Serge Pavlov <sepavloff@gmail.com> | 2014-04-13 16:52:03 +0000 |
---|---|---|
committer | Serge Pavlov <sepavloff@gmail.com> | 2014-04-13 16:52:03 +0000 |
commit | 6a7ffbed8ab434277483075b7bb3ed37ab4d5889 (patch) | |
tree | 1b76e8fd8c554a934cbe1996badc4479f9288b84 /clang/lib/Parse/ParseExprCXX.cpp | |
parent | 8e5e78e19bc94f36d968e6e8a8bcec17495ca3a0 (diff) | |
download | bcm5719-llvm-6a7ffbed8ab434277483075b7bb3ed37ab4d5889.tar.gz bcm5719-llvm-6a7ffbed8ab434277483075b7bb3ed37ab4d5889.zip |
Improve error recovery around colon.
Parse of nested name spacifier is modified so that it properly recovers
if colon is mistyped as double colon in case statement.
This patch fixes PR15133.
Differential Revision: http://llvm-reviews.chandlerc.com/D2870
llvm-svn: 206135
Diffstat (limited to 'clang/lib/Parse/ParseExprCXX.cpp')
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 6495d193f7c..614949c9351 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -365,15 +365,15 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // Consume the template-id token. ConsumeToken(); - + assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); SourceLocation CCLoc = ConsumeToken(); HasScopeSpecifier = true; - + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); - + if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), SS, TemplateId->TemplateKWLoc, @@ -393,7 +393,6 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, continue; } - // The rest of the nested-name-specifier possibilities start with // tok::identifier. if (Tok.isNot(tok::identifier)) @@ -418,9 +417,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, // error, but they probably meant something else strange so don't // recover like this. PP.LookAhead(1).is(tok::identifier)) { - Diag(Next, diag::err_unexected_colon_in_nested_name_spec) + Diag(Next, diag::err_unexpected_colon_in_nested_name_spec) << FixItHint::CreateReplacement(Next.getLocation(), "::"); - // Recover as if the user wrote '::'. Next.setKind(tok::coloncolon); } @@ -434,23 +432,52 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, return false; } + if (ColonIsSacred) { + const Token &Next2 = GetLookAheadToken(2); + if (Next2.is(tok::kw_private) || Next2.is(tok::kw_protected) || + Next2.is(tok::kw_public) || Next2.is(tok::kw_virtual)) { + Diag(Next2, diag::err_unexpected_token_in_nested_name_spec) + << Next2.getName() + << FixItHint::CreateReplacement(Next.getLocation(), ":"); + Token ColonColon; + PP.Lex(ColonColon); + ColonColon.setKind(tok::colon); + PP.EnterToken(ColonColon); + break; + } + } + if (LastII) *LastII = &II; // We have an identifier followed by a '::'. Lookup this name // as the name in a nested-name-specifier. + Token Identifier = Tok; SourceLocation IdLoc = ConsumeToken(); assert((Tok.is(tok::coloncolon) || Tok.is(tok::colon)) && "NextToken() not working properly!"); + Token ColonColon = Tok; SourceLocation CCLoc = ConsumeToken(); CheckForLParenAfterColonColon(); - HasScopeSpecifier = true; + bool IsCorrectedToColon = false; + bool *CorrectionFlagPtr = ColonIsSacred ? &IsCorrectedToColon : 0; if (Actions.ActOnCXXNestedNameSpecifier(getCurScope(), II, IdLoc, CCLoc, - ObjectType, EnteringContext, SS)) + ObjectType, EnteringContext, SS, + false, CorrectionFlagPtr)) { + // Identifier is not recognized as a nested name, but we can have + // mistyped '::' instead of ':'. + if (CorrectionFlagPtr && IsCorrectedToColon) { + ColonColon.setKind(tok::colon); + PP.EnterToken(Tok); + PP.EnterToken(ColonColon); + Tok = Identifier; + break; + } SS.SetInvalid(SourceRange(IdLoc, CCLoc)); - + } + HasScopeSpecifier = true; continue; } |