rZhBoYao updated this revision to Diff 538678.
rZhBoYao edited the summary of this revision.
rZhBoYao added a comment.
Defaults to on for C++23 only. Enable for all the language modes in another
patch.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D152632/new/
https://reviews.llvm.org/D152632
Files:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticGroups.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Basic/IdentifierTable.h
clang/lib/Basic/IdentifierTable.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/test/CXX/drs/dr25xx.cpp
clang/www/cxx_dr_status.html
Index: clang/www/cxx_dr_status.html
===================================================================
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -14933,7 +14933,7 @@
<td><a href="https://cplusplus.github.io/CWG/issues/2521.html">2521</a></td>
<td>DR</td>
<td>User-defined literals and reserved identifiers</td>
- <td class="none" align="center">Unknown</td>
+ <td class="unreleased" align="center">Clang 17</td>
</tr>
<tr class="open" id="2522">
<td><a href="https://cplusplus.github.io/CWG/issues/2522.html">2522</a></td>
Index: clang/test/CXX/drs/dr25xx.cpp
===================================================================
--- clang/test/CXX/drs/dr25xx.cpp
+++ clang/test/CXX/drs/dr25xx.cpp
@@ -1,4 +1,14 @@
-// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify
+// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
+
+#if __cplusplus < 201103L
+// expected-no-diagnostics
+#endif
namespace dr2516 { // dr2516: yes
// NB: reusing 1482 test
@@ -13,9 +23,13 @@
namespace dr2518 { // dr2518: 17
+#if __cplusplus >= 201103L
template <class T>
void f(T t) {
if constexpr (sizeof(T) != sizeof(int)) {
+#if __cplusplus < 201703L
+// expected-error@-2 {{constexpr if is a C++17 extension}}
+#endif
static_assert(false, "must be int-sized"); // expected-error {{must be int-size}}
}
}
@@ -28,6 +42,9 @@
template <typename Ty>
struct S {
static_assert(false); // expected-error {{static assertion failed}}
+#if __cplusplus < 201703L
+// expected-error@-2 {{'static_assert' with no message is a C++17 extension}}
+#endif
};
template <>
@@ -41,11 +58,28 @@
S<float> s2;
S<double> s3; // expected-note {{in instantiation of template class 'dr2518::S<double>' requested here}}
}
+#endif
}
+namespace dr2521 { // dr2521: 17
+#if __cplusplus >= 202302L
+long double operator"" _\u03C0___(long double);
+// expected-warning@-1 {{identifier '_Ï___' preceded by space(s) in the literal operator declaration is deprecated}}
+// expected-warning@-2 {{user-defined literal suffixes containing '__' are reserved}}
+
+template <char... Chars> decltype(sizeof 0)
+operator"" _div();
+// expected-warning@-1 {{identifier '_div' preceded by space(s) in the literal operator declaration is deprecated}}
+
+using ::dr2521::operator"" _\u03C0___;
+using ::dr2521::operator""_div;
+// expected-warning@-2 {{identifier '_Ï___' preceded by space(s) in the literal operator declaration is deprecated}}
+#endif
+} // namespace dr2521
namespace dr2565 { // dr2565: 16 open
+#if __cplusplus >= 202002L
template<typename T>
concept C = requires (typename T::type x) {
x + 1;
@@ -107,4 +141,5 @@
// expected-error@-1{{static assertion failed}}
// expected-note@-2{{because substituted constraint expression is ill-formed: constraint depends on a previously diagnosed expression}}
+#endif
}
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -502,13 +502,17 @@
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<int>(Status)
- << FixItHint::CreateReplacement(
- Name.getSourceRange(),
- (StringRef("operator\"\"") + II->getName()).str());
+ 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<int>(Status) << Hint;
+ } else if (LangOpts.CPlusPlus23) {
+ Diag(Loc, diag::warn_deprecated_literal_operator_id)
+ << II->getName() << Hint;
+ }
}
}
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -16447,15 +16447,18 @@
}
}
- StringRef LiteralName
- = FnDecl->getDeclName().getCXXLiteralIdentifier()->getName();
- if (LiteralName[0] != '_' &&
+ auto *II = FnDecl->getDeclName().getCXXLiteralIdentifier();
+ auto Status = II->isReservedLiteralSuffixId();
+ if (Status != ReservedLiteralSuffixIdStatus::NotReserved &&
!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);
+ << static_cast<int>(Status)
+ << StringLiteralParser::isValidUDSuffix(getLangOpts(), II->getName());
}
return false;
Index: clang/lib/Basic/IdentifierTable.cpp
===================================================================
--- clang/lib/Basic/IdentifierTable.cpp
+++ clang/lib/Basic/IdentifierTable.cpp
@@ -397,6 +397,19 @@
return ReservedIdentifierStatus::NotReserved;
}
+ReservedLiteralSuffixIdStatus
+IdentifierInfo::isReservedLiteralSuffixId() const {
+ StringRef Name = getName();
+
+ if (Name[0] != '_')
+ return ReservedLiteralSuffixIdStatus::NotStartsWithUnderscore;
+
+ if (Name.contains("__"))
+ return ReservedLiteralSuffixIdStatus::ContainsDoubleUnderscore;
+
+ return ReservedLiteralSuffixIdStatus::NotReserved;
+}
+
StringRef IdentifierInfo::deuglifiedName() const {
StringRef Name = getName();
if (Name.size() >= 2 && Name.front() == '_' &&
Index: clang/include/clang/Basic/IdentifierTable.h
===================================================================
--- clang/include/clang/Basic/IdentifierTable.h
+++ clang/include/clang/Basic/IdentifierTable.h
@@ -50,6 +50,12 @@
ContainsDoubleUnderscore,
};
+enum class ReservedLiteralSuffixIdStatus {
+ NotReserved = 0,
+ NotStartsWithUnderscore,
+ ContainsDoubleUnderscore,
+};
+
/// Determine whether an identifier is reserved for use as a name at global
/// scope. Such identifiers might be implementation-specific global functions
/// or variables.
@@ -491,6 +497,10 @@
/// 7.1.3, C++ [lib.global.names]).
ReservedIdentifierStatus isReserved(const LangOptions &LangOpts) const;
+ /// Determine whether \p this is a name reserved for future standardization or
+ /// the implementation (C++ [usrlit.suffix]).
+ ReservedLiteralSuffixIdStatus isReservedLiteralSuffixId() const;
+
/// If the identifier is an "uglified" reserved name, return a cleaned form.
/// e.g. _Foo => Foo. Otherwise, just returns the name.
StringRef deuglifiedName() const;
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<ReservedIdentifier>, DefaultIgnore;
+def warn_deprecated_literal_operator_id: Warning<
+ "identifier '%0' preceded by space(s) in the literal operator declaration "
+ "is deprecated">, InGroup<DeprecatedLiteralOperator>;
def warn_reserved_module_name : Warning<
"%0 is a reserved name for a module">, InGroup<ReservedModuleIdentifier>;
@@ -9261,8 +9264,8 @@
"string literal operator templates are a GNU extension">,
InGroup<GNUStringLiteralOperatorTemplate>;
def warn_user_literal_reserved : Warning<
- "user-defined literal suffixes not starting with '_' are reserved"
- "%select{; no literal will invoke this operator|}0">,
+ "user-defined literal suffixes %select{<ERROR>|not starting with '_'|containing '__'}0 are reserved"
+ "%select{; no literal will invoke this operator|}1">,
InGroup<UserDefinedLiterals>;
// C++ conversion functions
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,
@@ -862,7 +864,7 @@
def ReservedModuleIdentifier : DiagGroup<"reserved-module-identifier">;
def ReservedIdentifier : DiagGroup<"reserved-identifier",
- [ReservedIdAsMacro, ReservedModuleIdentifier]>;
+ [ReservedIdAsMacro, ReservedModuleIdentifier, UserDefinedLiterals]>;
// Unreachable code warning groups.
//
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -142,6 +142,22 @@
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Implemented `DR2397 <https://wg21.link/CWG2397>`_ which allows ``auto`` specifier for pointers
and reference to arrays.
+- Implemented `CWG2521 <https://wg21.link/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 for C++23 language mode,
+ 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
------------------
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits