On 8/25/25 2:56 AM, Jakub Jelinek wrote:
Hi!
The following patch implements the proposed resolution of
https://cplusplus.github.io/CWG/issues/3048.html
Instead of rejecting structured binding size it just builds a normal
decl rather than structured binding declaration.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK.
2025-08-25 Jakub Jelinek <ja...@redhat.com>
* pt.cc (finish_expansion_stmt): Implement C++ CWG3048
- Empty destructuring expansion statements. Don't error for
destructuring expansion stmts if sz is 0, don't call
fit_decomposition_lang_decl if n is 0 and pass NULL rather than
this_decomp to cp_finish_decl.
* g++.dg/cpp26/expansion-stmt15.C: Don't expect error on
destructuring expansion stmts with structured binding size 0.
* g++.dg/cpp26/expansion-stmt21.C: New test.
* g++.dg/cpp26/expansion-stmt22.C: New test.
--- gcc/cp/pt.cc.jj 2025-08-23 15:51:08.726081054 +0200
+++ gcc/cp/pt.cc 2025-08-23 16:56:58.997154023 +0200
@@ -32834,11 +32834,6 @@ finish_expansion_stmt (tree expansion_st
tf_warning_or_error);
if (sz < 0)
return;
- if (sz == 0)
- {
- error_at (loc, "empty structured binding");
- return;
- }
n = sz;
tree auto_node = make_auto ();
tree decomp_type = cp_build_reference_type (auto_node, true);
@@ -32850,7 +32845,8 @@ finish_expansion_stmt (tree expansion_st
= DECL_DECLARED_CONSTEXPR_P (range_decl);
if (DECL_DECLARED_CONSTEXPR_P (decl))
TREE_READONLY (decl) = 1;
- fit_decomposition_lang_decl (decl, NULL_TREE);
+ if (n)
+ fit_decomposition_lang_decl (decl, NULL_TREE);
pushdecl (decl);
cp_decomp this_decomp;
this_decomp.count = n;
@@ -32871,7 +32867,7 @@ finish_expansion_stmt (tree expansion_st
DECL_NAME (decl) = for_range__identifier;
cp_finish_decl (decl, expansion_init,
/*is_constant_init*/false, NULL_TREE,
- LOOKUP_ONLYCONVERTING, &this_decomp);
+ LOOKUP_ONLYCONVERTING, n ? &this_decomp : NULL);
DECL_NAME (decl) = NULL_TREE;
}
--- gcc/testsuite/g++.dg/cpp26/expansion-stmt15.C.jj 2025-08-15 22:38:29.076869994 +0200
+++ gcc/testsuite/g++.dg/cpp26/expansion-stmt15.C 2025-08-23
17:05:32.182449214 +0200
@@ -27,11 +27,11 @@ foo (int n)
int e = 42;
d[0] = 42;
template for (auto a : A {}) // { dg-warning "'template for' only available
with" "" { target c++23_down } }
- ; // { dg-error "empty structured binding"
"" { target *-*-* } .-1 }
+ ;
template for (int b : B {}) // { dg-warning "'template for' only available
with" "" { target c++23_down } }
;
template for (int i : c) // { dg-warning "'template for' only available
with" "" { target c++23_down } }
- ; // { dg-error "empty structured binding"
"" { target *-*-* } .-1 }
+ ;
template for (int i : d) // { dg-warning "'template for' only available
with" "" { target c++23_down } }
; // { dg-error "cannot decompose variable length
array" "" { target *-*-* } .-1 }
template for (auto a : C {}) // { dg-warning "'template for' only available
with" "" { target c++23_down } }
--- gcc/testsuite/g++.dg/cpp26/expansion-stmt21.C.jj 2025-08-23
17:08:16.771305746 +0200
+++ gcc/testsuite/g++.dg/cpp26/expansion-stmt21.C 2025-08-23
17:08:48.477892823 +0200
@@ -0,0 +1,24 @@
+// DR3048 - Empty destructuring expansion statements
+// { dg-do run { target c++11 } }
+// { dg-options "" }
+
+struct A {};
+
+int
+foo ()
+{
+ int c[0] = {};
+ int r = 0;
+ template for (auto a : A {}) // { dg-warning "'template for' only available
with" "" { target c++23_down } }
+ ++r;
+ template for (int i : c) // { dg-warning "'template for' only available
with" "" { target c++23_down } }
+ ++r;
+ return r;
+}
+
+int
+main ()
+{
+ if (foo () != 0)
+ __builtin_abort ();
+}
--- gcc/testsuite/g++.dg/cpp26/expansion-stmt22.C.jj 2025-08-23
17:08:25.082197512 +0200
+++ gcc/testsuite/g++.dg/cpp26/expansion-stmt22.C 2025-08-23
17:12:29.452987817 +0200
@@ -0,0 +1,16 @@
+// DR3048 - Empty destructuring expansion statements
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct A {};
+
+void
+foo ()
+{
+ static constexpr A b {};
+ template for (constexpr auto a : b) // { dg-warning "'template for' only available
with" "" { target c++23_down } }
+ ;
+ A c {};
+ template for (constexpr auto a : c) // { dg-warning "'template for' only available
with" "" { target c++23_down } }
+ ; // { dg-error "'c' is not a constant expression"
"" { target *-*-* } .-1 }
+}
Jakub