From: Richard Smith Date: Thu, 8 Mar 2012 02:39:21 +0000 (+0000) Subject: Implement C++11 [lex.ext]p10 for string and character literals: a ud-suffix not X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2fb4ae36825ca3a0cbe7e845c5747062870066be;p=clang Implement C++11 [lex.ext]p10 for string and character literals: a ud-suffix not starting with an underscore is ill-formed. Since this rule rejects programs that were using '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 --- 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, 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, DefaultIgnore; +def ext_reserved_user_defined_literal : ExtWarn< + "invalid suffix on literal; C++11 requires a space between literal and " + "identifier">, InGroup, 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; def warn_user_literal_reserved : Warning< - "user-defined literals not starting with '_' are reserved by the " - "implementation">, InGroup; - + "user-defined literal suffixes not starting with '_' are reserved; " + "no literal will invoke this operator">, + InGroup; + // 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 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 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 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}}