aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Lex/Lexer.cpp1
-rw-r--r--lib/Lex/ModuleMap.cpp6
-rw-r--r--lib/Lex/PPDirectives.cpp14
-rw-r--r--lib/Lex/PPExpressions.cpp4
-rw-r--r--lib/Lex/PPMacroExpansion.cpp29
-rw-r--r--lib/Lex/Pragma.cpp23
-rw-r--r--lib/Lex/TokenConcatenation.cpp39
-rw-r--r--lib/Parse/ParseDeclCXX.cpp9
-rw-r--r--lib/Parse/ParseExpr.cpp23
-rw-r--r--lib/Parse/ParseExprCXX.cpp7
-rw-r--r--lib/Parse/ParseObjc.cpp2
-rw-r--r--lib/Parse/ParseStmt.cpp6
-rw-r--r--lib/Parse/Parser.cpp9
-rw-r--r--lib/Rewrite/HTMLRewrite.cpp1
14 files changed, 138 insertions, 35 deletions
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp
index 2b24d1cc75..a7fba8019d 100644
--- a/lib/Lex/Lexer.cpp
+++ b/lib/Lex/Lexer.cpp
@@ -1582,6 +1582,7 @@ const char *Lexer::LexUDSuffix(Token &Result, const char *CurPtr) {
unsigned Size;
char C = getCharAndSize(CurPtr, Size);
if (isIdentifierHead(C)) {
+ Result.setFlag(Token::HasUDSuffix);
do {
CurPtr = ConsumeChar(CurPtr, Size, Result);
C = getCharAndSize(CurPtr, Size);
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp
index 28043d1198..e6851afada 100644
--- a/lib/Lex/ModuleMap.cpp
+++ b/lib/Lex/ModuleMap.cpp
@@ -617,6 +617,12 @@ retry:
break;
case tok::string_literal: {
+ if (LToken.hasUDSuffix()) {
+ Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
+ HadError = true;
+ goto retry;
+ }
+
// Parse the string literal.
LangOptions LangOpts;
StringLiteralParser StringLiteral(&LToken, 1, SourceMgr, LangOpts, *Target);
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index 1e8f59023b..7345ef2197 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -822,8 +822,10 @@ void Preprocessor::HandleLineDirective(Token &Tok) {
; // ok
else if (StrTok.isNot(tok::string_literal)) {
Diag(StrTok, diag::err_pp_line_invalid_filename);
- DiscardUntilEndOfDirective();
- return;
+ return DiscardUntilEndOfDirective();
+ } else if (StrTok.hasUDSuffix()) {
+ Diag(StrTok, diag::err_invalid_string_udl);
+ return DiscardUntilEndOfDirective();
} else {
// Parse and validate the string, converting it into a unique ID.
StringLiteralParser Literal(&StrTok, 1, *this);
@@ -957,6 +959,9 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) {
else if (StrTok.isNot(tok::string_literal)) {
Diag(StrTok, diag::err_pp_linemarker_invalid_filename);
return DiscardUntilEndOfDirective();
+ } else if (StrTok.hasUDSuffix()) {
+ Diag(StrTok, diag::err_invalid_string_udl);
+ return DiscardUntilEndOfDirective();
} else {
// Parse and validate the string, converting it into a unique ID.
StringLiteralParser Literal(&StrTok, 1, *this);
@@ -1047,6 +1052,11 @@ void Preprocessor::HandleIdentSCCSDirective(Token &Tok) {
return;
}
+ if (StrTok.hasUDSuffix()) {
+ Diag(StrTok, diag::err_invalid_string_udl);
+ return DiscardUntilEndOfDirective();
+ }
+
// Verify that there is nothing after the string, other than EOD.
CheckEndOfDirective("ident");
diff --git a/lib/Lex/PPExpressions.cpp b/lib/Lex/PPExpressions.cpp
index c4ab143aaa..8d8fe316e7 100644
--- a/lib/Lex/PPExpressions.cpp
+++ b/lib/Lex/PPExpressions.cpp
@@ -251,6 +251,10 @@ static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT,
case tok::wide_char_constant: { // L'x'
case tok::utf16_char_constant: // u'x'
case tok::utf32_char_constant: // U'x'
+ // Complain about, and drop, any ud-suffix.
+ if (PeekTok.hasUDSuffix())
+ PP.Diag(PeekTok, diag::err_pp_invalid_char_udl);
+
SmallString<32> CharBuffer;
bool CharInvalid = false;
StringRef ThisTok = PP.getSpelling(PeekTok, CharBuffer, &CharInvalid);
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 99f2b23dff..777e0db026 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -825,6 +825,16 @@ static bool EvaluateHasIncludeCommon(Token &Tok,
return false;
}
+ // Get ')'.
+ PP.LexNonComment(Tok);
+
+ // Ensure we have a trailing ).
+ if (Tok.isNot(tok::r_paren)) {
+ PP.Diag(Tok.getLocation(), diag::err_pp_missing_rparen) << II->getName();
+ PP.Diag(LParenLoc, diag::note_matching) << "(";
+ return false;
+ }
+
bool isAngled = PP.GetIncludeFilenameSpelling(Tok.getLocation(), Filename);
// If GetIncludeFilenameSpelling set the start ptr to null, there was an
// error.
@@ -836,20 +846,8 @@ static bool EvaluateHasIncludeCommon(Token &Tok,
const FileEntry *File =
PP.LookupFile(Filename, isAngled, LookupFrom, CurDir, NULL, NULL, NULL);
- // Get the result value. Result = true means the file exists.
- bool Result = File != 0;
-
- // Get ')'.
- PP.LexNonComment(Tok);
-
- // Ensure we have a trailing ).
- if (Tok.isNot(tok::r_paren)) {
- PP.Diag(Tok.getLocation(), diag::err_pp_missing_rparen) << II->getName();
- PP.Diag(LParenLoc, diag::note_matching) << "(";
- return false;
- }
-
- return Result;
+ // Get the result value. A result of true means the file exists.
+ return File != 0;
}
/// EvaluateHasInclude - Process a '__has_include("path")' expression.
@@ -1091,6 +1089,9 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
// from macro expansion.
SmallVector<Token, 4> StrToks;
while (Tok.is(tok::string_literal)) {
+ // Complain about, and drop, any ud-suffix.
+ if (Tok.hasUDSuffix())
+ Diag(Tok, diag::err_invalid_string_udl);
StrToks.push_back(Tok);
LexUnexpandedToken(Tok);
}
diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp
index 046a4d02f0..404feaab46 100644
--- a/lib/Lex/Pragma.cpp
+++ b/lib/Lex/Pragma.cpp
@@ -133,6 +133,20 @@ void Preprocessor::Handle_Pragma(Token &Tok) {
Lex(Tok);
if (Tok.isNot(tok::string_literal) && Tok.isNot(tok::wide_string_literal)) {
Diag(PragmaLoc, diag::err__Pragma_malformed);
+ // Skip this token, and the ')', if present.
+ if (Tok.isNot(tok::r_paren))
+ Lex(Tok);
+ if (Tok.is(tok::r_paren))
+ Lex(Tok);
+ return;
+ }
+
+ if (Tok.hasUDSuffix()) {
+ Diag(Tok, diag::err_invalid_string_udl);
+ // Skip this token, and the ')', if present.
+ Lex(Tok);
+ if (Tok.is(tok::r_paren))
+ Lex(Tok);
return;
}
@@ -442,6 +456,8 @@ void Preprocessor::HandlePragmaComment(Token &Tok) {
// "foo " "bar" "Baz"
SmallVector<Token, 4> StrToks;
while (Tok.is(tok::string_literal)) {
+ if (Tok.hasUDSuffix())
+ Diag(Tok, diag::err_invalid_string_udl);
StrToks.push_back(Tok);
Lex(Tok);
}
@@ -518,6 +534,8 @@ void Preprocessor::HandlePragmaMessage(Token &Tok) {
// "foo " "bar" "Baz"
SmallVector<Token, 4> StrToks;
while (Tok.is(tok::string_literal)) {
+ if (Tok.hasUDSuffix())
+ Diag(Tok, diag::err_invalid_string_udl);
StrToks.push_back(Tok);
Lex(Tok);
}
@@ -577,6 +595,11 @@ IdentifierInfo *Preprocessor::ParsePragmaPushOrPopMacro(Token &Tok) {
return 0;
}
+ if (Tok.hasUDSuffix()) {
+ Diag(Tok, diag::err_invalid_string_udl);
+ return 0;
+ }
+
// Remember the macro string.
std::string StrVal = getSpelling(Tok);
diff --git a/lib/Lex/TokenConcatenation.cpp b/lib/Lex/TokenConcatenation.cpp
index 335d864f3f..ca7e55d863 100644
--- a/lib/Lex/TokenConcatenation.cpp
+++ b/lib/Lex/TokenConcatenation.cpp
@@ -85,6 +85,19 @@ TokenConcatenation::TokenConcatenation(Preprocessor &pp) : PP(pp) {
TokenInfo[tok::hash ] |= aci_custom_firstchar;
TokenInfo[tok::arrow ] |= aci_custom_firstchar;
+ // These tokens have custom code in C++11 mode.
+ if (PP.getLangOptions().CPlusPlus0x) {
+ TokenInfo[tok::string_literal ] |= aci_custom;
+ TokenInfo[tok::wide_string_literal ] |= aci_custom;
+ TokenInfo[tok::utf8_string_literal ] |= aci_custom;
+ TokenInfo[tok::utf16_string_literal] |= aci_custom;
+ TokenInfo[tok::utf32_string_literal] |= aci_custom;
+ TokenInfo[tok::char_constant ] |= aci_custom;
+ TokenInfo[tok::wide_char_constant ] |= aci_custom;
+ TokenInfo[tok::utf16_char_constant ] |= aci_custom;
+ TokenInfo[tok::utf32_char_constant ] |= aci_custom;
+ }
+
// These tokens change behavior if followed by an '='.
TokenInfo[tok::amp ] |= aci_avoid_equal; // &=
TokenInfo[tok::plus ] |= aci_avoid_equal; // +=
@@ -183,6 +196,28 @@ bool TokenConcatenation::AvoidConcat(const Token &PrevPrevTok,
case tok::raw_identifier:
llvm_unreachable("tok::raw_identifier in non-raw lexing mode!");
+ case tok::string_literal:
+ case tok::wide_string_literal:
+ case tok::utf8_string_literal:
+ case tok::utf16_string_literal:
+ case tok::utf32_string_literal:
+ case tok::char_constant:
+ case tok::wide_char_constant:
+ case tok::utf16_char_constant:
+ case tok::utf32_char_constant:
+ if (!PP.getLangOptions().CPlusPlus0x)
+ return false;
+
+ // In C++11, a string or character literal followed by an identifier is a
+ // single token.
+ if (Tok.getIdentifierInfo())
+ return true;
+
+ // A ud-suffix is an identifier. If the previous token ends with one, treat
+ // it as an identifier.
+ if (!PrevTok.hasUDSuffix())
+ return false;
+ // FALL THROUGH.
case tok::identifier: // id+id or id+number or id+L"foo".
// id+'.'... will not append.
if (Tok.is(tok::numeric_constant))
@@ -201,9 +236,11 @@ bool TokenConcatenation::AvoidConcat(const Token &PrevPrevTok,
// Otherwise, this is a narrow character or string. If the *identifier*
// is a literal 'L', 'u8', 'u' or 'U', avoid pasting L "foo" -> L"foo".
return IsIdentifierStringPrefix(PrevTok);
+
case tok::numeric_constant:
return isalnum(FirstChar) || Tok.is(tok::numeric_constant) ||
- FirstChar == '+' || FirstChar == '-' || FirstChar == '.';
+ FirstChar == '+' || FirstChar == '-' || FirstChar == '.' ||
+ (PP.getLangOptions().CPlusPlus0x && FirstChar == '_');
case tok::period: // ..., .*, .1234
return (FirstChar == '.' && PrevPrevTok.is(tok::period)) ||
isdigit(FirstChar) ||
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
diff --git a/lib/Rewrite/HTMLRewrite.cpp b/lib/Rewrite/HTMLRewrite.cpp
index 63b7def52a..6a1e3dcdc0 100644
--- a/lib/Rewrite/HTMLRewrite.cpp
+++ b/lib/Rewrite/HTMLRewrite.cpp
@@ -409,6 +409,7 @@ void html::SyntaxHighlight(Rewriter &R, FileID FID, const Preprocessor &PP) {
--TokLen;
// FALL THROUGH.
case tok::string_literal:
+ // FIXME: Exclude the optional ud-suffix from the highlighted range.
HighlightRange(RB, TokOffs, TokOffs+TokLen, BufferStart,
"<span class='string_literal'>", "</span>");
break;