Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -136,6 +136,22 @@ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Implemented `DR2397 `_ which allows ``auto`` specifier for pointers and reference to arrays. +- Implemented `CWG2521 `_ which reserves using ``__`` in user defined literal suffixes + for C++ implementations, and deprecates literal operator function declarations using an identifier. + Taught ``-Wuser-defined-literals`` for the former, on by default, and added ``-Wdeprecated-literal-operator`` + for the latter, off by default. + + .. code-block:: c++ + + // What follows is warned by -Wuser-defined-literals + // albeit "ill-formed, no diagnostic required". + // Its behavior is undefined, [reserved.names.general]p2. + string operator ""__i18n(const char*, std::size_t); + + // Let's assume this is not in the global namespace. + // -Wdeprecated-literal-operator whines about extra spaces. + string operator "" _i18n(const char*, std::size_t); + // ^ an extra space C Language Changes ------------------ Index: clang/include/clang/Basic/DiagnosticGroups.td =================================================================== --- clang/include/clang/Basic/DiagnosticGroups.td +++ clang/include/clang/Basic/DiagnosticGroups.td @@ -183,6 +183,7 @@ def DeprecatedCopyWithUserProvidedDtor : DiagGroup<"deprecated-copy-with-user-provided-dtor">; def DeprecatedCopy : DiagGroup<"deprecated-copy", [DeprecatedCopyWithUserProvidedCopy]>; def DeprecatedCopyWithDtor : DiagGroup<"deprecated-copy-with-dtor", [DeprecatedCopyWithUserProvidedDtor]>; +def DeprecatedLiteralOperator : DiagGroup<"deprecated-literal-operator">; // For compatibility with GCC. def : DiagGroup<"deprecated-copy-dtor", [DeprecatedCopyWithDtor]>; def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">; @@ -219,6 +220,7 @@ DeprecatedEnumFloatConversion, DeprecatedBuiltins, DeprecatedIncrementBool, + DeprecatedLiteralOperator, DeprecatedPragma, DeprecatedRegister, DeprecatedThisCapture, Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -406,6 +406,9 @@ "it starts with '_' followed by a capital letter|" "it contains '__'}1">, InGroup, DefaultIgnore; +def warn_deprecated_literal_operator_id: Warning< + "identifier '%0' preceded by space(s) in the literal operator declaration " + "is deprecated">, InGroup, DefaultIgnore; def warn_reserved_module_name : Warning< "%0 is a reserved name for a module">, InGroup; @@ -9263,7 +9266,7 @@ "string literal operator templates are a GNU extension">, InGroup; def warn_user_literal_reserved : Warning< - "user-defined literal suffixes not starting with '_' are reserved" + "user-defined literal suffixes containing '__' or not starting with '_' are reserved" "%select{; no literal will invoke this operator|}0">, InGroup; Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -16445,11 +16445,13 @@ StringRef LiteralName = FnDecl->getDeclName().getCXXLiteralIdentifier()->getName(); - if (LiteralName[0] != '_' && + if ((LiteralName[0] != '_' || LiteralName.contains("__")) && !getSourceManager().isInSystemHeader(FnDecl->getLocation())) { - // C++11 [usrlit.suffix]p1: - // Literal suffix identifiers that do not start with an underscore - // are reserved for future standardization. + // C++23 [usrlit.suffix]p1: + // Literal suffix identifiers that do not start with an underscore are + // reserved for future standardization. Literal suffix identifiers that + // contain a double underscore __ are reserved for use by C++ + // implementations. Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved) << StringLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName); } Index: clang/lib/Sema/SemaExprCXX.cpp =================================================================== --- clang/lib/Sema/SemaExprCXX.cpp +++ clang/lib/Sema/SemaExprCXX.cpp @@ -501,10 +501,16 @@ IdentifierInfo *II = Name.Identifier; ReservedIdentifierStatus Status = II->isReserved(PP.getLangOpts()); SourceLocation Loc = Name.getEndLoc(); - if (isReservedInAllContexts(Status) && - !PP.getSourceManager().isInSystemHeader(Loc)) { - Diag(Loc, diag::warn_reserved_extern_symbol) - << II << static_cast(Status) + if (!PP.getSourceManager().isInSystemHeader(Loc)) { + if (isReservedInAllContexts(Status)) { + Diag(Loc, diag::warn_reserved_extern_symbol) + << II << static_cast(Status) + << FixItHint::CreateReplacement( + Name.getSourceRange(), + (StringRef("operator\"\"") + II->getName()).str()); + } + Diag(Loc, diag::warn_deprecated_literal_operator_id) + << II->getName() << FixItHint::CreateReplacement( Name.getSourceRange(), (StringRef("operator\"\"") + II->getName()).str()); Index: clang/test/CXX/drs/dr17xx.cpp =================================================================== --- clang/test/CXX/drs/dr17xx.cpp +++ clang/test/CXX/drs/dr17xx.cpp @@ -127,7 +127,7 @@ #if __cplusplus >= 201103L float operator ""_E(const char *); // expected-error@+2 {{invalid suffix on literal; C++11 requires a space between literal and identifier}} - // expected-warning@+1 {{user-defined literal suffixes not starting with '_' are reserved; no literal will invoke this operator}} + // expected-warning@+1 {{user-defined literal suffixes containing '__' or not starting with '_' are reserved; no literal will invoke this operator}} float operator ""E(const char *); #endif } Index: clang/test/CXX/drs/dr25xx.cpp =================================================================== --- clang/test/CXX/drs/dr25xx.cpp +++ clang/test/CXX/drs/dr25xx.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify -Wdeprecated-literal-operator +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify -Wdeprecated namespace dr2516 { // dr2516: yes // NB: reusing 1482 test @@ -108,3 +109,20 @@ // expected-note@-2{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}} } + +namespace dr2521 { // dr2521: 17 + +// expected-warning@+2{{identifier '_π___' preceded by space(s) in the literal operator declaration is deprecated}} +// expected-warning@+1{{user-defined literal suffixes containing '__' or not starting with '_' are reserved}} +decltype(sizeof 0) operator "" _\u{3C0}___(long double); + +template consteval auto +operator"" _div() { return (... / (Chars - '0')); } +// expected-warning@-1{{identifier '_div' preceded by space(s) in the literal operator declaration is deprecated}} + +} // namespace dr2521 + +// expected-warning@+1{{identifier '_π___' preceded by space(s) in the literal operator declaration is deprecated}} +using dr2521::operator"" _\u{3C0}___, dr2521::operator""_div; + +[[maybe_unused]] constexpr auto div = 841_div; Index: clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp =================================================================== --- clang/test/CXX/lex/lex.literal/lex.ext/p1.cpp +++ clang/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 suffixes not starting with '_' are reserved}} +void operator "" p31(long double); // expected-warning{{user-defined literal suffixes containing '__' or not starting with '_' are reserved}} void operator "" _p31(long double); -long double operator "" pi(long double); // expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} +long double operator "" pi(long double); // expected-warning{{user-defined literal suffixes containing '__' or not starting with '_' are reserved}} float hexfloat = 0x1p31; // allow hexfloats Index: clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp =================================================================== --- clang/test/CXX/lex/lex.literal/lex.ext/p10.cpp +++ clang/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 {{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}} +void operator "" wibble(const char *); // expected-warning {{user-defined literal suffixes containing '__' or not starting with '_' are reserved; no literal will invoke this operator}} +void operator "" wibble(const char *, size_t); // expected-warning {{user-defined literal suffixes containing '__' or not starting with '_' are reserved; no literal will invoke this operator}} template void f() { Index: clang/test/Parser/cxx0x-literal-operators.cpp =================================================================== --- clang/test/Parser/cxx0x-literal-operators.cpp +++ clang/test/Parser/cxx0x-literal-operators.cpp @@ -3,6 +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{{user-defined literal suffixes containing '__' or not starting with '_' are reserved}} void operator "" tester (const char *); // \ - expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} + expected-warning{{user-defined literal suffixes containing '__' or not starting with '_' are reserved}} Index: clang/test/SemaCXX/no-warn-user-defined-literals-in-system-headers.cpp =================================================================== --- clang/test/SemaCXX/no-warn-user-defined-literals-in-system-headers.cpp +++ clang/test/SemaCXX/no-warn-user-defined-literals-in-system-headers.cpp @@ -2,4 +2,4 @@ #include -void operator "" bar(long double); // expected-warning{{user-defined literal suffixes not starting with '_' are reserved}} +void operator "" bar(long double); // expected-warning{{user-defined literal suffixes containing '__' or not starting with '_' are reserved}} Index: clang/www/cxx_dr_status.html =================================================================== --- clang/www/cxx_dr_status.html +++ clang/www/cxx_dr_status.html @@ -14933,7 +14933,7 @@ 2521 DR User-defined literals and reserved identifiers - Unknown + Clang 17 2522