https://github.com/Sirraide updated https://github.com/llvm/llvm-project/pull/169690
>From 16c7a3c385c68174c6f718a24471c175e4257f06 Mon Sep 17 00:00:00 2001 From: Sirraide <[email protected]> Date: Wed, 26 Nov 2025 18:03:57 +0100 Subject: [PATCH 1/2] [Clang] [C++26] Expansion Statements (Part 11) --- clang/docs/ReleaseNotes.rst | 2 + .../clang/Basic/DiagnosticCommonKinds.td | 4 - clang/test/AST/ast-dump-expansion-stmt.cpp | 54 +++++++++ clang/test/AST/ast-print-expansion-stmts.cpp | 113 ++++++++++++++++++ clang/www/cxx_status.html | 8 +- 5 files changed, 176 insertions(+), 5 deletions(-) create mode 100644 clang/test/AST/ast-dump-expansion-stmt.cpp create mode 100644 clang/test/AST/ast-print-expansion-stmts.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index fc17eead02589..1fab855bb1fc2 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -126,6 +126,8 @@ C++ Language Changes C++2c Feature Support ^^^^^^^^^^^^^^^^^^^^^ +- Clang now has partial support for `P1306R5 <https://wg21.link/P1306R5>`_ Expansion Statements. Iterating expansion + statements currently cannot be expanded and will result in a diagnostic, but other types of expansion statements work. C++23 Feature Support ^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td index f1ee130eb1f11..cb267e3ee05c1 100644 --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td @@ -22,10 +22,6 @@ def select_constexpr_spec_kind : TextSubstitution< def fatal_too_many_errors : Error<"too many errors emitted, stopping now">, DefaultFatal; -// TODO: Remove this. -def err_expansion_statements_todo : Error< - "TODO (expansion statements)">; - def warn_stack_exhausted : Warning< "stack nearly exhausted; compilation time may suffer, and " "crashes due to stack overflow are likely">, diff --git a/clang/test/AST/ast-dump-expansion-stmt.cpp b/clang/test/AST/ast-dump-expansion-stmt.cpp new file mode 100644 index 0000000000000..94f0ee1449f17 --- /dev/null +++ b/clang/test/AST/ast-dump-expansion-stmt.cpp @@ -0,0 +1,54 @@ +// Test without serialization: +// RUN: %clang_cc1 -std=c++26 -triple x86_64-unknown-unknown -ast-dump %s +// +// Test with serialization: +// RUN: %clang_cc1 -std=c++26 -triple x86_64-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -x c++ -std=c++26 -triple x86_64-unknown-unknown -include-pch %t -ast-dump-all /dev/null \ +// RUN: | sed -e "s/ <undeserialized declarations>//" -e "s/ imported//" + +#if 0 // Disabled until we support iterating expansion statements. +template <typename T, __SIZE_TYPE__ size> +struct Array { + T data[size]{}; + constexpr const T* begin() const { return data; } + constexpr const T* end() const { return data + size; } +}; +#endif // 0 + +void foo(int); + +template <typename T> +void test(T t) { + // CHECK: CXXExpansionStmtDecl + // CHECK-NEXT: CXXExpansionStmtPattern {{.*}} enumerating + // CHECK: CXXExpansionStmtInstantiation + template for (auto x : {1, 2, 3}) { + foo(x); + } + +#if 0 // Disabled until we support iterating expansion statements. + // NOTE: Remove 'DISABLED-' when the '#if 0' is removed. + // DISABLED-CHECK: CXXExpansionStmtDecl + // DISABLED-CHECK-NEXT: CXXExpansionStmtPattern {{.*}} iterating + // DISABLED-CHECK: CXXExpansionStmtInstantiation + static constexpr Array<int, 3> a; + template for (auto x : a) { + foo(x); + } +#endif + + // CHECK: CXXExpansionStmtDecl + // CHECK-NEXT: CXXExpansionStmtPattern {{.*}} destructuring + // CHECK: CXXExpansionStmtInstantiation + int arr[3]{1, 2, 3}; + template for (auto x : arr) { + foo(x); + } + + // CHECK: CXXExpansionStmtDecl + // CHECK-NEXT: CXXExpansionStmtPattern {{.*}} dependent + // CHECK-NOT: CXXExpansionStmtInstantiation + template for (auto x : t) { + foo(x); + } +} diff --git a/clang/test/AST/ast-print-expansion-stmts.cpp b/clang/test/AST/ast-print-expansion-stmts.cpp new file mode 100644 index 0000000000000..880e17a9d3e2f --- /dev/null +++ b/clang/test/AST/ast-print-expansion-stmts.cpp @@ -0,0 +1,113 @@ +// Without serialization: +// RUN: %clang_cc1 -std=c++26 -ast-print %s | FileCheck %s +// +// With serialization: +// RUN: %clang_cc1 -std=c++26 -emit-pch -o %t %s +// RUN: %clang_cc1 -x c++ -std=c++26 -include-pch %t -ast-print /dev/null | FileCheck %s + +#if 0 // Disabled until we support iterating expansion statements. +template <typename T, __SIZE_TYPE__ size> +struct Array { + T data[size]{}; + constexpr const T* begin() const { return data; } + constexpr const T* end() const { return data + size; } +}; +#endif // 0 + +// CHECK: void foo(int); +void foo(int); + +// CHECK: template <typename T> void test(T t) { +template <typename T> +void test(T t) { + // Enumerating expansion statement. + // + // CHECK: template for (auto x : {1, 2, 3}) { + // CHECK-NEXT: foo(x); + // CHECK-NEXT: } + template for (auto x : {1, 2, 3}) { + foo(x); + } + +#if 0 // Disabled until we support iterating expansion statements. + // Iterating expansion statement. + // + // NOTE: Remove 'DISABLED-' when the '#if 0' is removed. + // DISABLED-CHECK: static constexpr Array<int, 3> a; + // DISABLED-CHECK-NEXT: template for (auto x : (a)) { + // DISABLED-CHECK-NEXT: foo(x); + // DISABLED-CHECK-NEXT: } + static constexpr Array<int, 3> a; + template for (auto x : a) { + foo(x); + } +#endif // 0 + + // Destructuring expansion statement. + // + // CHECK: int arr[3]{1, 2, 3}; + // CHECK-NEXT: template for (auto x : arr) { + // CHECK-NEXT: foo(x); + // CHECK-NEXT: } + int arr[3]{1, 2, 3}; + template for (auto x : arr) { + foo(x); + } + + // Dependent expansion statement. + // + // CHECK: template for (auto x : t) { + // CHECK-NEXT: foo(x); + // CHECK-NEXT: } + template for (auto x : t) { + foo(x); + } +} + +// CHECK: template <typename T> void test2(T t) { +template <typename T> +void test2(T t) { + // Enumerating expansion statement. + // + // CHECK: template for (int x : {1, 2, 3}) { + // CHECK-NEXT: foo(x); + // CHECK-NEXT: } + template for (int x : {1, 2, 3}) { + foo(x); + } + +#if 0 // Disabled until we support iterating expansion statements. + // Iterating expansion statement. + // + // NOTE: Remove 'DISABLED-' when the '#if 0' is removed. + // DISABLED-CHECK: static constexpr Array<int, 3> a; + // DISABLED-CHECK-NEXT: template for (int x : (a)) { + // DISABLED-CHECK-NEXT: foo(x); + // DISABLED-CHECK-NEXT: } + + static constexpr Array<int, 3> a; + template for (int x : a) { + foo(x); + } +#endif // 0 + + // Destructuring expansion statement. + // + // CHECK: int arr[3]{1, 2, 3}; + // CHECK-NEXT: template for (int x : arr) { + // CHECK-NEXT: foo(x); + // CHECK-NEXT: } + int arr[3]{1, 2, 3}; + template for (int x : arr) { + foo(x); + } + + // Dependent expansion statement. + // + // CHECK: template for (int x : t) { + // CHECK-NEXT: foo(x); + // CHECK-NEXT: } + template for (int x : t) { + foo(x); + } +} diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 2c834b07f9a8f..9ff43c713d5b3 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -320,7 +320,13 @@ <h2 id="cxx26">C++2c implementation status</h2> <tr> <td>Expansion Statements</td> <td><a href="https://wg21.link/P1306">P1306R5</a></td> - <td class="none" align="center">No</td> + <td class="partial" align="center"> + <details> + <summary>Clang 23 (Partial)</summary> + Iterating expansion statements currently cannot be expanded and will + result in a diagnostic, but other types of expansion statements work. + </details> + </td> </tr> <tr> <td>constexpr virtual inheritance</td> >From 77bb03e7cd1a875283292b6d11912c53ed78ef5b Mon Sep 17 00:00:00 2001 From: Sirraide <[email protected]> Date: Fri, 10 Jul 2026 21:58:54 +0200 Subject: [PATCH 2/2] Revert "[Clang] [C++26] Expansion Statements (Part 10)" This reverts commit 4e3cf1966eb18c3155c567dcefc5510ee1f7c378. --- .../clang/Basic/DiagnosticSemaKinds.td | 4 - clang/include/clang/Basic/LangOptions.def | 1 - clang/include/clang/Options/Options.td | 4 - clang/lib/Driver/ToolChains/Clang.cpp | 1 - clang/lib/Sema/SemaExpand.cpp | 18 ----- .../SemaCXX/cxx2c-expansion-stmts-limit.cpp | 73 ------------------- .../SemaCXX/cxx2c-fexpansion-statements.cpp | 9 --- 7 files changed, 110 deletions(-) delete mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp delete mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 14e6b71a4256e..bfe0fe75389fa 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -167,10 +167,6 @@ def note_constexpr_assert_failed : Note< "assertion failed during evaluation of constant expression">; def err_expansion_size_expr_not_ice : Error< "expansion statement size is not a constant expression">; -def err_expansion_too_big : Error< - "expansion statement size %0 exceeds maximum configured size %1">; -def note_use_fexpansion_limit : Note< - "use -fexpansion-limit=N to adjust this limit">; def err_iterating_expansion_stmt_unsupported : Error< "iterating expansion statements are not yet supported">; diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 7da7851085130..dd4c5a653d38b 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -386,7 +386,6 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign, "maximum constexpr call depth") LANGOPT(ConstexprStepLimit, 32, 1048576, Benign, "maximum constexpr evaluation steps") -LANGOPT(MaxTemplateForExpansions, 32, 16384, Benign, "maximum template for expansions") LANGOPT(EnableNewConstInterp, 1, 0, Benign, "enable the experimental new constant interpreter") LANGOPT(BracketDepth, 32, 256, Benign, diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 6819a2b582b89..412683fd968b0 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -2159,10 +2159,6 @@ def fconstexpr_steps_EQ : Joined<["-"], "fconstexpr-steps=">, Group<f_Group>, Visibility<[ClangOption, CC1Option]>, HelpText<"Set the maximum number of steps in constexpr function evaluation (0 = no limit)">, MarshallingInfoInt<LangOpts<"ConstexprStepLimit">, "1048576">; -def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group<f_Group>, - Visibility<[ClangOption, CC1Option]>, - HelpText<"Set the maximum number of times a single expansion statement may be expanded (0 = no limit)">, - MarshallingInfoInt<LangOpts<"MaxTemplateForExpansions">, "256">; def fexperimental_new_constant_interpreter : Flag<["-"], "fexperimental-new-constant-interpreter">, Group<f_Group>, HelpText<"Enable the experimental new constant interpreter">, Visibility<[ClangOption, CC1Option]>, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index e7b16101943ae..86b0a705c7fe9 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -6563,7 +6563,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_foperator_arrow_depth_EQ); Args.AddLastArg(CmdArgs, options::OPT_fconstexpr_depth_EQ); Args.AddLastArg(CmdArgs, options::OPT_fconstexpr_steps_EQ); - Args.AddLastArg(CmdArgs, options::OPT_fexpansion_limit_EQ); Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library); diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp index 8b25adc98b659..8647276149d9a 100644 --- a/clang/lib/Sema/SemaExpand.cpp +++ b/clang/lib/Sema/SemaExpand.cpp @@ -52,18 +52,6 @@ struct IterableExpansionStmtData { }; } // namespace -static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations, - SourceLocation Loc) { - unsigned Max = S.LangOpts.MaxTemplateForExpansions; - if (Max != 0 && NumInstantiations > Max) { - S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max; - S.Diag(Loc, diag::note_use_fexpansion_limit); - return true; - } - - return false; -} - // Build a 'DeclRefExpr' designating the template parameter that is used as // the expansion index static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) { @@ -267,9 +255,6 @@ static StmtResult BuildDestructuringDecompositionDecl( if (!Arity) return StmtError(); - if (CheckExpansionSize(S, *Arity, ColonLoc)) - return StmtError(); - QualType AutoRRef = S.Context.getAutoRRefDeductType(); SmallVector<BindingDecl *> Bindings; for (unsigned I = 0; I < *Arity; ++I) @@ -528,9 +513,6 @@ StmtResult Sema::FinishCXXExpansionStmt(Stmt *Exp, Stmt *Body) { if (!NumInstantiations) return StmtError(); - if (CheckExpansionSize(*this, *NumInstantiations, Expansion->getColonLoc())) - return StmtError(); - // Collect preamble statements. // // There are at most 3 of these: for iterating expansion statements, these diff --git a/clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp b/clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp deleted file mode 100644 index 384ca022ae5ee..0000000000000 --- a/clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp +++ /dev/null @@ -1,73 +0,0 @@ -// RUN: %clang_cc1 %s -std=c++2c -fsyntax-only -fexpansion-limit=32 -verify -// RUN: %clang_cc1 %s -std=c++2c -fsyntax-only -fexpansion-limit=32 -verify -fexperimental-new-constant-interpreter - -void g(int); - -#if 0 // Disabled until we support iterating expansion statements. -template <__SIZE_TYPE__ size> -struct String { - char data[size]; - - template <__SIZE_TYPE__ n> - constexpr String(const char (&str)[n]) { __builtin_memcpy(data, str, n); } - - constexpr const char* begin() const { return data; } - constexpr const char* end() const { return data + size - 1; } -}; - -template <__SIZE_TYPE__ n> -String(const char (&str)[n]) -> String<n>; - -template <typename T, __SIZE_TYPE__ size> -struct Array { - T data[size]{}; - constexpr const T* begin() const { return data; } - constexpr const T* end() const { return data + size; } -}; -#endif // 0 - -void expansion_size() { -#if 0 // Disabled until we support iterating expansion statements. - static constexpr Array<int, 32> almost_too_big; - template for (auto x : almost_too_big) g(x); - template for (constexpr auto x : almost_too_big) g(x); - - static constexpr Array<int, 33> too_big; - template for (auto x : too_big) g(x); // expected-error {{expansion statement size 33 exceeds maximum configured size 32}} expected-note {{use -fexpansion-limit=N to adjust this limit}} - template for (constexpr auto x : too_big) g(x); // expected-error {{expansion statement size 33 exceeds maximum configured size 32}} expected-note {{use -fexpansion-limit=N to adjust this limit}} - - static constexpr String big{"1234567890123456789012345678901234567890234567890"}; - template for (auto x : big) g(x); // expected-error {{expansion statement size 49 exceeds maximum configured size 32}} expected-note {{use -fexpansion-limit=N to adjust this limit}} - template for (constexpr auto x : big) g(x); // expected-error {{expansion statement size 49 exceeds maximum configured size 32}} expected-note {{use -fexpansion-limit=N to adjust this limit}} -#endif // 0 - - template for (auto x : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32}) g(x); - template for (constexpr auto x : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32}) g(x); - - template for (auto x : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // expected-error {{expansion statement size 33 exceeds maximum configured size 32}} expected-note {{use -fexpansion-limit=N to adjust this limit}} - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33}) g(x); - template for (constexpr auto x : {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, // expected-error {{expansion statement size 33 exceeds maximum configured size 32}} expected-note {{use -fexpansion-limit=N to adjust this limit}} - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33}) g(x); - - int huge[1'000'000'000]; - template for (auto x : huge) {} // expected-error {{expansion statement size 1000000000 exceeds maximum configured size 32}} expected-note {{use -fexpansion-limit=N to adjust this limit}} -} - -void array_too_big() { - int ok[32]; - int too_big[33]; - - template for (auto x : ok) {} - template for (auto x : too_big) {} // expected-error {{expansion statement size 33 exceeds maximum configured size 32}} \ - expected-note {{use -fexpansion-limit=N to adjust this limit}} -} diff --git a/clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp b/clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp deleted file mode 100644 index 2c80c392e400d..0000000000000 --- a/clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// RUN: %clang_cc1 %s -std=c++2c -fsyntax-only -fexpansion-limit=0 -verify -// expected-no-diagnostics - -// Test that passing =0 disables the limit. - -void big() { - int ok[500]; - template for (auto x : ok) {} -} _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
