[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Jul 10 13:00:02 PDT 2026
https://github.com/Sirraide updated https://github.com/llvm/llvm-project/pull/169689
>From 4e3cf1966eb18c3155c567dcefc5510ee1f7c378 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH 1/2] [Clang] [C++26] Expansion Statements (Part 10)
---
.../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 insertions(+)
create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
create 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 bfe0fe75389fa..14e6b71a4256e 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -167,6 +167,10 @@ 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 dd4c5a653d38b..7da7851085130 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -386,6 +386,7 @@ 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 412683fd968b0..6819a2b582b89 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2159,6 +2159,10 @@ 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 86b0a705c7fe9..e7b16101943ae 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6563,6 +6563,7 @@ 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 8647276149d9a..8b25adc98b659 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -52,6 +52,18 @@ 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) {
@@ -255,6 +267,9 @@ 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)
@@ -513,6 +528,9 @@ 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
new file mode 100644
index 0000000000000..384ca022ae5ee
--- /dev/null
+++ b/clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
@@ -0,0 +1,73 @@
+// 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
new file mode 100644
index 0000000000000..2c80c392e400d
--- /dev/null
+++ b/clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp
@@ -0,0 +1,9 @@
+// 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) {}
+}
>From 9127173e51ed2575f47703604627006f4a4960b6 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Fri, 10 Jul 2026 21:59:51 +0200
Subject: [PATCH 2/2] [Clang] [C++26] Expansion Statements (Part 11: Final
Touches and Tests) (#169690)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This makes some very minor final changes that didn’t really fit anywhere
else, and in addition it also adds the AST dump tests because I wasn’t
quite sure where else to put them (we can’t put them with the other AST
stuff since this requires Sema).
---
clang/docs/ReleaseNotes.rst | 2 +
.../clang/Basic/DiagnosticCommonKinds.td | 4 -
.../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 ---
clang/test/AST/ast-dump-expansion-stmt.cpp | 54 +++++++++
clang/test/AST/ast-print-expansion-stmts.cpp | 113 ++++++++++++++++++
.../SemaCXX/cxx2c-expansion-stmts-limit.cpp | 73 -----------
.../SemaCXX/cxx2c-fexpansion-statements.cpp | 9 --
clang/www/cxx_status.html | 8 +-
12 files changed, 176 insertions(+), 115 deletions(-)
create mode 100644 clang/test/AST/ast-dump-expansion-stmt.cpp
create mode 100644 clang/test/AST/ast-print-expansion-stmts.cpp
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/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/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/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/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) {}
-}
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>
More information about the llvm-branch-commits
mailing list