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 <corentinja...@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@-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@-2 {{expected string literal for diagnostic message in static_assert}} +#endif +// cxx-error@-4 {{use of undeclared identifier 'invalid'}} +// cxx-warning@-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@-1 {{a type specifier is required for all declarations}} +// since-cxx11-warning@-2 {{'static_assert' declarations are incompatible with C++98}} +// since-cxx11-error@-3 {{static assertion failed: a}} + +#if __cplusplus >= 201103L +static_assert(false); +// since-cxx11-warning@-1 {{'static_assert' declarations are incompatible with C++98}} +// precxx17-warning@-2 {{'static_assert' with no message is a C++17 extension}} +// since-cxx17-warning@-3 {{'static_assert' with no message is incompatible with C++ standards before C++17}} +// since-cxx11-error@-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@-1 {{'static_assert' declarations are incompatible with C++98}} +// precxx26-warning@-2 {{'static_assert' with a user-generated message is a C++26 extension}} +// since-cxx26-warning@-3 {{'static_assert' with a user-generated message is incompatible with C++ standards before C++26}} +// since-cxx11-error@-4 {{static assertion failed: b}} +#endif _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits