[cfe-commits] r152098 - in /cfe/trunk: include/clang/Basic/ include/clang/Lex/ include/clang/Parse/ lib/Lex/ lib/Parse/ lib/Rewrite/ test/CXX/over/over.oper/over.literal/ test/Lexer/ test/Parser/

Richard Smith richard-llvm at metafoo.co.uk
Mon Mar 5 19:21:47 PST 2012


Author: rsmith
Date: Mon Mar  5 21:21:47 2012
New Revision: 152098

URL: http://llvm.org/viewvc/llvm-project?rev=152098&view=rev
Log:
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.

Added:
    cfe/trunk/test/Lexer/token-concat.cpp
    cfe/trunk/test/Parser/asm.cpp
    cfe/trunk/test/Parser/cxx11-user-defined-literals.cpp
    cfe/trunk/test/Parser/objcxx11-user-defined-literal.mm
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Lex/Token.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Lex/Lexer.cpp
    cfe/trunk/lib/Lex/ModuleMap.cpp
    cfe/trunk/lib/Lex/PPDirectives.cpp
    cfe/trunk/lib/Lex/PPExpressions.cpp
    cfe/trunk/lib/Lex/PPMacroExpansion.cpp
    cfe/trunk/lib/Lex/Pragma.cpp
    cfe/trunk/lib/Lex/TokenConcatenation.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Parse/ParseObjc.cpp
    cfe/trunk/lib/Parse/ParseStmt.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Rewrite/HTMLRewrite.cpp
    cfe/trunk/test/CXX/over/over.oper/over.literal/p8.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td Mon Mar  5 21:21:47 2012
@@ -41,6 +41,8 @@
 def err_expected_colon_after_setter_name : Error<
   "method name referenced in property setter attribute "
   "must end with ':'">;
+def err_invalid_string_udl : Error<
+  "string literal with user-defined suffix cannot be used here">;
 
 // Parse && Sema
 def ext_no_declarators : ExtWarn<"declaration does not declare anything">,

Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td Mon Mar  5 21:21:47 2012
@@ -136,6 +136,9 @@
 def err_string_concat_mixed_suffix : Error<
   "differing user-defined suffixes ('%0' and '%1') in string literal "
   "concatenation">;
+def err_pp_invalid_char_udl : Error<
+  "character literal with user-defined suffix cannot be used in preprocessor "
+  "constant expression">;
 def err_bad_string_encoding : Error<
   "illegal character encoding in string literal">;
 def warn_bad_string_encoding : ExtWarn<

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Mon Mar  5 21:21:47 2012
@@ -200,7 +200,7 @@
   "use of address-of-label extension outside of a function body">;
 def err_expected_string_literal : Error<"expected string literal">;
 def err_asm_operand_wide_string_literal : Error<
-  "cannot use wide string literal in 'asm'">;
+  "cannot use %select{unicode|wide}0 string literal in 'asm'">;
 def err_expected_selector_for_method : Error<
   "expected selector for Objective-C method">;
 def err_expected_property_name : Error<"expected property name">;
@@ -425,8 +425,11 @@
 def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;
 
 // C++ operator overloading
-def err_operator_string_not_empty : Error<
+def err_literal_operator_string_not_empty : Error<
   "string literal after 'operator' must be '\"\"'">;
+def err_literal_operator_missing_space : Error<
+  "C++11 requires a space between the \"\" and the user-defined suffix in a "
+  "literal operator">;
 def warn_cxx98_compat_literal_operator : Warning<
   "literal operators are incompatible with C++98">,
   InGroup<CXX98Compat>, DefaultIgnore;

Modified: cfe/trunk/include/clang/Lex/Token.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Token.h?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/Token.h (original)
+++ cfe/trunk/include/clang/Lex/Token.h Mon Mar  5 21:21:47 2012
@@ -75,7 +75,8 @@
     LeadingSpace  = 0x02,  // Whitespace exists before this token.
     DisableExpand = 0x04,  // This identifier may never be macro expanded.
     NeedsCleaning = 0x08,   // Contained an escaped newline or trigraph.
-    LeadingEmptyMacro = 0x10 // Empty macro exists before this token.
+    LeadingEmptyMacro = 0x10, // Empty macro exists before this token.
+    HasUDSuffix = 0x20     // This string or character literal has a ud-suffix.
   };
 
   tok::TokenKind getKind() const { return (tok::TokenKind)Kind; }
@@ -263,6 +264,9 @@
     return (Flags & LeadingEmptyMacro) ? true : false;
   }
 
+  /// \brief Return true if this token is a string or character literal which
+  /// has a ud-suffix.
+  bool hasUDSuffix() const { return (Flags & HasUDSuffix) ? true : false; }
 };
 
 /// PPConditionalInfo - Information about the conditional stack (#if directives)

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Mar  5 21:21:47 2012
@@ -1359,7 +1359,7 @@
                                                   SourceLocation LParenLoc,
                                                   SourceLocation RParenLoc);
 
-  ExprResult ParseStringLiteralExpression();
+  ExprResult ParseStringLiteralExpression(bool AllowUserDefinedLiteral = false);
 
   ExprResult ParseGenericSelectionExpression();
 

Modified: cfe/trunk/lib/Lex/Lexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Lexer.cpp?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/Lexer.cpp (original)
+++ cfe/trunk/lib/Lex/Lexer.cpp Mon Mar  5 21:21:47 2012
@@ -1582,6 +1582,7 @@
   unsigned Size;
   char C = getCharAndSize(CurPtr, Size);
   if (isIdentifierHead(C)) {
+    Result.setFlag(Token::HasUDSuffix);
     do {
       CurPtr = ConsumeChar(CurPtr, Size, Result);
       C = getCharAndSize(CurPtr, Size);

Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Mon Mar  5 21:21:47 2012
@@ -617,6 +617,12 @@
     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);

Modified: cfe/trunk/lib/Lex/PPDirectives.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPDirectives.cpp?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPDirectives.cpp (original)
+++ cfe/trunk/lib/Lex/PPDirectives.cpp Mon Mar  5 21:21:47 2012
@@ -822,8 +822,10 @@
     ; // 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 @@
   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 @@
     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");
 

Modified: cfe/trunk/lib/Lex/PPExpressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPExpressions.cpp?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPExpressions.cpp (original)
+++ cfe/trunk/lib/Lex/PPExpressions.cpp Mon Mar  5 21:21:47 2012
@@ -251,6 +251,10 @@
   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);

Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
+++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Mon Mar  5 21:21:47 2012
@@ -825,6 +825,16 @@
     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 @@
   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 @@
         // 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);
         }

Modified: cfe/trunk/lib/Lex/Pragma.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Pragma.cpp?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/Pragma.cpp (original)
+++ cfe/trunk/lib/Lex/Pragma.cpp Mon Mar  5 21:21:47 2012
@@ -133,6 +133,20 @@
   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 @@
     // "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 @@
   // "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 @@
     return 0;
   }
 
+  if (Tok.hasUDSuffix()) {
+    Diag(Tok, diag::err_invalid_string_udl);
+    return 0;
+  }
+
   // Remember the macro string.
   std::string StrVal = getSpelling(Tok);
 

Modified: cfe/trunk/lib/Lex/TokenConcatenation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/TokenConcatenation.cpp?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/TokenConcatenation.cpp (original)
+++ cfe/trunk/lib/Lex/TokenConcatenation.cpp Mon Mar  5 21:21:47 2012
@@ -85,6 +85,19 @@
   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 @@
   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 @@
     // 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) ||

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Mar  5 21:21:47 2012
@@ -272,6 +272,11 @@
   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 @@
   }
 
   ExprResult AssertMessage(ParseStringLiteralExpression());
-  if (AssertMessage.isInvalid())
+  if (AssertMessage.isInvalid()) {
+    SkipUntil(tok::semi);
     return 0;
+  }
 
   T.consumeClose();
 

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Mon Mar  5 21:21:47 2012
@@ -497,14 +497,14 @@
 ///         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 @@
 ///         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 @@
 /// [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 @@
   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 @@
 ///
 ///       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 @@
   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());

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Mon Mar  5 21:21:47 2012
@@ -1905,8 +1905,13 @@
 
   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)) {

Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Mon Mar  5 21:21:47 2012
@@ -2011,6 +2011,8 @@
 
   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)

Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Mon Mar  5 21:21:47 2012
@@ -1797,10 +1797,8 @@
 
   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();
   }
 

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Mon Mar  5 21:21:47 2012
@@ -1127,9 +1127,13 @@
   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 @@
       return ExprError();
   }
 
-  ExprResult Res(ParseStringLiteralExpression());
-  if (Res.isInvalid()) return move(Res);
-
-  return move(Res);
+  return ParseStringLiteralExpression();
 }
 
 /// ParseSimpleAsm

Modified: cfe/trunk/lib/Rewrite/HTMLRewrite.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/HTMLRewrite.cpp?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/lib/Rewrite/HTMLRewrite.cpp (original)
+++ cfe/trunk/lib/Rewrite/HTMLRewrite.cpp Mon Mar  5 21:21:47 2012
@@ -409,6 +409,7 @@
       --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;

Modified: cfe/trunk/test/CXX/over/over.oper/over.literal/p8.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/over/over.oper/over.literal/p8.cpp?rev=152098&r1=152097&r2=152098&view=diff
==============================================================================
--- cfe/trunk/test/CXX/over/over.oper/over.literal/p8.cpp (original)
+++ cfe/trunk/test/CXX/over/over.oper/over.literal/p8.cpp Mon Mar  5 21:21:47 2012
@@ -10,7 +10,7 @@
 // FIXME: This should be accepted once we support UCNs
 template<char...> int operator "" \u03C0(); // ok, UCN for lowercase pi // expected-error {{expected identifier}}
 // FIXME: Accept this as an extension, with a fix-it to add the space
-float operator ""E(const char *); // expected-error {{must be '""'}} expected-error {{expected identifier}}
+float operator ""E(const char *); // expected-error {{C++11 requires a space between the "" and the user-defined suffix in a literal operator}}
 float operator " " B(const char *); // expected-error {{must be '""'}} expected-warning {{hexfloat}}
 string operator "" 5X(const char *, std::size_t); // expected-error {{expected identifier}}
 double operator "" _miles(double); // expected-error {{parameter}}

Added: cfe/trunk/test/Lexer/token-concat.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Lexer/token-concat.cpp?rev=152098&view=auto
==============================================================================
--- cfe/trunk/test/Lexer/token-concat.cpp (added)
+++ cfe/trunk/test/Lexer/token-concat.cpp Mon Mar  5 21:21:47 2012
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -E -std=c++11 -o - %s | FileCheck %s
+
+#define id(x) x
+id("s")_x // CHECK: "s" _x
+id(L"s")_x // CHECK: L"s" _x
+id(u8"s")_x // CHECK: u8"s" _x
+id(u"s")_x // CHECK: u"s" _x
+id(U"s")_x // CHECK: U"s" _x
+id('s')_x // CHECK: 's' _x
+id(L's')_x // CHECK: L's' _x
+id(u's')_x // CHECK: u's' _x
+id(U's')_x // CHECK: U's' _x
+id("s"_x)_y // CHECK: "s"_x _y
+id(1.0_)f // CHECK: 1.0_ f
+id(1.0)_f // CHECK: 1.0 _f
+id(0xface+)b_count // CHECK: 0xface+ b_count
+id("s")1 // CHECK: "s"1
+id("s"_x)1 // CHECK: "s"_x 1
+id(1)_2_x // CHECK: 1 _2_x

Added: cfe/trunk/test/Parser/asm.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/asm.cpp?rev=152098&view=auto
==============================================================================
--- cfe/trunk/test/Parser/asm.cpp (added)
+++ cfe/trunk/test/Parser/asm.cpp Mon Mar  5 21:21:47 2012
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+int foo1 asm ("bar1");
+int foo2 asm (L"bar2"); // expected-error {{cannot use wide string literal in 'asm'}}
+int foo3 asm (u8"bar3"); // expected-error {{cannot use unicode string literal in 'asm'}}
+int foo4 asm (u"bar4"); // expected-error {{cannot use unicode string literal in 'asm'}}
+int foo5 asm (U"bar5"); // expected-error {{cannot use unicode string literal in 'asm'}}
+int foo6 asm ("bar6"_x); // expected-error {{string literal with user-defined suffix cannot be used here}}

Added: cfe/trunk/test/Parser/cxx11-user-defined-literals.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx11-user-defined-literals.cpp?rev=152098&view=auto
==============================================================================
--- cfe/trunk/test/Parser/cxx11-user-defined-literals.cpp (added)
+++ cfe/trunk/test/Parser/cxx11-user-defined-literals.cpp Mon Mar  5 21:21:47 2012
@@ -0,0 +1,60 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s -fms-extensions -triple x86_64-apple-darwin9.0.0
+
+// A ud-suffix cannot be used on string literals in a whole bunch of contexts:
+
+#include "foo"_bar // expected-error {{expected "FILENAME" or <FILENAME>}}
+#line 1 "foo"_bar // expected-error {{user-defined suffix cannot be used here}}
+# 1 "foo"_bar 1 // expected-error {{user-defined suffix cannot be used here}}
+#ident "foo"_bar // expected-error {{user-defined suffix cannot be used here}}
+_Pragma("foo"_bar) // expected-error {{user-defined suffix cannot be used here}}
+#pragma comment(lib, "foo"_bar) // expected-error {{user-defined suffix cannot be used here}}
+_Pragma("comment(lib, \"foo\"_bar)") // expected-error {{user-defined suffix cannot be used here}}
+#pragma message "hi"_there // expected-error {{user-defined suffix cannot be used here}} expected-warning {{hi}}
+#pragma push_macro("foo"_bar) // expected-error {{user-defined suffix cannot be used here}}
+#if __has_warning("-Wan-island-to-discover"_bar) // expected-error {{user-defined suffix cannot be used here}}
+#elif __has_include("foo"_bar) // expected-error {{expected "FILENAME" or <FILENAME>}}
+#endif
+
+extern "C++"_x {} // expected-error {{user-defined suffix cannot be used here}} expected-error {{unknown linkage language}}
+
+int f() {
+  asm("mov %eax, %rdx"_foo); // expected-error {{user-defined suffix cannot be used here}}
+}
+
+static_assert(true, "foo"_bar); // expected-error {{user-defined suffix cannot be used here}}
+
+int cake() __attribute__((availability(macosx, unavailable, message = "is a lie"_x))); // expected-error {{user-defined suffix cannot be used here}}
+
+// A ud-suffix cannot be used on character literals in preprocessor constant
+// expressions:
+#if 'x'_y - u'x'_z // expected-error 2{{character literal with user-defined suffix cannot be used in preprocessor constant expression}}
+#error error
+#endif
+
+// But they can appear in expressions.
+constexpr char operator"" _id(char c) { return c; }
+constexpr wchar_t operator"" _id(wchar_t c) { return c; }
+constexpr char16_t operator"" _id(char16_t c) { return c; }
+constexpr char32_t operator"" _id(char32_t c) { return c; }
+
+using size_t = decltype(sizeof(int));
+constexpr const char operator"" _id(const char *p, size_t n) { return *p; }
+constexpr const wchar_t operator"" _id(const wchar_t *p, size_t n) { return *p; }
+constexpr const char16_t operator"" _id(const char16_t *p, size_t n) { return *p; }
+constexpr const char32_t operator"" _id(const char32_t *p, size_t n) { return *p; }
+
+template<int n> struct S {};
+S<"a"_id[0]> sa;
+S<L"b"_id[0]> sb;
+S<u8"c"_id[0]> sc;
+S<u"d"_id[0]> sd;
+S<U"e"_id[0]> se;
+
+S<'w'_id> sw;
+S<L'x'_id> sx;
+S<u'y'_id> sy;
+S<U'z'_id> sz;
+
+void h() {
+  (void)"test"_id "test" L"test";
+}

Added: cfe/trunk/test/Parser/objcxx11-user-defined-literal.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/objcxx11-user-defined-literal.mm?rev=152098&view=auto
==============================================================================
--- cfe/trunk/test/Parser/objcxx11-user-defined-literal.mm (added)
+++ cfe/trunk/test/Parser/objcxx11-user-defined-literal.mm Mon Mar  5 21:21:47 2012
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+id x = @"foo"_bar; // expected-error{{user-defined suffix cannot be used here}}





More information about the cfe-commits mailing list