]> granicus.if.org Git - clang/commitdiff
Implement C++11 [lex.ext]p10 for string and character literals: a ud-suffix not
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 8 Mar 2012 02:39:21 +0000 (02:39 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 8 Mar 2012 02:39:21 +0000 (02:39 +0000)
starting with an underscore is ill-formed.

Since this rule rejects programs that were using <inttypes.h>'s macros, recover
from this error by treating the ud-suffix as a separate preprocessing-token,
with a DefaultError ExtWarn. The approach of treating such cases as two tokens
is under discussion for standardization, but is in any case a conforming
extension and allows existing codebases to keep building while the committee
makes up its mind.

Reword the warning on the definition of literal operators not starting with
underscores (which are, strangely, legal) to more explicitly state that such
operators can't be called by literals. Remove the special-case diagnostic for
hexfloats, since it was both triggering in the wrong cases and incorrect.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152287 91177308-0d34-0410-b5e6-96231b3b80d8

12 files changed:
include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticLexKinds.td
include/clang/Basic/DiagnosticSemaKinds.td
lib/Lex/Lexer.cpp
lib/Sema/SemaDeclCXX.cpp
test/CXX/lex/lex.literal/lex.ext/p1.cpp
test/CXX/lex/lex.literal/lex.ext/p10.cpp
test/CXX/over/over.oper/over.literal/p8.cpp
test/FixIt/fixit-cxx0x.cpp
test/FixIt/fixit-cxx11-compat.cpp
test/Parser/cxx0x-literal-operators.cpp
test/SemaCXX/cxx0x-compat.cpp

index c40ff031741441ee5358345c9a8ec9e1dc5203f6..f5de122e0e31fb5bf8ca7221a4073bc42784bcfb 100644 (file)
@@ -79,7 +79,15 @@ def : DiagGroup<"c++0x-narrowing", [CXX11Narrowing]>;
 // Name of this warning in GCC
 def : DiagGroup<"narrowing", [CXX11Narrowing]>;
 
-def CXX11Compat : DiagGroup<"c++11-compat", [CXX11Narrowing]>;
+def CXX11CompatReservedUserDefinedLiteral :
+  DiagGroup<"c++11-compat-reserved-user-defined-literal">;
+def ReservedUserDefinedLiteral :
+  DiagGroup<"reserved-user-defined-literal",
+            [CXX11CompatReservedUserDefinedLiteral]>;
+
+def CXX11Compat : DiagGroup<"c++11-compat",
+                            [CXX11Narrowing,
+                             CXX11CompatReservedUserDefinedLiteral]>;
 def : DiagGroup<"c++0x-compat", [CXX11Compat]>;
 
 def : DiagGroup<"effc++">;
index d31a48b656169d30cafb675fce7724b7fa700cd9..4fd55ef4e7bb29c87563497e39ab41d2eb91544a 100644 (file)
@@ -134,6 +134,13 @@ def warn_cxx98_compat_unicode_literal : Warning<
 def warn_cxx11_compat_user_defined_literal : Warning<
   "identifier after literal will be treated as a user-defined literal suffix "
   "in C++11">, InGroup<CXX11Compat>, DefaultIgnore;
+def warn_cxx11_compat_reserved_user_defined_literal : Warning<
+  "identifier after literal will be treated as a reserved user-defined literal "
+  "suffix in C++11">,
+  InGroup<CXX11CompatReservedUserDefinedLiteral>, DefaultIgnore;
+def ext_reserved_user_defined_literal : ExtWarn<
+  "invalid suffix on literal; C++11 requires a space between literal and "
+  "identifier">, InGroup<ReservedUserDefinedLiteral>, DefaultError;
 def err_unsupported_string_concat : Error<
   "unsupported non-standard concatenation of string literals">;
 def err_string_concat_mixed_suffix : Error<
index 07a94be54b7331543774b7ebb969b46f8c6b4df8..0f5e7670ac1379709b87583985d4de1ccf51b88e 100644 (file)
@@ -4757,13 +4757,11 @@ def err_literal_operator_params : Error<
   "parameter declaration for literal operator %0 is not valid">;
 def err_literal_operator_extern_c : Error<
   "literal operator must have C++ linkage">;
-def warn_user_literal_hexfloat : Warning<
-  "user-defined literal with suffix '%0' is preempted by C99 hexfloat "
-  "extension">, InGroup<UserDefinedLiterals>;
 def warn_user_literal_reserved : Warning<
-  "user-defined literals not starting with '_' are reserved by the "
-  "implementation">, InGroup<UserDefinedLiterals>;
-  
+  "user-defined literal suffixes not starting with '_' are reserved; "
+  "no literal will invoke this operator">,
+  InGroup<UserDefinedLiterals>;
+
 // C++ conversion functions
 def err_conv_function_not_member : Error<
   "conversion function must be a non-static member function">;
index 0d388c6d01ee7fc09b5c007eaaec16ce6c72f1cb..0b342389a035338d4e5490aba220d0ee6477a2c2 100644 (file)
@@ -1584,7 +1584,20 @@ const char *Lexer::LexUDSuffix(Token &Result, const char *CurPtr) {
   if (isIdentifierHead(C)) {
     if (!getFeatures().CPlusPlus0x) {
       if (!isLexingRawMode())
-        Diag(CurPtr, diag::warn_cxx11_compat_user_defined_literal)
+        Diag(CurPtr,
+             C == '_' ? diag::warn_cxx11_compat_user_defined_literal
+                      : diag::warn_cxx11_compat_reserved_user_defined_literal)
+          << FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
+      return CurPtr;
+    }
+
+    // C++11 [lex.ext]p10, [usrlit.suffix]p1: A program containing a ud-suffix
+    // that does not start with an underscore is ill-formed. As a conforming
+    // extension, we treat all such suffixes as if they had whitespace before
+    // them.
+    if (C != '_') {
+      if (!isLexingRawMode())
+        Diag(CurPtr, diag::ext_reserved_user_defined_literal)
           << FixItHint::CreateInsertion(getSourceLocation(CurPtr), " ");
       return CurPtr;
     }
index abcaf983572d5af97856af00e991699daf639d0d..221cc6e53eeeb22784e6b1afca60e328d72a9b74 100644 (file)
@@ -9383,30 +9383,15 @@ FinishedParams:
     return true;
   }
 
-  StringRef LiteralName 
+  StringRef LiteralName
     = FnDecl->getDeclName().getCXXLiteralIdentifier()->getName();
   if (LiteralName[0] != '_') {
-    // C++0x [usrlit.suffix]p1:
-    //   Literal suffix identifiers that do not start with an underscore are 
-    //   reserved for future standardization.
-    bool IsHexFloat = true;
-    if (LiteralName.size() > 1 && 
-        (LiteralName[0] == 'P' || LiteralName[0] == 'p')) {
-      for (unsigned I = 1, N = LiteralName.size(); I < N; ++I) {
-        if (!isdigit(LiteralName[I])) {
-          IsHexFloat = false;
-          break;
-        }
-      }
-    }
-    
-    if (IsHexFloat)
-      Diag(FnDecl->getLocation(), diag::warn_user_literal_hexfloat)
-        << LiteralName;
-    else
-      Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved);
+    // C++11 [usrlit.suffix]p1:
+    //   Literal suffix identifiers that do not start with an underscore
+    //   are reserved for future standardization.
+    Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved);
   }
-  
+
   return false;
 }
 
index c167e822ebdf8bbe5a3bdfe37faab96a7b899896..1c227a1b10d385ab5a1019b55d5625cb9a728835 100644 (file)
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
 
-void operator "" p31(long double); // expected-warning{{user-defined literal with suffix 'p31' is preempted by C99 hexfloat extension}}
+void operator "" p31(long double); // expected-warning{{user-defined literal suffixes not starting with '_' are reserved}}
 void operator "" _p31(long double);
-long double operator "" pi(long double); // expected-warning{{user-defined literals not starting with '_' are reserved by the implementation}}
+long double operator "" pi(long double); // expected-warning{{user-defined literal suffixes not starting with '_' are reserved}}
 
 float hexfloat = 0x1p31; // allow hexfloats
index 6652c9a890f1cc8fc75f0780e1fa77e4b84c930c..dc86fdf07f62a9d998336b50d62a423dadbb19d0 100644 (file)
@@ -1,8 +1,8 @@
 // RUN: %clang_cc1 -std=c++11 -verify %s
 
 using size_t = decltype(sizeof(int));
-void operator "" wibble(const char *); // expected-warning {{preempted}}
-void operator "" wibble(const char *, size_t); // expected-warning {{preempted}}
+void operator "" wibble(const char *); // expected-warning {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}}
+void operator "" wibble(const char *, size_t); // expected-warning {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}}
 
 template<typename T>
 void f() {
@@ -10,6 +10,6 @@ void f() {
   // FIXME: Reject these for the right reason.
   123wibble; // expected-error {{suffix 'wibble'}}
   123.0wibble; // expected-error {{suffix 'wibble'}}
-  ""wibble;
-  R"x("hello")x"wibble;
+  const char *p = ""wibble; // expected-error {{invalid suffix on literal; C++11 requires a space between literal and identifier}} expected-error {{expected ';'}}
+  const char *q = R"x("hello")x"wibble; // expected-error {{invalid suffix on literal; C++11 requires a space between literal and identifier}} expected-error {{expected ';'}}
 }
index 1837aafc7bc9995d3688ac6e703abb1afbe851ef..3f76082d10a970453f3661c7bac3f99ff44e355f 100644 (file)
@@ -9,9 +9,11 @@ void operator "" _km(long double); // ok
 string operator "" _i18n(const char*, std::size_t); // ok
 // 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 {{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}}
+float operator ""E(const char *); // expected-error {{C++11 requires a space between literal and identifier}} expected-warning {{reserved}}
+float operator " " B(const char *); // expected-error {{must be '""'}} expected-warning {{reserved}}
 string operator "" 5X(const char *, std::size_t); // expected-error {{expected identifier}}
 double operator "" _miles(double); // expected-error {{parameter}}
 template<char...> int operator "" j(const char*); // expected-error {{parameter}}
+
+// FIXME: Accept this as an extension, with a fix-it to add the space
+float operator ""_E(const char *); // expected-error {{C++11 requires a space between the "" and the user-defined suffix in a literal operator}}
index da6bf2fe446b49667b66b15489c45aff8102ea64..2bf9b20326e5a051c360035d03fefcb4df5baf24 100644 (file)
@@ -60,3 +60,8 @@ void S2::f(int i) {
   (void)[] mutable { }; // expected-error{{lambda requires '()' before 'mutable'}}
   (void)[] -> int { }; // expected-error{{lambda requires '()' before return type}}
 }
+
+#define bar "bar"
+const char *p = "foo"bar; // expected-error {{requires a space between}}
+#define ord - '0'
+int k = '4'ord; // expected-error {{requires a space between}}
index 3a5ec84a45498ddc5c0413f530d46b881617ce97..39ae439d266b6b5766f7789a1a24b218e142670c 100644 (file)
@@ -6,4 +6,6 @@
 // This is a test of the code modification hints for C++11-compatibility problems.
 
 #define bar "bar"
-const char *p = "foo"bar; // expected-warning {{will be treated as a user-defined literal suffix}}
+const char *p = "foo"bar; // expected-warning {{will be treated as a reserved user-defined literal suffix}}
+#define _bar "_bar"
+const char *q = "foo"_bar; // expected-warning {{will be treated as a user-defined literal suffix}}
index 4fcbad490d387ae6b1381505061804db300b5977..1881fcb7f09904c43972fc18f92a8553165df511 100644 (file)
@@ -1,6 +1,8 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
 
 void operator "" (const char *); // expected-error {{expected identifier}}
-void operator "k" foo(const char *); // expected-error {{string literal after 'operator' must be '""'}} \
-// expected-warning{{user-defined literal with suffix 'foo' is preempted by C99 hexfloat extension}}
-void operator "" tester (const char *); // expected-warning{{user-defined literal with suffix 'tester' is preempted by C99 hexfloat extension}}
+void operator "k" foo(const char *); // \
+  expected-error {{string literal after 'operator' must be '""'}} \
+  expected-warning{{user-defined literal suffixes not starting with '_' are reserved}}
+void operator "" tester (const char *); // \
+  expected-warning{{user-defined literal suffixes not starting with '_' are reserved}}
index 611dcc755ec9b8790b36f3bc08a87e1866ea0e24..123008aadd81754e38ed908edeb8747eba70e53a 100644 (file)
@@ -32,8 +32,8 @@ t = { 1234 }; // expected-warning {{constant expression evaluates to 1234 which
 int printf(const char *, ...);
 typedef __typeof(sizeof(int)) size_t;
 void h(size_t foo, size_t bar) {
-  printf("foo is %"PRIuS", bar is %"PRIuS, foo, bar); // expected-warning 2{{identifier after literal will be treated as a user-defined literal suffix in C++11}}
+  printf("foo is %"PRIuS", bar is %"PRIuS, foo, bar); // expected-warning 2{{identifier after literal will be treated as a reserved user-defined literal suffix in C++11}}
 }
 
-#define x + 1
-char c = 'x'x; // expected-warning {{will be treated as a user-defined literal suffix}}
+#define _x + 1
+char c = 'x'_x; // expected-warning {{will be treated as a user-defined literal suffix}}