https://github.com/Sirraide updated https://github.com/llvm/llvm-project/pull/169690
>From f87b7af08ed4e37924e898e69ba886b976989ff5 Mon Sep 17 00:00:00 2001 From: Sirraide <[email protected]> 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@-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@-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> _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
