diff options
-rw-r--r-- | include/clang/Basic/DiagnosticGroups.td | 10 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticLexKinds.td | 7 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 10 | ||||
-rw-r--r-- | lib/Lex/Lexer.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 27 | ||||
-rw-r--r-- | test/CXX/lex/lex.literal/lex.ext/p1.cpp | 4 | ||||
-rw-r--r-- | test/CXX/lex/lex.literal/lex.ext/p10.cpp | 8 | ||||
-rw-r--r-- | test/CXX/over/over.oper/over.literal/p8.cpp | 8 | ||||
-rw-r--r-- | test/FixIt/fixit-cxx0x.cpp | 5 | ||||
-rw-r--r-- | test/FixIt/fixit-cxx11-compat.cpp | 4 | ||||
-rw-r--r-- | test/Parser/cxx0x-literal-operators.cpp | 8 | ||||
-rw-r--r-- | test/SemaCXX/cxx0x-compat.cpp | 6 |
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}} |