aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticGroups.td10
-rw-r--r--include/clang/Basic/DiagnosticLexKinds.td7
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td10
-rw-r--r--lib/Lex/Lexer.cpp15
-rw-r--r--lib/Sema/SemaDeclCXX.cpp27
-rw-r--r--test/CXX/lex/lex.literal/lex.ext/p1.cpp4
-rw-r--r--test/CXX/lex/lex.literal/lex.ext/p10.cpp8
-rw-r--r--test/CXX/over/over.oper/over.literal/p8.cpp8
-rw-r--r--test/FixIt/fixit-cxx0x.cpp5
-rw-r--r--test/FixIt/fixit-cxx11-compat.cpp4
-rw-r--r--test/Parser/cxx0x-literal-operators.cpp8
-rw-r--r--test/SemaCXX/cxx0x-compat.cpp6
12 files changed, 67 insertions, 45 deletions
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index c40ff03174..f5de122e0e 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/include/clang/Basic/DiagnosticGroups.td
@@ -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++">;
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td
index d31a48b656..4fd55ef4e7 100644
--- a/include/clang/Basic/DiagnosticLexKinds.td
+++ b/include/clang/Basic/DiagnosticLexKinds.td
@@ -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<
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 07a94be54b..0f5e7670ac 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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">;
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp
index 0d388c6d01..0b342389a0 100644
--- a/lib/Lex/Lexer.cpp
+++ b/lib/Lex/Lexer.cpp
@@ -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;
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index abcaf98357..221cc6e53e 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -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;
}
diff --git a/test/CXX/lex/lex.literal/lex.ext/p1.cpp b/test/CXX/lex/lex.literal/lex.ext/p1.cpp
index c167e822eb..1c227a1b10 100644
--- a/test/CXX/lex/lex.literal/lex.ext/p1.cpp
+++ b/test/CXX/lex/lex.literal/lex.ext/p1.cpp
@@ -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
diff --git a/test/CXX/lex/lex.literal/lex.ext/p10.cpp b/test/CXX/lex/lex.literal/lex.ext/p10.cpp
index 6652c9a890..dc86fdf07f 100644
--- a/test/CXX/lex/lex.literal/lex.ext/p10.cpp
+++ b/test/CXX/lex/lex.literal/lex.ext/p10.cpp
@@ -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 ';'}}
}
diff --git a/test/CXX/over/over.oper/over.literal/p8.cpp b/test/CXX/over/over.oper/over.literal/p8.cpp
index 1837aafc7b..3f76082d10 100644
--- a/test/CXX/over/over.oper/over.literal/p8.cpp
+++ b/test/CXX/over/over.oper/over.literal/p8.cpp
@@ -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}}
diff --git a/test/FixIt/fixit-cxx0x.cpp b/test/FixIt/fixit-cxx0x.cpp
index da6bf2fe44..2bf9b20326 100644
--- a/test/FixIt/fixit-cxx0x.cpp
+++ b/test/FixIt/fixit-cxx0x.cpp
@@ -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}}
diff --git a/test/FixIt/fixit-cxx11-compat.cpp b/test/FixIt/fixit-cxx11-compat.cpp
index 3a5ec84a45..39ae439d26 100644
--- a/test/FixIt/fixit-cxx11-compat.cpp
+++ b/test/FixIt/fixit-cxx11-compat.cpp
@@ -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}}
diff --git a/test/Parser/cxx0x-literal-operators.cpp b/test/Parser/cxx0x-literal-operators.cpp
index 4fcbad490d..1881fcb7f0 100644
--- a/test/Parser/cxx0x-literal-operators.cpp
+++ b/test/Parser/cxx0x-literal-operators.cpp
@@ -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}}
diff --git a/test/SemaCXX/cxx0x-compat.cpp b/test/SemaCXX/cxx0x-compat.cpp
index 611dcc755e..123008aadd 100644
--- a/test/SemaCXX/cxx0x-compat.cpp
+++ b/test/SemaCXX/cxx0x-compat.cpp
@@ -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}}