Previously, members_of_class did not preserve decleration order for
imported types, as DECL_UIDs reflect streaming order rather than source order.
With TYPE_FIELDS now stored in declaration order by the preceding patch,
the DECL_UID-based sort in class_members_of is no longer needed, and
the decleration order for imported members is preserved.

gcc/cp/ChangeLog:

        * reflect.cc
          (class_members_of): remove sort on DECL_UID

gcc/testsuite/ChangeLog:

        * g++.dg/modules/reflect-class-order_a.C: New test.
        * g++.dg/modules/reflect-class-order_b.C: New test.
        * g++.dg/modules/reflect-clone-dtor_a.C: New test.
        * g++.dg/modules/reflect-clone-dtor_b.C: New test.

Signed-off-by: Thomas Berger <[email protected]>
---
 gcc/cp/reflect.cc                             |  5 ----
 .../g++.dg/modules/reflect-class-order_a.C    | 15 ++++++++++++
 .../g++.dg/modules/reflect-class-order_b.C    | 24 +++++++++++++++++++
 .../g++.dg/modules/reflect-clone-dtor_a.C     | 10 ++++++++
 .../g++.dg/modules/reflect-clone-dtor_b.C     |  9 +++++++
 5 files changed, 58 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/reflect-class-order_a.C
 create mode 100644 gcc/testsuite/g++.dg/modules/reflect-class-order_b.C
 create mode 100644 gcc/testsuite/g++.dg/modules/reflect-clone-dtor_a.C
 create mode 100644 gcc/testsuite/g++.dg/modules/reflect-clone-dtor_b.C

diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
index 2e18d2ce99d..c1c48f41712 100644
--- a/gcc/cp/reflect.cc
+++ b/gcc/cp/reflect.cc
@@ -6692,11 +6692,6 @@ class_members_of (location_t loc, const constexpr_ctx 
*ctx, tree r,
                                  get_reflection_raw (loc, m));
        }
     }
-  /* TYPE_DECLs in TYPE_FIELDS come after other decls due to the "struct
-     stat hack" (see finish_member_declaration), so for members_of the
-     declaration order is not preserved.  */
-  if (kind == METAFN_MEMBERS_OF && elts)
-    elts->qsort (members_cmp);
   if (kind == METAFN_MEMBERS_OF && !implicitly_declared.is_empty ())
     {
       gcc_assert (implicitly_declared.length () <= 8);
diff --git a/gcc/testsuite/g++.dg/modules/reflect-class-order_a.C b/gcc/
testsuite/g++.dg/modules/reflect-class-order_a.C
new file mode 100644
index 00000000000..083ce8582e7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/reflect-class-order_a.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-fmodules -freflection" }
+// { dg-module-cmi reflect_class_order }
+
+export module reflect_class_order;
+
+export struct A
+{
+  int a;
+  typedef int b;
+  struct C {};
+  int foo () { return 42; }
+  using D = C;
+  long e;
+};
diff --git a/gcc/testsuite/g++.dg/modules/reflect-class-order_b.C b/gcc/
testsuite/g++.dg/modules/reflect-class-order_b.C
new file mode 100644
index 00000000000..5ad513afa1e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/reflect-class-order_b.C
@@ -0,0 +1,24 @@
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-fmodules -freflection" }
+
+#include <meta>
+
+import reflect_class_order;
+
+/* Class members must be returned in declaration order
+   ([meta.reflection.member.queries] para. 4):
+     "Reflections of class members [...] appear in the order in which
+      they are declared."
+   Synthesized special members follow after ([Note 2]).
+
+   Expected order for A: a, b, C, foo, D, e.  */
+
+constexpr auto unchecked = std::meta::access_context::unchecked ();
+
+static_assert (identifier_of (members_of (^^A, unchecked)[0]) == "a");
+static_assert (identifier_of (members_of (^^A, unchecked)[1]) == "b");
+static_assert (identifier_of (members_of (^^A, unchecked)[2]) == "C");
+static_assert (identifier_of (members_of (^^A, unchecked)[3]) == "foo");
+static_assert (identifier_of (members_of (^^A, unchecked)[4]) == "D");
+static_assert (identifier_of (members_of (^^A, unchecked)[5]) == "e");
+static_assert (members_of (^^A, unchecked).size () == 12); // 6 defined + 
ctor, dtor, operators
diff --git a/gcc/testsuite/g++.dg/modules/reflect-clone-dtor_a.C b/gcc/
testsuite/g++.dg/modules/reflect-clone-dtor_a.C
new file mode 100644
index 00000000000..f56d7ff8c26
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/reflect-clone-dtor_a.C
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-fmodules -freflection" }
+// { dg-module-cmi reflect_clone_dtor }
+
+export module reflect_clone_dtor;
+
+export struct B
+{
+  virtual ~B ();
+};
diff --git a/gcc/testsuite/g++.dg/modules/reflect-clone-dtor_b.C b/gcc/
testsuite/g++.dg/modules/reflect-clone-dtor_b.C
new file mode 100644
index 00000000000..35dc6accb0a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/reflect-clone-dtor_b.C
@@ -0,0 +1,9 @@
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-fmodules -freflection" }
+
+#include <meta>
+import reflect_clone_dtor;
+
+/* make sure we don't break with cloned functions */
+static_assert (
+    members_of (^^B, std::meta::access_context::unchecked ()).size () == 4);
-- 
2.52.0




Reply via email to