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 ();
+}

Reply via email to