On 3/15/26 7:58 AM, Thomas Berger wrote:
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
ChangeLog descriptions should also start with a capital letter and end
with a period. And this can all go on one line. Subsequent lines are
indented to line up with the *, rather than the filename.
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);