On Thu, Dec 19, 2024 at 11:56:10AM -0500, Jason Merrill wrote: > Looks right.
So, I've tried to construct a testcase, but turns out modules.cc just doesn't handle structured bindings at namespace scope at all, so it is premature to try to get the ordering right in it. The first patch contains the attempt to turn dr2867-5.C testcase into a module header testcase with a fix for the first ICE I've run into (but it ICEs immediately elsewhere, the assumption that all namespace scope decls have names is all around). The second patch is much simpler testcase which doesn't care about ordering of anything and ICEs without/with the other patches the same. Should be all !DECL_NAME (decl) MK_unique? Or just DECL_DECOMPOSITION_P (decl) && !DECL_NAME (decl)? Structured bindings can't be redeclared, so I guess they are unique. Jakub
2025-01-03 Jakub Jelinek <ja...@redhat.com> * module.cc (trees_out::get_merge_kind): Don't ICE if DECL_NAME is NULL. * g++.dg/modules/dr2867-1_a.H: New test. * g++.dg/modules/dr2867-1_b.C: New test. --- gcc/cp/module.cc.jj 2025-01-02 11:47:10.367499411 +0100 +++ gcc/cp/module.cc 2025-01-03 12:18:23.403515542 +0100 @@ -10985,7 +10985,8 @@ trees_out::get_merge_kind (tree decl, de break; } - if (IDENTIFIER_ANON_P (DECL_NAME (decl))) + if (DECL_NAME (decl) + && IDENTIFIER_ANON_P (DECL_NAME (decl))) { if (RECORD_OR_UNION_TYPE_P (ctx)) mk = MK_field; --- gcc/testsuite/g++.dg/modules/dr2867-1_a.H.jj 2025-01-03 12:05:52.601093929 +0100 +++ gcc/testsuite/g++.dg/modules/dr2867-1_a.H 2025-01-03 12:13:23.746737536 +0100 @@ -0,0 +1,88 @@ +// CWG2867 - Order of initialization for structured bindings. +// { dg-additional-options -fmodule-header } +// { dg-module-cmi {} } + +#define assert(X) do { if (!(X)) __builtin_abort(); } while (0) + +namespace std { + template<typename T> struct tuple_size; + template<int, typename> struct tuple_element; +} + +extern int a, c, d, i; + +struct A { + A () { assert (c == 3); ++c; } + ~A () { ++a; } + template <int I> int &get () const { assert (c == 5 + I); ++c; return i; } +}; + +template <> struct std::tuple_size <A> { static const int value = 4; }; +template <int I> struct std::tuple_element <I, A> { using type = int; }; +template <> struct std::tuple_size <const A> { static const int value = 4; }; +template <int I> struct std::tuple_element <I, const A> { using type = int; }; + +struct B { + B () { assert (c >= 1 && c <= 2); ++c; } + ~B () { assert (c >= 9 && c <= 10); ++c; } +}; + +struct C { + constexpr C () {} + constexpr C (const C &) {} + template <int I> int &get () const { assert (d == 1 + I); ++d; return i; } +}; + +template <> struct std::tuple_size <C> { static const int value = 3; }; +template <int I> struct std::tuple_element <I, C> { using type = int; }; +template <> struct std::tuple_size <const C> { static const int value = 3; }; +template <int I> struct std::tuple_element <I, const C> { using type = int; }; + +inline A +foo (const B &, const B &) +{ + A a; + assert (c == 4); + ++c; + return a; +} + +constexpr C +foo (const C &, const C &) +{ + return C {}; +} + +inline int +bar (int &x, int y) +{ + x = y; + return y; +} + +inline int +baz (int &x, int y) +{ + assert (x == y); + return y; +} + +struct E { + ~E () { assert (a == 2); } +}; + +namespace { +E e; +int c1 = bar (c, 1); +const auto &[x, y, z, w] = foo (B {}, B {}); +int c2 = baz (c, 11); +int d1 = bar (d, 1); +const auto &[s, t, u] = foo (C {}, C {}); +int d2 = baz (d, 4); +int c3 = bar (c, 1); +auto [x2, y2, z2, w2] = foo (B {}, B {}); +int c4 = baz (c, 11); +int d3 = bar (d, 1); +auto [s2, t2, u2] = foo (C {}, C {}); +int d4 = baz (d, 4); +} --- gcc/testsuite/g++.dg/modules/dr2867-1_b.C.jj 2025-01-03 12:13:30.533641916 +0100 +++ gcc/testsuite/g++.dg/modules/dr2867-1_b.C 2025-01-03 12:13:51.037353027 +0100 @@ -0,0 +1,13 @@ +// CWG2867 - Order of initialization for structured bindings. +// { dg-do run } +// { dg-additional-options "-fmodules-ts" } + +import "dr2867-1_a.H"; + +int a, c, d, i; + +int +main () +{ + assert (a == 0); +}
2025-01-03 Jakub Jelinek <ja...@redhat.com> * g++.dg/modules/decomp-2_a.H: New test. * g++.dg/modules/decomp-2_b.C: New test. --- gcc/testsuite/g++.dg/modules/decomp-2_a.H.jj 2025-01-03 12:26:03.425073619 +0100 +++ gcc/testsuite/g++.dg/modules/decomp-2_a.H 2025-01-03 12:22:54.988707272 +0100 @@ -0,0 +1,11 @@ +// { dg-additional-options -fmodule-header } +// { dg-module-cmi {} } + +struct A { + int a, b, c; +}; + +namespace { +A d = { 1, 2, 3 }; +auto [a, b, c] = d; +} --- gcc/testsuite/g++.dg/modules/decomp-2_b.C.jj 2025-01-03 12:26:06.737027332 +0100 +++ gcc/testsuite/g++.dg/modules/decomp-2_b.C 2025-01-03 12:25:26.431590654 +0100 @@ -0,0 +1,11 @@ +// { dg-do run } +// { dg-additional-options "-fmodules-ts" } + +import "decomp-2_a.H"; + +int +main () +{ + if (a != 1 || b != 2 || c != 3) + __builtin_abort (); +}