[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 11: Final Touches and Tests) (PR #169690)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Mar 23 16:03:10 PDT 2026
https://github.com/Sirraide updated https://github.com/llvm/llvm-project/pull/169690
>From f87b7af08ed4e37924e898e69ba886b976989ff5 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Wed, 26 Nov 2025 18:03:57 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 11)
---
clang/docs/ReleaseNotes.rst | 1 +
.../clang/Basic/DiagnosticCommonKinds.td | 4 -
clang/test/AST/ast-dump-expansion-stmt.cpp | 49 +++++++++
clang/test/AST/ast-print-expansion-stmts.cpp | 104 ++++++++++++++++++
clang/test/SemaTemplate/GH176155.cpp | 20 +---
clang/www/cxx_status.html | 2 +-
6 files changed, 160 insertions(+), 20 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 3dabf951661e5..0bc081a179f77 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -117,6 +117,7 @@ C++ Language Changes
C++2c Feature Support
^^^^^^^^^^^^^^^^^^^^^
+- Implemented `P1306R5 <https://wg21.link/P1306R5>`_ Expansion Statements.
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..eb9acd5e0b652
--- /dev/null
+++ b/clang/test/AST/ast-dump-expansion-stmt.cpp
@@ -0,0 +1,49 @@
+// 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//"
+
+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; }
+};
+
+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);
+ }
+
+ // CHECK: CXXExpansionStmtDecl
+ // CHECK-NEXT: CXXExpansionStmtPattern {{.*}} iterating
+ // CHECK: CXXExpansionStmtInstantiation
+ static constexpr Array<int, 3> a;
+ template for (auto x : a) {
+ foo(x);
+ }
+
+ // 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..014da274af093
--- /dev/null
+++ b/clang/test/AST/ast-print-expansion-stmts.cpp
@@ -0,0 +1,104 @@
+// 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
+
+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; }
+};
+
+// 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);
+ }
+
+ // Iterating expansion statement.
+ //
+ // CHECK: static constexpr Array<int, 3> a;
+ // CHECK-NEXT: template for (auto x : (a)) {
+ // CHECK-NEXT: foo(x);
+ // CHECK-NEXT: }
+ static constexpr Array<int, 3> a;
+ template for (auto x : a) {
+ foo(x);
+ }
+
+ // 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);
+ }
+
+ // Iterating expansion statement.
+ //
+ // CHECK: static constexpr Array<int, 3> a;
+ // CHECK-NEXT: template for (int x : (a)) {
+ // CHECK-NEXT: foo(x);
+ // CHECK-NEXT: }
+ static constexpr Array<int, 3> a;
+ template for (int x : a) {
+ foo(x);
+ }
+
+ // 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/SemaTemplate/GH176155.cpp b/clang/test/SemaTemplate/GH176155.cpp
index 12a9de2ae2d46..ce2ca2d488a03 100644
--- a/clang/test/SemaTemplate/GH176155.cpp
+++ b/clang/test/SemaTemplate/GH176155.cpp
@@ -1,26 +1,16 @@
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+// expected-no-diagnostics
template <int> struct bad {
template <class T, auto =
- [] { // #lambda
- // expected-note@#lambda {{while substituting into a lambda expression here}}
- // expected-note@#lambda 2{{capture 'i' by value}}
- // expected-note@#lambda 2{{capture 'i' by reference}}
- // expected-note@#lambda 2{{default capture by value}}
- // expected-note@#lambda 2{{default capture by reference}}
- for (int i = 0; i < 100; ++i) { // #i
- // expected-error at -1 {{variable 'i' cannot be implicitly captured in a lambda with no capture-default specified}}
- // expected-note@#i {{'i' declared here}}
- // expected-note@#lambda {{lambda expression begins here}}
- // expected-error at -4 {{variable 'i' cannot be implicitly captured in a lambda with no capture-default specified}}
- // expected-note@#i {{'i' declared here}}
- // expected-note@#lambda {{lambda expression begins here}}
+ [] {
+ for (int i = 0; i < 100; ++i) {
struct LoopHelper {
static constexpr void process() {}
};
}
}>
- static void f(T) {} // expected-note {{in instantiation of default argument for 'f<int>' required here}}
+ static void f(T) {}
};
-int main() { bad<0>::f(0); } // expected-note {{while substituting deduced template arguments into function template 'f'}}
+int main() { bad<0>::f(0); }
diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index 00ca18bc87635..43a0e7bfbdfe9 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -317,7 +317,7 @@ <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="unreleased" align="center">Clang 23</td>
</tr>
<tr>
<td>constexpr virtual inheritance</td>
More information about the llvm-branch-commits
mailing list