Skip to content

Commit be427df

Browse files
MitalAshokcor3ntin
andauthored
[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 <[email protected]>
1 parent 0593b95 commit be427df

File tree

10 files changed

+59
-12
lines changed

10 files changed

+59
-12
lines changed

clang/docs/LanguageExtensions.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,7 @@ Generic lambda expressions __cpp_generic_lambdas C+
14831483
variable templates __cpp_variable_templates C++14 C++03
14841484
Binary literals __cpp_binary_literals C++14 C++03
14851485
Relaxed constexpr __cpp_constexpr C++14 C++11
1486+
Static assert with no message __cpp_static_assert >= 201411L C++17 C++11
14861487
Pack expansion in generalized lambda-capture __cpp_init_captures C++17 C++03
14871488
``if constexpr`` __cpp_if_constexpr C++17 C++11
14881489
fold expressions __cpp_fold_expressions C++17 C++03
@@ -1503,6 +1504,7 @@ Conditional ``explicit`` __cpp_conditional_explicit C+
15031504
``static operator()`` __cpp_static_call_operator C++23 C++03
15041505
Attributes on Lambda-Expressions C++23 C++11
15051506
Attributes on Structured Bindings __cpp_structured_bindings C++26 C++03
1507+
Static assert with user-generated message __cpp_static_assert >= 202306L C++26 C++11
15061508
Pack Indexing __cpp_pack_indexing C++26 C++03
15071509
``= delete ("should have a reason");`` __cpp_deleted_function C++26 C++03
15081510
Variadic Friends __cpp_variadic_friend C++26 C++03

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ C++ Language Changes
109109
constant expression. Supports the `V.xyzw` syntax and other tidbits
110110
as seen in OpenCL. Selecting multiple elements is left as a future work.
111111

112+
- Accept C++26 user-defined ``static_assert`` messages in C++11 as an extension.
113+
114+
112115
C++2c Feature Support
113116
^^^^^^^^^^^^^^^^^^^^^
114117

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,12 @@ def warn_c17_compat_static_assert_no_message : Warning<
470470
"'_Static_assert' with no message is incompatible with C standards before "
471471
"C23">,
472472
DefaultIgnore, InGroup<CPre23Compat>;
473+
def ext_cxx_static_assert_user_generated_message : ExtWarn<
474+
"'static_assert' with a user-generated message is a C++26 extension">,
475+
InGroup<CXX26>;
476+
def warn_cxx20_compat_static_assert_user_generated_message : Warning<
477+
"'static_assert' with a user-generated message is incompatible with "
478+
"C++ standards before C++26">, DefaultIgnore, InGroup<CXXPre26Compat>;
473479
def err_function_definition_not_allowed : Error<
474480
"function definition is not allowed here">;
475481
def err_expected_end_of_enumerator : Error<

clang/lib/Frontend/InitPreprocessor.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -671,10 +671,9 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
671671
LangOpts.CPlusPlus23 ? "202211L"
672672
: LangOpts.CPlusPlus17 ? "201603L"
673673
: "200907");
674-
Builder.defineMacro("__cpp_static_assert", LangOpts.CPlusPlus26 ? "202306L"
675-
: LangOpts.CPlusPlus17
676-
? "201411L"
677-
: "200410");
674+
// C++17 / C++26 static_assert supported as an extension in earlier language
675+
// modes, so we use the C++26 value.
676+
Builder.defineMacro("__cpp_static_assert", "202306L");
678677
Builder.defineMacro("__cpp_decltype", "200707L");
679678
Builder.defineMacro("__cpp_attributes", "200809L");
680679
Builder.defineMacro("__cpp_rvalue_references", "200610L");

clang/lib/Parse/ParseDeclCXX.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,7 +1076,7 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd) {
10761076
}
10771077

10781078
bool ParseAsExpression = false;
1079-
if (getLangOpts().CPlusPlus26) {
1079+
if (getLangOpts().CPlusPlus11) {
10801080
for (unsigned I = 0;; ++I) {
10811081
const Token &T = GetLookAheadToken(I);
10821082
if (T.is(tok::r_paren))
@@ -1088,9 +1088,13 @@ Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd) {
10881088
}
10891089
}
10901090

1091-
if (ParseAsExpression)
1091+
if (ParseAsExpression) {
1092+
Diag(Tok,
1093+
getLangOpts().CPlusPlus26
1094+
? diag::warn_cxx20_compat_static_assert_user_generated_message
1095+
: diag::ext_cxx_static_assert_user_generated_message);
10921096
AssertMessage = ParseConstantExpressionInExprEvalContext();
1093-
else if (tokenIsLikeStringLiteral(Tok, getLangOpts()))
1097+
} else if (tokenIsLikeStringLiteral(Tok, getLangOpts()))
10941098
AssertMessage = ParseUnevaluatedStringLiteralExpression();
10951099
else {
10961100
Diag(Tok, diag::err_expected_string_literal)

clang/test/CXX/drs/cwg27xx.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ void test() {
178178
}
179179

180180
namespace cwg2798 { // cwg2798: 17
181-
#if __cpp_static_assert >= 202306
181+
#if __cplusplus > 202302L
182182
struct string {
183183
constexpr string() {
184184
data_ = new char[6]();

clang/test/Lexer/cxx-features.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@
325325
#error "wrong value for __cpp_range_based_for"
326326
#endif
327327

328-
#if check(static_assert, 0, 200410, 200410, 201411, 201411, 201411, 202306)
328+
#if check(static_assert, 0, 202306, 202306, 202306, 202306, 202306, 202306)
329329
#error "wrong value for __cpp_static_assert"
330330
#endif
331331

clang/test/Parser/cxx11-user-defined-literals.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ int f() {
2121
asm("mov %eax, %rdx"_foo); // expected-error {{user-defined suffix cannot be used here}}
2222
}
2323

24-
static_assert(true, "foo"_bar); // expected-error {{user-defined suffix cannot be used here}}
24+
static_assert(true, "foo"_bar); // expected-error {{no matching literal operator for call to 'operator""_bar'}}
25+
// expected-warning@-1 {{'static_assert' with a user-generated message is a C++26 extension}}
2526

2627
int cake() __attribute__((availability(macosx, unavailable, message = "is a lie"_x))); // expected-error {{user-defined suffix cannot be used here}}
2728

clang/test/Sema/static-assert.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,12 @@ void foo(void) {
2525
#endif
2626
}
2727

28-
_Static_assert(1, invalid); // expected-error {{expected string literal for diagnostic message in static_assert}} \
29-
// ext-warning {{'_Static_assert' is a C11 extension}}
28+
_Static_assert(1, invalid); // ext-warning {{'_Static_assert' is a C11 extension}}
29+
#ifndef __cplusplus
30+
// expected-error@-2 {{expected string literal for diagnostic message in static_assert}}
31+
#endif
32+
// cxx-error@-4 {{use of undeclared identifier 'invalid'}}
33+
// cxx-warning@-5 {{'static_assert' with a user-generated message is a C++26 extension}}
3034

3135
struct A {
3236
int a;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %clang_cc1 -std=c++98 -fsyntax-only -pedantic %s -verify=precxx11,precxx17,precxx26
2+
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -pedantic %s -verify=since-cxx11,precxx17,precxx26 -Wc++98-compat
3+
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -pedantic %s -verify=since-cxx11,since-cxx17,precxx26 -Wc++98-compat -Wpre-c++17-compat
4+
// 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
5+
6+
static_assert(false, "a");
7+
// precxx11-error@-1 {{a type specifier is required for all declarations}}
8+
// since-cxx11-warning@-2 {{'static_assert' declarations are incompatible with C++98}}
9+
// since-cxx11-error@-3 {{static assertion failed: a}}
10+
11+
#if __cplusplus >= 201103L
12+
static_assert(false);
13+
// since-cxx11-warning@-1 {{'static_assert' declarations are incompatible with C++98}}
14+
// precxx17-warning@-2 {{'static_assert' with no message is a C++17 extension}}
15+
// since-cxx17-warning@-3 {{'static_assert' with no message is incompatible with C++ standards before C++17}}
16+
// since-cxx11-error@-4 {{static assertion failed}}
17+
18+
struct X {
19+
static constexpr int size() { return 1; } // since-cxx11-warning {{'constexpr'}}
20+
static constexpr const char* data() { return "b"; } // since-cxx11-warning {{'constexpr'}}
21+
};
22+
23+
static_assert(false, X());
24+
// since-cxx11-warning@-1 {{'static_assert' declarations are incompatible with C++98}}
25+
// precxx26-warning@-2 {{'static_assert' with a user-generated message is a C++26 extension}}
26+
// since-cxx26-warning@-3 {{'static_assert' with a user-generated message is incompatible with C++ standards before C++26}}
27+
// since-cxx11-error@-4 {{static assertion failed: b}}
28+
#endif

0 commit comments

Comments
 (0)