diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-08 23:06:02 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-08 23:06:02 +0000 |
commit | 7d182a7909881f5555db0f519843681a7252f79d (patch) | |
tree | 852efa4a708a02a27e955c24f47b933075495f99 /clang/lib | |
parent | f7fc1d48595d946929908c2fb3658450b2a2cebe (diff) | |
download | bcm5719-llvm-7d182a7909881f5555db0f519843681a7252f79d.tar.gz bcm5719-llvm-7d182a7909881f5555db0f519843681a7252f79d.zip |
Fix a couple of issues with literal-operator-id parsing, and provide recovery
for a few kinds of error. Specifically:
Since we're after translation phase 6, the "" token might be formed by multiple
source-level string literals. Checking the token width is not a correct way of
detecting empty string literals, due to escaped newlines. Diagnose and recover
from a missing space between "" and suffix, and from string literals other than
"", which are followed by a suffix.
llvm-svn: 152348
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 67 |
1 files changed, 56 insertions, 11 deletions
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index c735c6f2b30..847b3964fb5 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -15,6 +15,7 @@ #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" #include "clang/Basic/PrettyStackTrace.h" +#include "clang/Lex/LiteralSupport.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ParsedTemplate.h" @@ -1903,24 +1904,68 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, // literal-operator-id: [C++0x 13.5.8] // operator "" identifier - if (getLang().CPlusPlus0x && Tok.is(tok::string_literal)) { + if (getLang().CPlusPlus0x && isTokenStringLiteral()) { Diag(Tok.getLocation(), diag::warn_cxx98_compat_literal_operator); - // FIXME: Add a FixIt to insert a space before the suffix, and recover. - if (Tok.hasUDSuffix()) { - Diag(Tok.getLocation(), diag::err_literal_operator_missing_space); - return true; + + SourceLocation DiagLoc; + unsigned DiagId = 0; + + // We're past translation phase 6, so perform string literal concatenation + // before checking for "". + llvm::SmallVector<Token, 4> Toks; + llvm::SmallVector<SourceLocation, 4> TokLocs; + while (isTokenStringLiteral()) { + if (!Tok.is(tok::string_literal) && !DiagId) { + DiagLoc = Tok.getLocation(); + DiagId = diag::err_literal_operator_string_prefix; + } + Toks.push_back(Tok); + TokLocs.push_back(ConsumeStringToken()); } - if (Tok.getLength() != 2) - Diag(Tok.getLocation(), diag::err_literal_operator_string_not_empty); - ConsumeStringToken(); - if (Tok.isNot(tok::identifier)) { + StringLiteralParser Literal(Toks.data(), Toks.size(), PP); + if (Literal.hadError) + return true; + + // Grab the literal operator's suffix, which will be either the next token + // or a ud-suffix from the string literal. + IdentifierInfo *II = 0; + SourceLocation SuffixLoc; + if (!Literal.getUDSuffix().empty()) { + II = &PP.getIdentifierTable().get(Literal.getUDSuffix()); + SuffixLoc = + Lexer::AdvanceToTokenCharacter(TokLocs[Literal.getUDSuffixToken()], + Literal.getUDSuffixOffset(), + PP.getSourceManager(), getLang()); + // This form is not permitted by the standard (yet). + DiagLoc = SuffixLoc; + DiagId = diag::err_literal_operator_missing_space; + } else if (Tok.is(tok::identifier)) { + II = Tok.getIdentifierInfo(); + SuffixLoc = ConsumeToken(); + TokLocs.push_back(SuffixLoc); + } else { Diag(Tok.getLocation(), diag::err_expected_ident); return true; } - IdentifierInfo *II = Tok.getIdentifierInfo(); - Result.setLiteralOperatorId(II, KeywordLoc, ConsumeToken()); + // The string literal must be empty. + if (!Literal.GetString().empty() || Literal.Pascal) { + DiagLoc = TokLocs.front(); + DiagId = diag::err_literal_operator_string_not_empty; + } + + if (DiagId) { + // This isn't a valid literal-operator-id, but we think we know + // what the user meant. Tell them what they should have written. + llvm::SmallString<32> Str; + Str += "\"\" "; + Str += II->getName(); + Diag(DiagLoc, DiagId) << FixItHint::CreateReplacement( + SourceRange(TokLocs.front(), TokLocs.back()), Str); + } + + Result.setLiteralOperatorId(II, KeywordLoc, SuffixLoc); return false; } |