Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/16?
-- >8 --
Given
struct X {
template<class T1, class T2> X(T1, T2); // #1
};
our members_of(^^X) included #1 three times: __ct, and then also the two
clones: __ct_comp and __ct_base. In class_members_of we have code to skip
DECL_CLONED_FUNCTION_P, but it doesn't cover templates. Do so.
PR c++/127643
gcc/cp/ChangeLog:
* reflect.cc (class_members_of): Also skip templated clones.
gcc/testsuite/ChangeLog:
* g++.dg/reflect/members_of18.C: New test.
---
gcc/cp/reflect.cc | 9 ++---
gcc/testsuite/g++.dg/reflect/members_of18.C | 40 +++++++++++++++++++++
2 files changed, 45 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/reflect/members_of18.C
diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc
index 51f0885436e..8bf518df64f 100644
--- a/gcc/cp/reflect.cc
+++ b/gcc/cp/reflect.cc
@@ -7133,16 +7133,17 @@ class_members_of (location_t loc, const constexpr_ctx
*ctx, tree r,
{
tree m = field;
if (TREE_CODE (field) == FIELD_DECL && DECL_ARTIFICIAL (field))
- continue; /* Ignore bases and the vptr. */
+ /* Ignore bases and the vptr. */
+ continue;
+ else if (DECL_CLONED_FUNCTION_P (field))
+ /* Ignore cloned cdtors. */
+ continue;
else if (DECL_SELF_REFERENCE_P (field))
continue;
else if (TREE_CODE (field) == TYPE_DECL)
m = TREE_TYPE (field);
else if (TREE_CODE (field) == FUNCTION_DECL)
{
- /* Ignore cloned cdtors. */
- if (DECL_CLONED_FUNCTION_P (field))
- continue;
/* Ignore functions with unsatisfied constraints. */
if (!constraints_satisfied_p (field))
continue;
diff --git a/gcc/testsuite/g++.dg/reflect/members_of18.C
b/gcc/testsuite/g++.dg/reflect/members_of18.C
new file mode 100644
index 00000000000..18e96b28dd8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/members_of18.C
@@ -0,0 +1,40 @@
+// PR c++/127643
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+#include <meta>
+
+struct X {
+ template<class T1, class T2> X(T1, T2);
+ template<class T1, class T2> void f(T1, T2);
+};
+
+template<typename>
+struct Y {
+ template<class T> Y(T);
+};
+
+static constexpr auto ctx = std::meta::access_context::unchecked();
+
+/* 7 because we expect:
+ template<class T1, class T2> X::X(T1, T2)
+ template<class T1, class T2> void X::f(T1, T2)
+ constexpr X::X(const X&)
+ constexpr X& X::operator=(const X&)
+ constexpr X::X(X&&)
+ constexpr X& X::operator=(X&&)
+ constexpr X::~X() */
+static_assert (members_of (^^X, ctx).size () == 7);
+
+consteval auto
+count_ctor_templates (std::meta::info r)
+{
+ int n = 0;
+ for (auto m : members_of (r, ctx))
+ if (is_constructor_template (m))
+ ++n;
+ return n;
+}
+
+static_assert (count_ctor_templates (^^X) == 1);
+static_assert (count_ctor_templates (^^Y<int>) == 1);
base-commit: a924d879f01d00d6c29e870c51bebcbf5e5a96eb
--
2.55.0