diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-06 03:21:47 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-06 03:21:47 +0000 |
commit | 99831e4677a7e2e051af636221694d60ba31fcdb (patch) | |
tree | 4684bde38a7659db0c97673dcab98cffce576f9b /lib/Parse | |
parent | c1b0f7fa9b755ab59129ae85187d0d4f91379995 (diff) |
User-defined literals: reject string and character UDLs in all places where the
grammar requires a string-literal and not a user-defined-string-literal. The
two constructs are still represented by the same TokenKind, in order to prevent
a combinatorial explosion of different kinds of token. A flag on Token tracks
whether a ud-suffix is present, in order to prevent clients from needing to look
at the token's spelling.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152098 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 9 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 23 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 7 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 6 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 9 |
6 files changed, 38 insertions, 18 deletions
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 978b2b362d..89f024637e 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -272,6 +272,11 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { if (Invalid) return 0; + // FIXME: This is incorrect: linkage-specifiers are parsed in translation + // phase 7, so string-literal concatenation is supposed to occur. + // extern "" "C" "" "+" "+" { } is legal. + if (Tok.hasUDSuffix()) + Diag(Tok, diag::err_invalid_string_udl); SourceLocation Loc = ConsumeStringToken(); ParseScope LinkageScope(this, Scope::DeclScope); @@ -617,8 +622,10 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ } ExprResult AssertMessage(ParseStringLiteralExpression()); - if (AssertMessage.isInvalid()) + if (AssertMessage.isInvalid()) { + SkipUntil(tok::semi); return 0; + } T.consumeClose(); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index fe4ae38e76..21a2e573c7 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -497,14 +497,14 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { /// unary-operator cast-expression /// 'sizeof' unary-expression /// 'sizeof' '(' type-name ')' -/// [C++0x] 'sizeof' '...' '(' identifier ')' +/// [C++11] 'sizeof' '...' '(' identifier ')' /// [GNU] '__alignof' unary-expression /// [GNU] '__alignof' '(' type-name ')' -/// [C++0x] 'alignof' '(' type-id ')' +/// [C++11] 'alignof' '(' type-id ')' /// [GNU] '&&' identifier +/// [C++11] 'noexcept' '(' expression ')' [C++11 5.3.7] /// [C++] new-expression /// [C++] delete-expression -/// [C++0x] 'noexcept' '(' expression ')' /// /// unary-operator: one of /// '&' '*' '+' '-' '~' '!' @@ -516,7 +516,8 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { /// constant /// string-literal /// [C++] boolean-literal [C++ 2.13.5] -/// [C++0x] 'nullptr' [C++0x 2.14.7] +/// [C++11] 'nullptr' [C++11 2.14.7] +/// [C++11] user-defined-literal /// '(' expression ')' /// [C11] generic-selection /// '__func__' [C99 6.4.2.2] @@ -535,9 +536,9 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { /// [OBJC] '@encode' '(' type-name ')' /// [OBJC] objc-string-literal /// [C++] simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3] -/// [C++0x] simple-type-specifier braced-init-list [C++ 5.2.3] +/// [C++11] simple-type-specifier braced-init-list [C++11 5.2.3] /// [C++] typename-specifier '(' expression-list[opt] ')' [C++ 5.2.3] -/// [C++0x] typename-specifier braced-init-list [C++ 5.2.3] +/// [C++11] typename-specifier braced-init-list [C++11 5.2.3] /// [C++] 'const_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'dynamic_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] /// [C++] 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1] @@ -850,7 +851,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::utf8_string_literal: case tok::utf16_string_literal: case tok::utf32_string_literal: - Res = ParseStringLiteralExpression(); + Res = ParseStringLiteralExpression(true); break; case tok::kw__Generic: // primary-expression: generic-selection [C11 6.5.1] Res = ParseGenericSelectionExpression(); @@ -2102,7 +2103,7 @@ Parser::ParseCompoundLiteralExpression(ParsedType Ty, /// /// primary-expression: [C99 6.5.1] /// string-literal -ExprResult Parser::ParseStringLiteralExpression() { +ExprResult Parser::ParseStringLiteralExpression(bool AllowUserDefinedLiteral) { assert(isTokenStringLiteral() && "Not a string literal!"); // String concat. Note that keywords like __func__ and __FUNCTION__ are not @@ -2110,6 +2111,12 @@ ExprResult Parser::ParseStringLiteralExpression() { SmallVector<Token, 4> StringToks; do { + if (!AllowUserDefinedLiteral && Tok.hasUDSuffix()) { + Diag(Tok, diag::err_invalid_string_udl); + do ConsumeStringToken(); while (isTokenStringLiteral()); + return ExprError(); + } + StringToks.push_back(Tok); ConsumeStringToken(); } while (isTokenStringLiteral()); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index d8663077fd..c735c6f2b3 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -1905,8 +1905,13 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, if (getLang().CPlusPlus0x && Tok.is(tok::string_literal)) { 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; + } if (Tok.getLength() != 2) - Diag(Tok.getLocation(), diag::err_operator_string_not_empty); + Diag(Tok.getLocation(), diag::err_literal_operator_string_not_empty); ConsumeStringToken(); if (Tok.isNot(tok::identifier)) { diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index eea9a7e981..5ed8ffec4c 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -2011,6 +2011,8 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { case tok::string_literal: // primary-expression: string-literal case tok::wide_string_literal: + if (Tok.hasUDSuffix()) + return ExprError(Diag(Tok, diag::err_invalid_string_udl)); return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc)); default: if (Tok.getIdentifierInfo() == 0) diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 0ce73cbeb2..cd80c4c969 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -1797,10 +1797,8 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { ExprResult AsmString(ParseAsmStringLiteral()); if (AsmString.isInvalid()) { - // If the reason we are recovering is because of an improper string - // literal, it makes the most sense just to consume to the ')'. - if (isTokenStringLiteral()) - T.skipToEnd(); + // Consume up to and including the closing paren. + T.skipToEnd(); return StmtError(); } diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 6a479bc60c..8b1765df39 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -1127,9 +1127,13 @@ Parser::ExprResult Parser::ParseAsmStringLiteral() { switch (Tok.getKind()) { case tok::string_literal: break; + case tok::utf8_string_literal: + case tok::utf16_string_literal: + case tok::utf32_string_literal: case tok::wide_string_literal: { SourceLocation L = Tok.getLocation(); Diag(Tok, diag::err_asm_operand_wide_string_literal) + << (Tok.getKind() == tok::wide_string_literal) << SourceRange(L, L); return ExprError(); } @@ -1138,10 +1142,7 @@ Parser::ExprResult Parser::ParseAsmStringLiteral() { return ExprError(); } - ExprResult Res(ParseStringLiteralExpression()); - if (Res.isInvalid()) return move(Res); - - return move(Res); + return ParseStringLiteralExpression(); } /// ParseSimpleAsm |