From 21dc8df292d85b7f48f75ea2a707be6c4971e2f9 Mon Sep 17 00:00:00 2001 From: erichkeane Date: Thu, 3 Oct 2024 09:41:08 -0700 Subject: [PATCH 1/3] Turn Wdeprecated-literal-operator on by default It would be nice to see what our users think about this change, as this is something that WG21/EWG quite wants to fix a handful of questionable issues with UB. Depending on the outcome of this after being committed, we might instead suggest EWG undeprecate this, and require a bit of 'magic' from the lexer. Additionally, this patch makes it so we emit this diagnostic ALSO in cases where the literal name is reserved. It doesn't make sense to limit that. --- clang/docs/ReleaseNotes.rst | 22 +++++++ .../clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/lib/Sema/SemaExprCXX.cpp | 21 +++--- clang/test/CXX/drs/cwg14xx.cpp | 2 +- clang/test/CXX/drs/cwg17xx.cpp | 3 + clang/test/CXX/drs/cwg25xx.cpp | 3 + clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp | 2 +- .../test/CXX/lex/lex.literal/lex.ext/p10.cpp | 2 +- .../test/CXX/lex/lex.literal/lex.ext/p11.cpp | 6 +- clang/test/CXX/lex/lex.literal/lex.ext/p3.cpp | 10 +-- clang/test/CXX/lex/lex.literal/lex.ext/p4.cpp | 10 +-- clang/test/CXX/lex/lex.literal/lex.ext/p5.cpp | 8 +-- clang/test/CXX/lex/lex.literal/lex.ext/p6.cpp | 8 +-- clang/test/CXX/lex/lex.literal/lex.ext/p7.cpp | 6 +- clang/test/CXX/lex/lex.literal/lex.ext/p8.cpp | 6 +- clang/test/CXX/lex/lex.literal/lex.ext/p9.cpp | 2 +- .../CXX/over/over.oper/over.literal/p2.cpp | 28 ++++---- .../CXX/over/over.oper/over.literal/p3.cpp | 66 +++++++++---------- .../CXX/over/over.oper/over.literal/p5.cpp | 20 +++--- .../CXX/over/over.oper/over.literal/p6.cpp | 12 ++-- .../CXX/over/over.oper/over.literal/p7.cpp | 10 +-- .../CXX/over/over.oper/over.literal/p8.cpp | 16 ++--- clang/test/FixIt/fixit-c++11.cpp | 4 +- clang/test/Parser/cxx0x-literal-operators.cpp | 6 +- .../Parser/cxx11-user-defined-literals.cpp | 29 ++++---- .../cxx11-user-defined-literals-unused.cpp | 4 +- .../SemaCXX/cxx11-user-defined-literals.cpp | 60 ++++++++--------- clang/test/SemaCXX/cxx2a-consteval.cpp | 6 +- clang/test/SemaCXX/cxx98-compat.cpp | 2 +- clang/test/SemaCXX/literal-operators.cpp | 46 ++++++------- ...ser-defined-literals-in-system-headers.cpp | 3 +- clang/test/SemaCXX/reserved-identifier.cpp | 8 ++- clang/test/SemaCXX/warn-xor-as-pow.cpp | 6 +- 33 files changed, 237 insertions(+), 202 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 44d5f348ed2d54..edd1f1d2302d58 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -99,6 +99,20 @@ C++ Specific Potentially Breaking Changes // Was error, now evaluates to false. constexpr bool b = f() == g(); +- The warning ``-Wdeprecated-literal-operator`` is now on by default, as this is + something that WG21 has shown interest in removing from the language. The + result is that anyone who is compiling with ``-Werror`` should see this + diagnostic. To fix this diagnostic, simply removing the space character from + between the ``operator""`` and the user defined literal name will make the + source no longer deprecated. This is consistent with CWG2521. + + .. code-block:: c++ + + // Now diagnoses by default. + unsigned operator"" _udl_name(unsigned long long); + // Fixed version: + unsigned operator""_udl_name(unsigned long long); + ABI Changes in This Version --------------------------- @@ -216,6 +230,10 @@ Resolutions to C++ Defect Reports - Clang now allows trailing requires clause on explicit deduction guides. (`CWG2707: Deduction guides cannot have a trailing requires-clause `_). +- Clang now diagnoses a space in the first production of a ``literal-operator-id`` + by default. + (`CWG2521: User-defined literals and reserved identifiers `_). + C Language Changes ------------------ @@ -378,6 +396,10 @@ Improvements to Clang's diagnostics - Clang now emits a diagnostic note at the class declaration when the method definition does not match any declaration (#GH110638). +- Clang now emits a ``-Wdepredcated-literal-operator`` diagnostic, even if the + name was a reserved name, which we improperly allowed to suppress the + diagnostic. + Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index dc84110ef78211..3c9f6ecb506e36 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -439,7 +439,7 @@ def warn_reserved_extern_symbol: Warning< InGroup, DefaultIgnore; def warn_deprecated_literal_operator_id: Warning< "identifier %0 preceded by whitespace in a literal operator declaration " - "is deprecated">, InGroup, DefaultIgnore; + "is deprecated">, InGroup; def warn_reserved_module_name : Warning< "%0 is a reserved name for a module">, InGroup; def warn_import_implementation_partition_unit_in_interface_unit : Warning< diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index d490452e91c3bb..44ebfbaa043ce2 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -503,17 +503,16 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS, const IdentifierInfo *II = Name.Identifier; ReservedIdentifierStatus Status = II->isReserved(PP.getLangOpts()); SourceLocation Loc = Name.getEndLoc(); - if (!PP.getSourceManager().isInSystemHeader(Loc)) { - if (auto Hint = FixItHint::CreateReplacement( - Name.getSourceRange(), - (StringRef("operator\"\"") + II->getName()).str()); - isReservedInAllContexts(Status)) { - Diag(Loc, diag::warn_reserved_extern_symbol) - << II << static_cast(Status) << Hint; - } else { - Diag(Loc, diag::warn_deprecated_literal_operator_id) << II << Hint; - } - } + + auto Hint = FixItHint::CreateReplacement( + Name.getSourceRange(), + (StringRef("operator\"\"") + II->getName()).str()); + + Diag(Loc, diag::warn_deprecated_literal_operator_id) << II << Hint; + + if (isReservedInAllContexts(Status)) + Diag(Loc, diag::warn_reserved_extern_symbol) + << II << static_cast(Status) << Hint; } if (!SS.isValid()) diff --git a/clang/test/CXX/drs/cwg14xx.cpp b/clang/test/CXX/drs/cwg14xx.cpp index 5301185d046982..cb2f34bf5e427f 100644 --- a/clang/test/CXX/drs/cwg14xx.cpp +++ b/clang/test/CXX/drs/cwg14xx.cpp @@ -627,7 +627,7 @@ int i = N::f(); namespace cwg1479 { // cwg1479: 3.1 #if __cplusplus >= 201103L - int operator"" _a(const char*, std::size_t = 0); + int operator""_a(const char*, std::size_t = 0); // since-cxx11-error@-1 {{literal operator cannot have a default argument}} #endif } diff --git a/clang/test/CXX/drs/cwg17xx.cpp b/clang/test/CXX/drs/cwg17xx.cpp index fb53a56923b104..907240b0fc8b28 100644 --- a/clang/test/CXX/drs/cwg17xx.cpp +++ b/clang/test/CXX/drs/cwg17xx.cpp @@ -203,6 +203,9 @@ namespace cwg1762 { // cwg1762: 14 float operator ""E(const char *); // since-cxx11-error@-1 {{invalid suffix on literal; C++11 requires a space between literal and identifier}} // since-cxx11-warning@-2 {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}} + // since-cxx11-warning@-3 {{identifier 'E' preceded by whitespace in a literal operator declaration is deprecated}} + // FIXME: We could probably do a better job reacting to the fixit here, the + // fact that we complain about the space we added is a little strange. #endif } diff --git a/clang/test/CXX/drs/cwg25xx.cpp b/clang/test/CXX/drs/cwg25xx.cpp index 1924008f15ba58..87a728088ee6e4 100644 --- a/clang/test/CXX/drs/cwg25xx.cpp +++ b/clang/test/CXX/drs/cwg25xx.cpp @@ -88,6 +88,9 @@ operator"" _div(); using ::cwg2521::operator"" _\u03C0___; using ::cwg2521::operator""_div; // since-cxx11-warning@-2 {{identifier '_π___' preceded by whitespace in a literal operator declaration is deprecated}} + +long double operator"" _RESERVED(long double); +// since-cxx11-warning@-1 {{identifier '_RESERVED' preceded by whitespace in a literal operator declaration is deprecated}} #pragma clang diagnostic pop #endif } // namespace cwg2521 diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp index 1c227a1b10d385..ec478fbba60a18 100644 --- a/clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wno-deprecated-literal-operator -verify %s void operator "" p31(long double); // expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} void operator "" _p31(long double); diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp index 1b5d3880cb6129..6a9d713ca72d2e 100644 --- a/clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++11 -verify %s +// RUN: %clang_cc1 -std=c++11 -Wno-deprecated-literal-operator -verify %s using size_t = decltype(sizeof(int)); void operator "" wibble(const char *); // expected-warning {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}} diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p11.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p11.cpp index 8b5fcf4b609b65..d69a58a7dfad20 100644 --- a/clang/test/CXX/lex/lex.literal/lex.ext/p11.cpp +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p11.cpp @@ -6,16 +6,16 @@ template struct same_type; template struct same_type {}; template using X = T; template...> -int operator "" _x(); // expected-warning {{string literal operator templates are a GNU extension}} +int operator ""_x(); // expected-warning {{string literal operator templates are a GNU extension}} template -double operator "" _x(); +double operator ""_x(); auto a="string"_x; auto b=42_x; same_type test_a; same_type test_b; -char operator "" _x(const char *begin, size_t size); +char operator ""_x(const char *begin, size_t size); auto c="string"_x; auto d=L"string"_x; same_type test_c; diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p3.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p3.cpp index d764989312c246..e5ab09c628bcfa 100644 --- a/clang/test/CXX/lex/lex.literal/lex.ext/p3.cpp +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p3.cpp @@ -1,18 +1,18 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s -int &operator "" _x1 (unsigned long long); +int &operator ""_x1 (unsigned long long); int &i1 = 0x123_x1; -double &operator "" _x1 (const char *); +double &operator ""_x1 (const char *); int &i2 = 45_x1; -template char &operator "" _x1 (); +template char &operator ""_x1 (); int &i3 = 0377_x1; int &i4 = 90000000000000000000000000000000000000000000000_x1; // expected-error {{integer literal is too large to be represented in any integer type}} -double &operator "" _x2 (const char *); +double &operator ""_x2 (const char *); double &i5 = 123123123123123123123123123123123123123123123_x2; -template constexpr int operator "" _x3() { return sizeof...(Cs); } +template constexpr int operator ""_x3() { return sizeof...(Cs); } static_assert(123456789012345678901234567890123456789012345678901234567890_x3 == 60, ""); diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p4.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p4.cpp index 011e832c69d729..7dbe70ce084e76 100644 --- a/clang/test/CXX/lex/lex.literal/lex.ext/p4.cpp +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p4.cpp @@ -1,18 +1,18 @@ // RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s -int &operator "" _x1 (long double); +int &operator ""_x1 (long double); int &i1 = 0.123_x1; -double &operator "" _x1 (const char *); +double &operator ""_x1 (const char *); int &i2 = 45._x1; -template char &operator "" _x1 (); +template char &operator ""_x1 (); int &i3 = 0377e-1_x1; int &i4 = 1e1000000_x1; // expected-warning {{too large for type 'long double'}} -double &operator "" _x2 (const char *); +double &operator ""_x2 (const char *); double &i5 = 1e1000000_x2; -template constexpr int operator "" _x3() { return sizeof...(Cs); } +template constexpr int operator ""_x3() { return sizeof...(Cs); } static_assert(1e1000000_x3 == 9, ""); diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p5.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p5.cpp index aee20545ececfc..afadba282e626c 100644 --- a/clang/test/CXX/lex/lex.literal/lex.ext/p5.cpp +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p5.cpp @@ -3,19 +3,19 @@ using size_t = decltype(sizeof(int)); -int &operator "" _x1 (const char *); -double &operator "" _x1 (const char *, size_t); +int &operator ""_x1 (const char *); +double &operator ""_x1 (const char *, size_t); double &i1 = "foo"_x1; #if __cplusplus >= 202002L using char8 = float; -float &operator "" _x1 (const char8_t *, size_t); +float &operator ""_x1 (const char8_t *, size_t); #else using char8 = double; #endif char8 &i2 = u8"foo"_x1; double &i3 = L"foo"_x1; // expected-error {{no matching literal operator for call to 'operator""_x1' with arguments of types 'const wchar_t *' and 'unsigned long'}} -char &operator "" _x1(const wchar_t *, size_t); +char &operator ""_x1(const wchar_t *, size_t); char &i4 = L"foo"_x1; // ok double &i5 = R"(foo)"_x1; // ok char8 &i6 = u\ diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p6.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p6.cpp index 23cd7081d5e3ee..b1df641f2dc43c 100644 --- a/clang/test/CXX/lex/lex.literal/lex.ext/p6.cpp +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p6.cpp @@ -2,13 +2,13 @@ using size_t = decltype(sizeof(int)); -int &operator "" _x1 (const char *); +int &operator ""_x1 (const char *); double &i1 = 'a'_x1; // expected-error {{no matching literal operator}} -double &operator "" _x1 (wchar_t); +double &operator ""_x1 (wchar_t); double &i2 = L'a'_x1; double &i3 = 'a'_x1; // expected-error {{no matching literal operator}} -double &i4 = operator"" _x1('a'); // ok +double &i4 = operator""_x1('a'); // ok -char &operator "" _x1(char16_t); +char &operator ""_x1(char16_t); char &i5 = u'a'_x1; // ok double &i6 = L'a'_x1; // ok diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p7.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p7.cpp index 0b40ecdc143fcb..d571fcb8697eb0 100644 --- a/clang/test/CXX/lex/lex.literal/lex.ext/p7.cpp +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p7.cpp @@ -10,9 +10,9 @@ template struct same_type {}; namespace std_example { -long double operator "" _w(long double); -std::string operator "" _w(const char16_t*, size_t); -unsigned operator "" _w(const char*); +long double operator ""_w(long double); +std::string operator ""_w(const char16_t*, size_t); +unsigned operator ""_w(const char*); int main() { auto v1 = 1.2_w; // calls operator""_w(1.2L) auto v2 = u"one"_w; // calls operator""_w(u"one", 3) diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p8.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p8.cpp index d9078221ff5e3a..67d976263e0167 100644 --- a/clang/test/CXX/lex/lex.literal/lex.ext/p8.cpp +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p8.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -std=c++11 -verify %s using size_t = decltype(sizeof(int)); -constexpr const char *operator "" _id(const char *p, size_t) { return p; } +constexpr const char *operator ""_id(const char *p, size_t) { return p; } constexpr const char *s = "foo"_id "bar" "baz"_id "quux"; constexpr bool streq(const char *p, const char *q) { @@ -9,8 +9,8 @@ constexpr bool streq(const char *p, const char *q) { } static_assert(streq(s, "foobarbazquux"), ""); -constexpr const char *operator "" _trim(const char *p, size_t n) { - return *p == ' ' ? operator "" _trim(p + 1, n - 1) : p; +constexpr const char *operator ""_trim(const char *p, size_t n) { + return *p == ' ' ? operator ""_trim(p + 1, n - 1) : p; } constexpr const char *t = " " " "_trim " foo"; static_assert(streq(t, "foo"), ""); diff --git a/clang/test/CXX/lex/lex.literal/lex.ext/p9.cpp b/clang/test/CXX/lex/lex.literal/lex.ext/p9.cpp index 65e27b41b06680..fbdedd119d3d68 100644 --- a/clang/test/CXX/lex/lex.literal/lex.ext/p9.cpp +++ b/clang/test/CXX/lex/lex.literal/lex.ext/p9.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s using size_t = decltype(sizeof(int)); -void operator "" _x(const wchar_t *, size_t); +void operator ""_x(const wchar_t *, size_t); namespace std_example { diff --git a/clang/test/CXX/over/over.oper/over.literal/p2.cpp b/clang/test/CXX/over/over.oper/over.literal/p2.cpp index f3ebadd2b8b9bc..cf26806e9e7d75 100644 --- a/clang/test/CXX/over/over.oper/over.literal/p2.cpp +++ b/clang/test/CXX/over/over.oper/over.literal/p2.cpp @@ -1,43 +1,43 @@ // RUN: %clang_cc1 -std=c++11 %s -verify -void operator "" _a(const char *); +void operator ""_a(const char *); namespace N { - using ::operator "" _a; + using ::operator ""_a; - void operator "" _b(const char *); + void operator ""_b(const char *); } -using N::operator "" _b; +using N::operator ""_b; class C { - void operator "" _c(const char *); // expected-error {{must be in a namespace or global scope}} + void operator ""_c(const char *); // expected-error {{must be in a namespace or global scope}} - static void operator "" _c(unsigned long long); // expected-error {{must be in a namespace or global scope}} + static void operator ""_c(unsigned long long); // expected-error {{must be in a namespace or global scope}} - friend void operator "" _d(const char *); + friend void operator ""_d(const char *); }; -int operator "" _e; // expected-error {{cannot be the name of a variable}} +int operator ""_e; // expected-error {{cannot be the name of a variable}} void f() { - int operator "" _f; // expected-error {{cannot be the name of a variable}} + int operator ""_f; // expected-error {{cannot be the name of a variable}} } extern "C++" { - void operator "" _g(const char *); + void operator ""_g(const char *); } -template void operator "" _h() {} +template void operator ""_h() {} -template<> void operator "" _h<'a', 'b', 'c'>() {} +template<> void operator ""_h<'a', 'b', 'c'>() {} -template void operator "" _h<'a', 'b', 'c', 'd'>(); +template void operator ""_h<'a', 'b', 'c', 'd'>(); namespace rdar13605348 { class C { - double operator"" _x(long double value) { return double(value); } // expected-error{{literal operator 'operator""_x' must be in a namespace or global scope}} + double operator""_x(long double value) { return double(value); } // expected-error{{literal operator 'operator""_x' must be in a namespace or global scope}} double value() { return 3.2_x; } // expected-error{{no matching literal operator for call to}} }; diff --git a/clang/test/CXX/over/over.oper/over.literal/p3.cpp b/clang/test/CXX/over/over.oper/over.literal/p3.cpp index 674ace9aee1929..53ebe102630843 100644 --- a/clang/test/CXX/over/over.oper/over.literal/p3.cpp +++ b/clang/test/CXX/over/over.oper/over.literal/p3.cpp @@ -3,38 +3,38 @@ using size_t = decltype(sizeof(int)); // Acceptable parameter declarations -char operator "" _a(const char *); -char operator "" _a(const char []); -char operator "" _a(unsigned long long); -char operator "" _a(long double); -char operator "" _a(char); -char operator "" _a(const volatile char); -char operator "" _a(wchar_t); -char operator "" _a(char16_t); -char operator "" _a(char32_t); -char operator "" _a(const char *, size_t); -char operator "" _a(const wchar_t *, size_t); -char operator "" _a(const char16_t *, size_t); -char operator "" _a(const char32_t *, size_t); -char operator "" _a(const char [32], size_t); +char operator ""_a(const char *); +char operator ""_a(const char []); +char operator ""_a(unsigned long long); +char operator ""_a(long double); +char operator ""_a(char); +char operator ""_a(const volatile char); +char operator ""_a(wchar_t); +char operator ""_a(char16_t); +char operator ""_a(char32_t); +char operator ""_a(const char *, size_t); +char operator ""_a(const wchar_t *, size_t); +char operator ""_a(const char16_t *, size_t); +char operator ""_a(const char32_t *, size_t); +char operator ""_a(const char [32], size_t); // Unacceptable parameter declarations -char operator "" _b(); // expected-error {{parameter}} -char operator "" _b(const wchar_t *); // expected-error {{parameter}} -char operator "" _b(long long); // expected-error {{parameter}} -char operator "" _b(double); // expected-error {{parameter}} -char operator "" _b(short); // expected-error {{parameter}} -char operator "" _a(char, int = 0); // expected-error {{parameter}} -char operator "" _b(unsigned short); // expected-error {{parameter}} -char operator "" _b(signed char); // expected-error {{parameter}} -char operator "" _b(unsigned char); // expected-error {{parameter}} -char operator "" _b(const short *, size_t); // expected-error {{parameter}} -char operator "" _b(const unsigned short *, size_t); // expected-error {{parameter}} -char operator "" _b(const signed char *, size_t); // expected-error {{parameter}} -char operator "" _b(const unsigned char *, size_t); // expected-error {{parameter}} -char operator "" _a(const volatile char *, size_t); // expected-error {{parameter}} -char operator "" _a(volatile wchar_t *, size_t); // expected-error {{parameter}} -char operator "" _a(char16_t *, size_t); // expected-error {{parameter}} -char operator "" _a(const char32_t *, size_t, bool = false); // expected-error {{parameter}} -char operator "" _a(const char *, signed long); // expected-error {{parameter}} -char operator "" _a(const char *, size_t = 0); // expected-error {{default argument}} +char operator ""_b(); // expected-error {{parameter}} +char operator ""_b(const wchar_t *); // expected-error {{parameter}} +char operator ""_b(long long); // expected-error {{parameter}} +char operator ""_b(double); // expected-error {{parameter}} +char operator ""_b(short); // expected-error {{parameter}} +char operator ""_a(char, int = 0); // expected-error {{parameter}} +char operator ""_b(unsigned short); // expected-error {{parameter}} +char operator ""_b(signed char); // expected-error {{parameter}} +char operator ""_b(unsigned char); // expected-error {{parameter}} +char operator ""_b(const short *, size_t); // expected-error {{parameter}} +char operator ""_b(const unsigned short *, size_t); // expected-error {{parameter}} +char operator ""_b(const signed char *, size_t); // expected-error {{parameter}} +char operator ""_b(const unsigned char *, size_t); // expected-error {{parameter}} +char operator ""_a(const volatile char *, size_t); // expected-error {{parameter}} +char operator ""_a(volatile wchar_t *, size_t); // expected-error {{parameter}} +char operator ""_a(char16_t *, size_t); // expected-error {{parameter}} +char operator ""_a(const char32_t *, size_t, bool = false); // expected-error {{parameter}} +char operator ""_a(const char *, signed long); // expected-error {{parameter}} +char operator ""_a(const char *, size_t = 0); // expected-error {{default argument}} diff --git a/clang/test/CXX/over/over.oper/over.literal/p5.cpp b/clang/test/CXX/over/over.oper/over.literal/p5.cpp index bfad5f00cf6c75..593aa57b76a81c 100644 --- a/clang/test/CXX/over/over.oper/over.literal/p5.cpp +++ b/clang/test/CXX/over/over.oper/over.literal/p5.cpp @@ -3,20 +3,20 @@ using size_t = decltype(sizeof(int)); template struct S {}; -template void operator "" _a(); -template S operator "" _a(); +template void operator ""_a(); +template S operator ""_a(); template struct U { - friend int operator "" _a(const char *, size_t); + friend int operator ""_a(const char *, size_t); // FIXME: It's not entirely clear whether this is intended to be legal. - friend U operator "" _a(const T *, size_t); // expected-error {{parameter}} + friend U operator ""_a(const T *, size_t); // expected-error {{parameter}} }; template struct V { - friend void operator "" _b(); // expected-error {{parameters}} + friend void operator ""_b(); // expected-error {{parameters}} }; -template void operator "" _b(); // expected-error {{template}} -template void operator "" _b(int N = 0); // expected-error {{template}} -template void operator "" _b(); // expected-error {{template}} -template T operator "" _b(const char *); // expected-error {{template}} -template int operator "" _b(const T *, size_t); // expected-error {{template}} +template void operator ""_b(); // expected-error {{template}} +template void operator ""_b(int N = 0); // expected-error {{template}} +template void operator ""_b(); // expected-error {{template}} +template T operator ""_b(const char *); // expected-error {{template}} +template int operator ""_b(const T *, size_t); // expected-error {{template}} diff --git a/clang/test/CXX/over/over.oper/over.literal/p6.cpp b/clang/test/CXX/over/over.oper/over.literal/p6.cpp index 9ecf9ccccb14c6..265050e0a00967 100644 --- a/clang/test/CXX/over/over.oper/over.literal/p6.cpp +++ b/clang/test/CXX/over/over.oper/over.literal/p6.cpp @@ -1,15 +1,15 @@ // RUN: %clang_cc1 -std=c++11 %s -verify // expected-note@+1 {{extern "C" language linkage specification begins here}} -extern "C" void operator "" _a(const char *); // expected-error {{must have C++ linkage}} -extern "C" template void operator "" _b(); // expected-error {{must have C++ linkage}} +extern "C" void operator ""_a(const char *); // expected-error {{must have C++ linkage}} +extern "C" template void operator ""_b(); // expected-error {{must have C++ linkage}} // expected-note@-1 {{extern "C" language linkage specification begins here}} extern "C" { // expected-note 4 {{extern "C" language linkage specification begins here}} - void operator "" _c(const char *); // expected-error {{must have C++ linkage}} - template void operator "" _d(); // expected-error {{must have C++ linkage}} + void operator ""_c(const char *); // expected-error {{must have C++ linkage}} + template void operator ""_d(); // expected-error {{must have C++ linkage}} namespace N { - void operator "" _e(const char *); // expected-error {{must have C++ linkage}} - template void operator "" _f(); // expected-error {{must have C++ linkage}} + void operator ""_e(const char *); // expected-error {{must have C++ linkage}} + template void operator ""_f(); // expected-error {{must have C++ linkage}} } } diff --git a/clang/test/CXX/over/over.oper/over.literal/p7.cpp b/clang/test/CXX/over/over.oper/over.literal/p7.cpp index 74e9457bb55c38..244f043d4412e7 100644 --- a/clang/test/CXX/over/over.oper/over.literal/p7.cpp +++ b/clang/test/CXX/over/over.oper/over.literal/p7.cpp @@ -1,17 +1,17 @@ // RUN: %clang_cc1 -std=c++11 %s -verify // expected-no-diagnostics -constexpr int operator "" _a(const char *c) { +constexpr int operator ""_a(const char *c) { return c[0]; } -static_assert(operator "" _a("foo") == 'f', ""); +static_assert(operator ""_a("foo") == 'f', ""); void puts(const char *); -static inline void operator "" _puts(const char *c) { +static inline void operator ""_puts(const char *c) { puts(c); } void f() { - operator "" _puts("foo"); - operator "" _puts("bar"); + operator ""_puts("foo"); + operator ""_puts("bar"); } diff --git a/clang/test/CXX/over/over.oper/over.literal/p8.cpp b/clang/test/CXX/over/over.oper/over.literal/p8.cpp index 6644bae7e610d1..9c1f6c73292abc 100644 --- a/clang/test/CXX/over/over.oper/over.literal/p8.cpp +++ b/clang/test/CXX/over/over.oper/over.literal/p8.cpp @@ -5,13 +5,13 @@ namespace std { using size_t = decltype(sizeof(int)); } -void operator "" _km(long double); // ok -string operator "" _i18n(const char*, std::size_t); // ok -template int operator "" \u03C0(); // ok, UCN for lowercase pi // expected-warning {{reserved}} -float operator ""E(const char *); // expected-error {{invalid suffix on literal}} 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 {{template}} +void operator ""_km(long double); // ok +string operator ""_i18n(const char*, std::size_t); // ok +template int operator ""\u03C0(); // ok, UCN for lowercase pi // expected-warning {{reserved}} +float operator ""E(const char *); // expected-error {{invalid suffix on literal}} expected-warning {{reserved}} expected-warning{{whitespace}} +float operator " " B(const char *); // expected-error {{must be '""'}} expected-warning {{reserved}} expected-warning{{whitespace}} +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 {{template}} expected-warning{{whitespace}} float operator ""_E(const char *); diff --git a/clang/test/FixIt/fixit-c++11.cpp b/clang/test/FixIt/fixit-c++11.cpp index 10f4a9d0554ccc..e635c14e0c2155 100644 --- a/clang/test/FixIt/fixit-c++11.cpp +++ b/clang/test/FixIt/fixit-c++11.cpp @@ -74,8 +74,8 @@ const char *p = "foo"bar; // expected-error {{requires a space between}} #define ord - '0' int k = '4'ord; // expected-error {{requires a space between}} -void operator"x" _y(char); // expected-error {{must be '""'}} -void operator L"" _z(char); // expected-error {{encoding prefix}} +void operator"x"_y(char); // expected-error {{must be '""'}} +void operator L""_z(char); // expected-error {{encoding prefix}} void operator "x" "y" U"z" ""_whoops "z" "y"(char); // expected-error {{must be '""'}} void f() { diff --git a/clang/test/Parser/cxx0x-literal-operators.cpp b/clang/test/Parser/cxx0x-literal-operators.cpp index 1881fcb7f09904..76c776a33473a6 100644 --- a/clang/test/Parser/cxx0x-literal-operators.cpp +++ b/clang/test/Parser/cxx0x-literal-operators.cpp @@ -3,6 +3,8 @@ 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 suffixes not starting with '_' are reserved}} + expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} \ + expected-warning{{identifier 'foo' preceded by whitespace in a literal operator declaration is deprecated}} void operator "" tester (const char *); // \ - expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} + expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} \ + expected-warning{{identifier 'tester' preceded by whitespace in a literal operator declaration is deprecated}} diff --git a/clang/test/Parser/cxx11-user-defined-literals.cpp b/clang/test/Parser/cxx11-user-defined-literals.cpp index cdd06729efc39a..27a7181bc9f917 100644 --- a/clang/test/Parser/cxx11-user-defined-literals.cpp +++ b/clang/test/Parser/cxx11-user-defined-literals.cpp @@ -39,19 +39,19 @@ int cake() __attribute__((availability(macosx, unavailable, message = "is a lie" #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; } +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; } +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; } -constexpr unsigned long long operator"" _id(unsigned long long n) { return n; } -constexpr long double operator"" _id(long double d) { return d; } +constexpr unsigned long long operator""_id(unsigned long long n) { return n; } +constexpr long double operator""_id(long double d) { return d; } template struct S {}; S<"a"_id> sa; @@ -98,19 +98,22 @@ _no_such_suffix; // expected-error {{'operator""_no_such_suffix'}} // is "" in translation phase 7. void operator "\ " _foo(unsigned long long); // ok +// expected-warning@-1{{identifier '_foo' preceded by whitespace in a literal operator declaration is deprecated}} void operator R"xyzzy()xyzzy" _foo(long double); // ok +// expected-warning@-1{{identifier '_foo' preceded by whitespace in a literal operator declaration is deprecated}} void operator"" "" R"()" "" _foo(const char *); // ok +// expected-warning@-1{{identifier '_foo' preceded by whitespace}} void operator ""_no_space(const char *); // ok // Ensure we diagnose the bad cases. -void operator "\0" _non_empty(const char *); // expected-error {{must be '""'}} -void operator L"" _not_char(const char *); // expected-error {{cannot have an encoding prefix}} +void operator "\0"_non_empty(const char *); // expected-error {{must be '""'}} +void operator L""_not_char(const char *); // expected-error {{cannot have an encoding prefix}} void operator "" "" U"" // expected-error {{cannot have an encoding prefix}} -"" _also_not_char(const char *); +""_also_not_char(const char *); void operator "" u8"" "\u0123" "hello"_all_of_the_things ""(const char*); // expected-error {{must be '""'}} // Make sure we treat UCNs and UTF-8 as equivalent. diff --git a/clang/test/SemaCXX/cxx11-user-defined-literals-unused.cpp b/clang/test/SemaCXX/cxx11-user-defined-literals-unused.cpp index cd93ffbf21edf4..cf95ae7de98e94 100644 --- a/clang/test/SemaCXX/cxx11-user-defined-literals-unused.cpp +++ b/clang/test/SemaCXX/cxx11-user-defined-literals-unused.cpp @@ -1,8 +1,8 @@ // RUN: %clang_cc1 -std=c++11 -verify %s -Wunused namespace { -double operator"" _x(long double value) { return double(value); } -int operator"" _ii(long double value) { return int(value); } // expected-warning {{not needed and will not be emitted}} +double operator""_x(long double value) { return double(value); } +int operator""_ii(long double value) { return int(value); } // expected-warning {{not needed and will not be emitted}} } namespace rdar13589856 { diff --git a/clang/test/SemaCXX/cxx11-user-defined-literals.cpp b/clang/test/SemaCXX/cxx11-user-defined-literals.cpp index b5d4d9976c1372..bdf88ee01c3a12 100644 --- a/clang/test/SemaCXX/cxx11-user-defined-literals.cpp +++ b/clang/test/SemaCXX/cxx11-user-defined-literals.cpp @@ -6,18 +6,18 @@ enum class LitKind { CharStr, WideStr, Char16Str, Char32Str, Integer, Floating, Raw, Template }; -constexpr LitKind operator"" _kind(char p) { return LitKind::Char; } -constexpr LitKind operator"" _kind(wchar_t p) { return LitKind::WideChar; } -constexpr LitKind operator"" _kind(char16_t p) { return LitKind::Char16; } -constexpr LitKind operator"" _kind(char32_t p) { return LitKind::Char32; } -constexpr LitKind operator"" _kind(const char *p, size_t n) { return LitKind::CharStr; } -constexpr LitKind operator"" _kind(const wchar_t *p, size_t n) { return LitKind::WideStr; } -constexpr LitKind operator"" _kind(const char16_t *p, size_t n) { return LitKind::Char16Str; } -constexpr LitKind operator"" _kind(const char32_t *p, size_t n) { return LitKind::Char32Str; } -constexpr LitKind operator"" _kind(unsigned long long n) { return LitKind::Integer; } -constexpr LitKind operator"" _kind(long double n) { return LitKind::Floating; } -constexpr LitKind operator"" _kind2(const char *p) { return LitKind::Raw; } -template constexpr LitKind operator"" _kind3() { return LitKind::Template; } +constexpr LitKind operator""_kind(char p) { return LitKind::Char; } +constexpr LitKind operator""_kind(wchar_t p) { return LitKind::WideChar; } +constexpr LitKind operator""_kind(char16_t p) { return LitKind::Char16; } +constexpr LitKind operator""_kind(char32_t p) { return LitKind::Char32; } +constexpr LitKind operator""_kind(const char *p, size_t n) { return LitKind::CharStr; } +constexpr LitKind operator""_kind(const wchar_t *p, size_t n) { return LitKind::WideStr; } +constexpr LitKind operator""_kind(const char16_t *p, size_t n) { return LitKind::Char16Str; } +constexpr LitKind operator""_kind(const char32_t *p, size_t n) { return LitKind::Char32Str; } +constexpr LitKind operator""_kind(unsigned long long n) { return LitKind::Integer; } +constexpr LitKind operator""_kind(long double n) { return LitKind::Floating; } +constexpr LitKind operator""_kind2(const char *p) { return LitKind::Raw; } +template constexpr LitKind operator""_kind3() { return LitKind::Template; } static_assert('x'_kind == LitKind::Char, ""); static_assert(L'x'_kind == LitKind::WideChar, ""); @@ -41,7 +41,7 @@ static_assert(4e6_kind3 == LitKind::Template, ""); constexpr const char *fractional_digits_impl(const char *p) { return *p == '.' ? p + 1 : *p ? fractional_digits_impl(p + 1) : 0; } -constexpr const char *operator"" _fractional_digits(const char *p) { +constexpr const char *operator""_fractional_digits(const char *p) { return fractional_digits_impl(p) ?: p; } constexpr bool streq(const char *p, const char *q) { @@ -56,57 +56,57 @@ static_assert(streq(1e+97_fractional_digits, "1e+97"), ""); static_assert(streq(0377_fractional_digits, "0377"), ""); static_assert(streq(0377.5_fractional_digits, "5"), ""); -int operator"" _ambiguous(char); // expected-note {{candidate}} +int operator""_ambiguous(char); // expected-note {{candidate}} namespace N { - void *operator"" _ambiguous(char); // expected-note {{candidate}} + void *operator""_ambiguous(char); // expected-note {{candidate}} } using namespace N; int k = 'x'_ambiguous; // expected-error {{ambiguous}} -int operator"" _deleted(unsigned long long) = delete; // expected-note {{here}} +int operator""_deleted(unsigned long long) = delete; // expected-note {{here}} int m = 42_deleted; // expected-error {{attempt to use a deleted}} namespace Using { namespace M { - int operator"" _using(char); + int operator""_using(char); } int k1 = 'x'_using; // expected-error {{no matching literal operator for call to 'operator""_using'}} - using M::operator "" _using; + using M::operator ""_using; int k2 = 'x'_using; } namespace AmbiguousRawTemplate { - int operator"" _ambig1(const char *); // expected-note {{candidate}} - template int operator"" _ambig1(); // expected-note {{candidate}} + int operator""_ambig1(const char *); // expected-note {{candidate}} + template int operator""_ambig1(); // expected-note {{candidate}} int k1 = 123_ambig1; // expected-error {{call to 'operator""_ambig1' is ambiguous}} namespace Inner { - template int operator"" _ambig2(); // expected-note 3{{candidate}} + template int operator""_ambig2(); // expected-note 3{{candidate}} } - int operator"" _ambig2(const char *); // expected-note 3{{candidate}} - using Inner::operator"" _ambig2; + int operator""_ambig2(const char *); // expected-note 3{{candidate}} + using Inner::operator""_ambig2; int k2 = 123_ambig2; // expected-error {{call to 'operator""_ambig2' is ambiguous}} namespace N { - using Inner::operator"" _ambig2; + using Inner::operator""_ambig2; int k3 = 123_ambig2; // ok - using AmbiguousRawTemplate::operator"" _ambig2; + using AmbiguousRawTemplate::operator""_ambig2; int k4 = 123_ambig2; // expected-error {{ambiguous}} namespace M { - template int operator"" _ambig2(); + template int operator""_ambig2(); int k5 = 123_ambig2; // ok } - int operator"" _ambig2(unsigned long long); + int operator""_ambig2(unsigned long long); int k6 = 123_ambig2; // ok int k7 = 123._ambig2; // expected-error {{ambiguous}} @@ -121,7 +121,7 @@ template constexpr unsigned hash(unsigned a) { return hash(mash(a ^ mash(C))); } template struct constant { constexpr static T value = v; }; -template constexpr unsigned operator"" _hash() { +template constexpr unsigned operator""_hash() { return constant(0)>::value; } static_assert(0x1234_hash == 0x103eff5e, ""); @@ -129,7 +129,7 @@ static_assert(hash<'0', 'x', '1', '2', '3', '4'>(0) == 0x103eff5e, ""); // Functions and literal suffixes go in separate namespaces. namespace Namespace { - template int operator"" _x(); + template int operator""_x(); int k = _x(); // expected-error {{undeclared identifier '_x'}} int _y(unsigned long long); @@ -138,7 +138,7 @@ namespace Namespace { namespace PR14950 { template<...> // expected-error {{expected template parameter}} - int operator"" _b(); // expected-error {{no function template matches function template specialization}} + int operator""_b(); // expected-error {{no function template matches function template specialization}} int main() { return 0_b; } // expected-error {{no matching literal operator for call to 'operator""_b'}} } diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp index ae331055c52b2e..fef4674d178412 100644 --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -158,17 +158,17 @@ int i3 = f1(f1(f1(&f1, &f1), f1(&f1, &f1), f1(f1(&f1, &f1), &f1))); namespace user_defined_literal { -consteval int operator"" _test(unsigned long long i) { +consteval int operator""_test(unsigned long long i) { // expected-note@-1+ {{declared here}} return 0; } int i = 0_test; -auto ptr = &operator"" _test; +auto ptr = &operator""_test; // expected-error@-1 {{take address}} -consteval auto operator"" _test1(unsigned long long i) { +consteval auto operator""_test1(unsigned long long i) { return &f_eval; } diff --git a/clang/test/SemaCXX/cxx98-compat.cpp b/clang/test/SemaCXX/cxx98-compat.cpp index 3ce69d6908c5b2..28547d42c64902 100644 --- a/clang/test/SemaCXX/cxx98-compat.cpp +++ b/clang/test/SemaCXX/cxx98-compat.cpp @@ -84,7 +84,7 @@ struct DelayedDefaultArgumentParseInitList { } }; -int operator"" _hello(const char *); // expected-warning {{literal operators are incompatible with C++98}} +int operator""_hello(const char *); // expected-warning {{literal operators are incompatible with C++98}} enum EnumFixed : int { // expected-warning {{enumeration types with a fixed underlying type are incompatible with C++98}} }; diff --git a/clang/test/SemaCXX/literal-operators.cpp b/clang/test/SemaCXX/literal-operators.cpp index 067e151606202e..2a41e048914b78 100644 --- a/clang/test/SemaCXX/literal-operators.cpp +++ b/clang/test/SemaCXX/literal-operators.cpp @@ -3,46 +3,46 @@ #include struct tag { - void operator "" _tag_bad (const char *); // expected-error {{literal operator 'operator""_tag_bad' must be in a namespace or global scope}} - friend void operator "" _tag_good (const char *); + void operator ""_tag_bad (const char *); // expected-error {{literal operator 'operator""_tag_bad' must be in a namespace or global scope}} + friend void operator ""_tag_good (const char *); }; -namespace ns { void operator "" _ns_good (const char *); } +namespace ns { void operator ""_ns_good (const char *); } // Check extern "C++" declarations -extern "C++" void operator "" _extern_good (const char *); -extern "C++" { void operator "" _extern_good (const char *); } +extern "C++" void operator ""_extern_good (const char *); +extern "C++" { void operator ""_extern_good (const char *); } -void fn () { void operator "" _fn_good (const char *); } +void fn () { void operator ""_fn_good (const char *); } // One-param declarations (const char * was already checked) -void operator "" _good (char); -void operator "" _good (wchar_t); -void operator "" _good (char16_t); -void operator "" _good (char32_t); -void operator "" _good (unsigned long long); -void operator "" _good (long double); +void operator ""_good (char); +void operator ""_good (wchar_t); +void operator ""_good (char16_t); +void operator ""_good (char32_t); +void operator ""_good (unsigned long long); +void operator ""_good (long double); // Two-param declarations -void operator "" _good (const char *, size_t); -void operator "" _good (const wchar_t *, size_t); -void operator "" _good (const char16_t *, size_t); -void operator "" _good (const char32_t *, size_t); +void operator ""_good (const char *, size_t); +void operator ""_good (const wchar_t *, size_t); +void operator ""_good (const char16_t *, size_t); +void operator ""_good (const char32_t *, size_t); // Check typedef and array equivalences -void operator "" _good (const char[]); +void operator ""_good (const char[]); typedef const char c; -void operator "" _good (c*); +void operator ""_good (c*); // Check extra cv-qualifiers -void operator "" _cv_good (volatile const char *, const size_t); // expected-error {{invalid literal operator parameter type 'const volatile char *', did you mean 'const char *'?}} +void operator ""_cv_good (volatile const char *, const size_t); // expected-error {{invalid literal operator parameter type 'const volatile char *', did you mean 'const char *'?}} // Template declaration -template void operator "" _good (); +template void operator ""_good (); -template void operator "" _invalid(); // expected-error {{template parameter list for literal operator must be either 'char...' or 'typename T, T...'}} -template void operator "" _invalid(); // expected-error {{template parameter list for literal operator must be either 'char...' or 'typename T, T...'}} -template void operator "" _invalid(); // expected-error {{template parameter list for literal operator must be either 'char...' or 'typename T, T...'}} +template void operator ""_invalid(); // expected-error {{template parameter list for literal operator must be either 'char...' or 'typename T, T...'}} +template void operator ""_invalid(); // expected-error {{template parameter list for literal operator must be either 'char...' or 'typename T, T...'}} +template void operator ""_invalid(); // expected-error {{template parameter list for literal operator must be either 'char...' or 'typename T, T...'}} _Complex float operator""if(long double); // expected-warning {{reserved}} _Complex float test_if_1() { return 2.0f + 1.5if; }; diff --git a/clang/test/SemaCXX/no-warn-user-defined-literals-in-system-headers.cpp b/clang/test/SemaCXX/no-warn-user-defined-literals-in-system-headers.cpp index ee5b0c47b9ffcd..562d8cf654d187 100644 --- a/clang/test/SemaCXX/no-warn-user-defined-literals-in-system-headers.cpp +++ b/clang/test/SemaCXX/no-warn-user-defined-literals-in-system-headers.cpp @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wsystem-headers -isystem %S %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -isystem %S %s #include void operator "" bar(long double); // expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} +// expected-warning@-1{{identifier 'bar' preceded by whitespace in a literal operator declaration is deprecated}} diff --git a/clang/test/SemaCXX/reserved-identifier.cpp b/clang/test/SemaCXX/reserved-identifier.cpp index eaa5fe8330337e..a3e6d8ead61fd8 100644 --- a/clang/test/SemaCXX/reserved-identifier.cpp +++ b/clang/test/SemaCXX/reserved-identifier.cpp @@ -76,7 +76,8 @@ namespace { int _barbatruc; // no-warning } -long double operator"" _BarbeBleue(long double) // expected-warning {{identifier '_BarbeBleue' is reserved because it starts with '_' followed by a capital letter}} +long double operator"" _BarbeBleue(long double) // expected-warning {{identifier '_BarbeBleue' is reserved because it starts with '_' followed by a capital letter}}\ + // expected-warning {{identifier '_BarbeBleue' preceded by whitespace in a literal operator declaration is deprecated}} { return 0.; } @@ -86,10 +87,11 @@ long double operator""_SacreBleu(long double) // no-warning return 0.; } -long double sacrebleu = operator"" _SacreBleu(1.2); // expected-warning {{identifier '_SacreBleu' is reserved because it starts with '_' followed by a capital letter}} +long double sacrebleu = operator"" _SacreBleu(1.2); // expected-warning {{identifier '_SacreBleu' is reserved because it starts with '_' followed by a capital letter}} \ + // expected-warning {{identifier '_SacreBleu' preceded by whitespace in a literal operator declaration is deprecated}} long double sangbleu = operator""_SacreBleu(1.2); // no-warning -void operator"" _lowercase(unsigned long long); // no-warning +void operator"" _lowercase(unsigned long long); // expected-warning {{identifier '_lowercase' preceded by whitespace in a literal operator declaration is deprecated}} void operator""_lowercase(unsigned long long); // no-warning struct _BarbeRouge { // expected-warning {{identifier '_BarbeRouge' is reserved because it starts with '_' followed by a capital letter}} diff --git a/clang/test/SemaCXX/warn-xor-as-pow.cpp b/clang/test/SemaCXX/warn-xor-as-pow.cpp index 88719bd1a9d775..ade977f97e4366 100644 --- a/clang/test/SemaCXX/warn-xor-as-pow.cpp +++ b/clang/test/SemaCXX/warn-xor-as-pow.cpp @@ -19,10 +19,10 @@ #define flexor 7 #ifdef __cplusplus -constexpr long long operator"" _xor(unsigned long long v) { return v; } +constexpr long long operator""_xor(unsigned long long v) { return v; } -constexpr long long operator"" _0b(unsigned long long v) { return v; } -constexpr long long operator"" _0X(unsigned long long v) { return v; } +constexpr long long operator""_0b(unsigned long long v) { return v; } +constexpr long long operator""_0X(unsigned long long v) { return v; } #else #define xor ^ // iso646.h #endif From c45eda62adf3215f73bd56b672814883881b5531 Mon Sep 17 00:00:00 2001 From: erichkeane Date: Fri, 4 Oct 2024 07:32:17 -0700 Subject: [PATCH 2/3] Suppress diagnostic in the case where there is no leading underscore, which triggers other diagnostics --- clang/lib/Basic/IdentifierTable.cpp | 3 +++ clang/lib/Sema/SemaExprCXX.cpp | 9 ++++++++- clang/test/CXX/drs/cwg17xx.cpp | 3 --- clang/test/CXX/over/over.oper/over.literal/p8.cpp | 6 +++--- clang/test/Parser/cxx0x-literal-operators.cpp | 6 ++---- .../no-warn-user-defined-literals-in-system-headers.cpp | 1 - 6 files changed, 16 insertions(+), 12 deletions(-) diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp index c9c9d927a5902e..16151c94464f99 100644 --- a/clang/lib/Basic/IdentifierTable.cpp +++ b/clang/lib/Basic/IdentifierTable.cpp @@ -406,6 +406,9 @@ ReservedLiteralSuffixIdStatus IdentifierInfo::isReservedLiteralSuffixId() const { StringRef Name = getName(); + // Note: the diag::warn_deprecated_literal_operator_id diagnostic depends on + // this being the first check we do, so if this order changes, we have to fix + // that as well. if (Name[0] != '_') return ReservedLiteralSuffixIdStatus::NotStartsWithUnderscore; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 44ebfbaa043ce2..1e8e451242251c 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -508,7 +508,14 @@ bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS, Name.getSourceRange(), (StringRef("operator\"\"") + II->getName()).str()); - Diag(Loc, diag::warn_deprecated_literal_operator_id) << II << Hint; + // Only emit this diagnostic if we start with an underscore, else the + // diagnostic for C++11 requiring a space between the quotes and the + // identifier conflicts with this and gets confusing. The diagnostic stating + // this is a reserved name should force the underscore, which gets this + // back. + if (II->isReservedLiteralSuffixId() != + ReservedLiteralSuffixIdStatus::NotStartsWithUnderscore) + Diag(Loc, diag::warn_deprecated_literal_operator_id) << II << Hint; if (isReservedInAllContexts(Status)) Diag(Loc, diag::warn_reserved_extern_symbol) diff --git a/clang/test/CXX/drs/cwg17xx.cpp b/clang/test/CXX/drs/cwg17xx.cpp index 907240b0fc8b28..fb53a56923b104 100644 --- a/clang/test/CXX/drs/cwg17xx.cpp +++ b/clang/test/CXX/drs/cwg17xx.cpp @@ -203,9 +203,6 @@ namespace cwg1762 { // cwg1762: 14 float operator ""E(const char *); // since-cxx11-error@-1 {{invalid suffix on literal; C++11 requires a space between literal and identifier}} // since-cxx11-warning@-2 {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}} - // since-cxx11-warning@-3 {{identifier 'E' preceded by whitespace in a literal operator declaration is deprecated}} - // FIXME: We could probably do a better job reacting to the fixit here, the - // fact that we complain about the space we added is a little strange. #endif } diff --git a/clang/test/CXX/over/over.oper/over.literal/p8.cpp b/clang/test/CXX/over/over.oper/over.literal/p8.cpp index 9c1f6c73292abc..8aa31e1acd6e15 100644 --- a/clang/test/CXX/over/over.oper/over.literal/p8.cpp +++ b/clang/test/CXX/over/over.oper/over.literal/p8.cpp @@ -8,10 +8,10 @@ namespace std { void operator ""_km(long double); // ok string operator ""_i18n(const char*, std::size_t); // ok template int operator ""\u03C0(); // ok, UCN for lowercase pi // expected-warning {{reserved}} -float operator ""E(const char *); // expected-error {{invalid suffix on literal}} expected-warning {{reserved}} expected-warning{{whitespace}} -float operator " " B(const char *); // expected-error {{must be '""'}} expected-warning {{reserved}} expected-warning{{whitespace}} +float operator ""E(const char *); // expected-error {{invalid suffix on literal}} 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 {{template}} expected-warning{{whitespace}} +template int operator "" j(const char*); // expected-error {{template}} float operator ""_E(const char *); diff --git a/clang/test/Parser/cxx0x-literal-operators.cpp b/clang/test/Parser/cxx0x-literal-operators.cpp index 76c776a33473a6..1881fcb7f09904 100644 --- a/clang/test/Parser/cxx0x-literal-operators.cpp +++ b/clang/test/Parser/cxx0x-literal-operators.cpp @@ -3,8 +3,6 @@ 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 suffixes not starting with '_' are reserved}} \ - expected-warning{{identifier 'foo' preceded by whitespace in a literal operator declaration is deprecated}} + 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}} \ - expected-warning{{identifier 'tester' preceded by whitespace in a literal operator declaration is deprecated}} + expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} diff --git a/clang/test/SemaCXX/no-warn-user-defined-literals-in-system-headers.cpp b/clang/test/SemaCXX/no-warn-user-defined-literals-in-system-headers.cpp index 562d8cf654d187..61b08954c40b58 100644 --- a/clang/test/SemaCXX/no-warn-user-defined-literals-in-system-headers.cpp +++ b/clang/test/SemaCXX/no-warn-user-defined-literals-in-system-headers.cpp @@ -3,4 +3,3 @@ #include void operator "" bar(long double); // expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} -// expected-warning@-1{{identifier 'bar' preceded by whitespace in a literal operator declaration is deprecated}} From f9a9f81c8fb3ee2018103c4f4d7f1fc94bf1dedc Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Fri, 4 Oct 2024 09:23:53 -0700 Subject: [PATCH 3/3] Update clang/docs/ReleaseNotes.rst Co-authored-by: Vlad Serebrennikov --- clang/docs/ReleaseNotes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index edd1f1d2302d58..14fa94139387c4 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -104,7 +104,7 @@ C++ Specific Potentially Breaking Changes result is that anyone who is compiling with ``-Werror`` should see this diagnostic. To fix this diagnostic, simply removing the space character from between the ``operator""`` and the user defined literal name will make the - source no longer deprecated. This is consistent with CWG2521. + source no longer deprecated. This is consistent with `CWG2521 _`. .. code-block:: c++