[clang] be427df - [Clang][Parser] Accept P2741R3 (static_assert with user-generated message) in C++11 as an extension (#102044)

via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 5 08:38:11 PDT 2024


Author: Mital Ashok
Date: 2024-09-05T17:38:08+02:00
New Revision: be427dfb9ea6689947253d737708dc3645e179dc

URL: https://github.com/llvm/llvm-project/commit/be427dfb9ea6689947253d737708dc3645e179dc
DIFF: https://github.com/llvm/llvm-project/commit/be427dfb9ea6689947253d737708dc3645e179dc.diff

LOG: [Clang][Parser] Accept P2741R3 (static_assert with user-generated message) in C++11 as an extension (#102044)

Added a new `-Wpre-c++26-compat` warning for when this feature is used
in C++26 and a `-Wc++26-extensions` warning for when this is used in
C++11 through C++23.

---------

Co-authored-by: cor3ntin <corentinjabot at gmail.com>

Added: 
    clang/test/SemaCXX/static-assert-ext.cpp

Modified: 
    clang/docs/LanguageExtensions.rst
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticParseKinds.td
    clang/lib/Frontend/InitPreprocessor.cpp
    clang/lib/Parse/ParseDeclCXX.cpp
    clang/test/CXX/drs/cwg27xx.cpp
    clang/test/Lexer/cxx-features.cpp
    clang/test/Parser/cxx11-user-defined-literals.cpp
    clang/test/Sema/static-assert.c

Removed: 
    


################################################################################
diff  --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 62903fc3744cad..c08697282cbfe8 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -1483,6 +1483,7 @@ Generic lambda expressions                   __cpp_generic_lambdas            C+
 variable templates                           __cpp_variable_templates         C++14         C++03
 Binary literals                              __cpp_binary_literals            C++14         C++03
 Relaxed constexpr                            __cpp_constexpr                  C++14         C++11
+Static assert with no message                __cpp_static_assert >= 201411L   C++17         C++11
 Pack expansion in generalized lambda-capture __cpp_init_captures              C++17         C++03
 ``if constexpr``                             __cpp_if_constexpr               C++17         C++11
 fold expressions                             __cpp_fold_expressions           C++17         C++03
@@ -1503,6 +1504,7 @@ Conditional ``explicit``                     __cpp_conditional_explicit       C+
 ``static operator()``                        __cpp_static_call_operator       C++23         C++03
 Attributes on Lambda-Expressions                                              C++23         C++11
 Attributes on Structured Bindings            __cpp_structured_bindings        C++26         C++03
+Static assert with user-generated message    __cpp_static_assert >= 202306L   C++26         C++11
 Pack Indexing                                __cpp_pack_indexing              C++26         C++03
 ``= delete ("should have a reason");``       __cpp_deleted_function           C++26         C++03
 Variadic Friends                             __cpp_variadic_friend            C++26         C++03

diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ab3c3e6049f602..ebd0b7371e1bed 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -109,6 +109,9 @@ C++ Language Changes
   constant expression. Supports the `V.xyzw` syntax and other tidbits
   as seen in OpenCL. Selecting multiple elements is left as a future work.
 
+- Accept C++26 user-defined ``static_assert`` messages in C++11 as an extension.
+
+
 C++2c Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
 

diff  --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 0b8ab4bf092509..0aa2c4a70849a8 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -470,6 +470,12 @@ def warn_c17_compat_static_assert_no_message : Warning<
   "'_Static_assert' with no message is incompatible with C standards before "
   "C23">,
   DefaultIgnore, InGroup<CPre23Compat>;
+def ext_cxx_static_assert_user_generated_message : ExtWarn<
+  "'static_assert' with a user-generated message is a C++26 extension">,
+  InGroup<CXX26>;
+def warn_cxx20_compat_static_assert_user_generated_message : Warning<
+  "'static_assert' with a user-generated message is incompatible with "
+  "C++ standards before C++26">, DefaultIgnore, InGroup<CXXPre26Compat>;
 def err_function_definition_not_allowed : Error<
   "function definition is not allowed here">;
 def err_expected_end_of_enumerator : Error<

diff  --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index 61260a3379828d..9a0fdb175ff29e 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -671,10 +671,9 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
                         LangOpts.CPlusPlus23   ? "202211L"
                         : LangOpts.CPlusPlus17 ? "201603L"
                                                : "200907");
-    Builder.defineMacro("__cpp_static_assert", LangOpts.CPlusPlus26 ? "202306L"
-                                               : LangOpts.CPlusPlus17
-                                                   ? "201411L"
-                                                   : "200410");
+    // C++17 / C++26 static_assert supported as an extension in earlier language
+    // modes, so we use the C++26 value.
+    Builder.defineMacro("__cpp_static_assert", "202306L");
     Builder.defineMacro("__cpp_decltype", "200707L");
     Builder.defineMacro("__cpp_attributes", "200809L");
     Builder.defineMacro("__cpp_rvalue_references", "200610L");

diff  --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 7ca27d00c0bcbf..6370da1fab0042 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1076,7 +1076,7 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd) {
     }
 
     bool ParseAsExpression = false;
-    if (getLangOpts().CPlusPlus26) {
+    if (getLangOpts().CPlusPlus11) {
       for (unsigned I = 0;; ++I) {
         const Token &T = GetLookAheadToken(I);
         if (T.is(tok::r_paren))
@@ -1088,9 +1088,13 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd) {
       }
     }
 
-    if (ParseAsExpression)
+    if (ParseAsExpression) {
+      Diag(Tok,
+           getLangOpts().CPlusPlus26
+               ? diag::warn_cxx20_compat_static_assert_user_generated_message
+               : diag::ext_cxx_static_assert_user_generated_message);
       AssertMessage = ParseConstantExpressionInExprEvalContext();
-    else if (tokenIsLikeStringLiteral(Tok, getLangOpts()))
+    } else if (tokenIsLikeStringLiteral(Tok, getLangOpts()))
       AssertMessage = ParseUnevaluatedStringLiteralExpression();
     else {
       Diag(Tok, diag::err_expected_string_literal)

diff  --git a/clang/test/CXX/drs/cwg27xx.cpp b/clang/test/CXX/drs/cwg27xx.cpp
index b3867696c615b8..2b57dbc60aed70 100644
--- a/clang/test/CXX/drs/cwg27xx.cpp
+++ b/clang/test/CXX/drs/cwg27xx.cpp
@@ -178,7 +178,7 @@ void test() {
 }
 
 namespace cwg2798 { // cwg2798: 17
-#if __cpp_static_assert >= 202306
+#if __cplusplus > 202302L
 struct string {
   constexpr string() {
     data_ = new char[6]();

diff  --git a/clang/test/Lexer/cxx-features.cpp b/clang/test/Lexer/cxx-features.cpp
index 4a06d29ae9dbc6..5b88e00b715080 100644
--- a/clang/test/Lexer/cxx-features.cpp
+++ b/clang/test/Lexer/cxx-features.cpp
@@ -325,7 +325,7 @@
 #error "wrong value for __cpp_range_based_for"
 #endif
 
-#if check(static_assert, 0, 200410, 200410, 201411, 201411, 201411, 202306)
+#if check(static_assert, 0, 202306, 202306, 202306, 202306, 202306, 202306)
 #error "wrong value for __cpp_static_assert"
 #endif
 

diff  --git a/clang/test/Parser/cxx11-user-defined-literals.cpp b/clang/test/Parser/cxx11-user-defined-literals.cpp
index 1a7e7805882299..cdd06729efc39a 100644
--- a/clang/test/Parser/cxx11-user-defined-literals.cpp
+++ b/clang/test/Parser/cxx11-user-defined-literals.cpp
@@ -21,7 +21,8 @@ int f() {
   asm("mov %eax, %rdx"_foo); // expected-error {{user-defined suffix cannot be used here}}
 }
 
-static_assert(true, "foo"_bar); // expected-error {{user-defined suffix cannot be used here}}
+static_assert(true, "foo"_bar); // expected-error {{no matching literal operator for call to 'operator""_bar'}}
+// expected-warning at -1 {{'static_assert' with a user-generated message is a C++26 extension}}
 
 int cake() __attribute__((availability(macosx, unavailable, message = "is a lie"_x))); // expected-error {{user-defined suffix cannot be used here}}
 

diff  --git a/clang/test/Sema/static-assert.c b/clang/test/Sema/static-assert.c
index 4e9e6b7ee558bd..d603bc19bb824b 100644
--- a/clang/test/Sema/static-assert.c
+++ b/clang/test/Sema/static-assert.c
@@ -25,8 +25,12 @@ void foo(void) {
 #endif
 }
 
-_Static_assert(1, invalid); // expected-error {{expected string literal for diagnostic message in static_assert}} \
-                            // ext-warning {{'_Static_assert' is a C11 extension}}
+_Static_assert(1, invalid); // ext-warning {{'_Static_assert' is a C11 extension}}
+#ifndef __cplusplus
+// expected-error at -2 {{expected string literal for diagnostic message in static_assert}}
+#endif
+// cxx-error at -4 {{use of undeclared identifier 'invalid'}}
+// cxx-warning at -5 {{'static_assert' with a user-generated message is a C++26 extension}}
 
 struct A {
   int a;

diff  --git a/clang/test/SemaCXX/static-assert-ext.cpp b/clang/test/SemaCXX/static-assert-ext.cpp
new file mode 100644
index 00000000000000..05f7a0e96974aa
--- /dev/null
+++ b/clang/test/SemaCXX/static-assert-ext.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -std=c++98 -fsyntax-only -pedantic %s -verify=precxx11,precxx17,precxx26
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -pedantic %s -verify=since-cxx11,precxx17,precxx26 -Wc++98-compat
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -pedantic %s -verify=since-cxx11,since-cxx17,precxx26 -Wc++98-compat -Wpre-c++17-compat
+// RUN: %clang_cc1 -std=c++26 -fsyntax-only -pedantic %s -verify=since-cxx11,since-cxx17,since-cxx26 -Wc++98-compat -Wpre-c++17-compat -Wpre-c++26-compat
+
+static_assert(false, "a");
+// precxx11-error at -1 {{a type specifier is required for all declarations}}
+// since-cxx11-warning at -2 {{'static_assert' declarations are incompatible with C++98}}
+// since-cxx11-error at -3 {{static assertion failed: a}}
+
+#if __cplusplus >= 201103L
+static_assert(false);
+// since-cxx11-warning at -1 {{'static_assert' declarations are incompatible with C++98}}
+// precxx17-warning at -2 {{'static_assert' with no message is a C++17 extension}}
+// since-cxx17-warning at -3 {{'static_assert' with no message is incompatible with C++ standards before C++17}}
+// since-cxx11-error at -4 {{static assertion failed}}
+
+struct X {
+    static constexpr int size() { return 1; } // since-cxx11-warning {{'constexpr'}}
+    static constexpr const char* data() { return "b"; } // since-cxx11-warning {{'constexpr'}}
+};
+
+static_assert(false, X());
+// since-cxx11-warning at -1 {{'static_assert' declarations are incompatible with C++98}}
+// precxx26-warning at -2 {{'static_assert' with a user-generated message is a C++26 extension}}
+// since-cxx26-warning at -3 {{'static_assert' with a user-generated message is incompatible with C++ standards before C++26}}
+// since-cxx11-error at -4 {{static assertion failed: b}}
+#endif


        


More information about the cfe-commits mailing list