Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
-- >8 --
In compare11.C, the static_assert was wrongly failing because
compare_reflections got a FIELD_DECL and COMPONENT_REF for ^^S::mem.
We shouldn't have created the COMPONENT_REF. So this patch avoids
creating the COMPONENT_REF by avoiding the finish_qualified_id_expr
call in tsubst_qualified_id when processing a REFLECT_EXPR.
Happily, it fixed some other issues too.
Unfortunately, I found another issue (PR124440) while trying to test
this patch more extensively. I plan to fix that separately next.
PR c++/124331
gcc/cp/ChangeLog:
* pt.cc (tsubst_qualified_id): New reflect_p parameter. Don't call
adjust_result_of_qualified_name_lookup and finish_qualified_id_expr
if reflect_p.
(tsubst_expr) <case REFLECT_EXPR>: Handle SCOPE_REF specially by
calling tsubst_qualified_id with reflect_p=true.
gcc/testsuite/ChangeLog:
* g++.dg/reflect/expr13.C: Uncomment the commented out assert.
* g++.dg/reflect/serialize2.C: Replace #if 0 with #ifdef.
* g++.dg/reflect/compare11.C: New test.
* g++.dg/reflect/member21.C: New test.
* g++.dg/reflect/serialize3.C: New test.
---
gcc/cp/pt.cc | 13 ++++++---
gcc/testsuite/g++.dg/reflect/compare11.C | 15 +++++++++++
gcc/testsuite/g++.dg/reflect/expr13.C | 3 +--
gcc/testsuite/g++.dg/reflect/member21.C | 32 +++++++++++++++++++++++
gcc/testsuite/g++.dg/reflect/serialize2.C | 3 +--
gcc/testsuite/g++.dg/reflect/serialize3.C | 5 ++++
6 files changed, 64 insertions(+), 7 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/reflect/compare11.C
create mode 100644 gcc/testsuite/g++.dg/reflect/member21.C
create mode 100644 gcc/testsuite/g++.dg/reflect/serialize3.C
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index ddf492b3435..7a6476caf89 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -18069,12 +18069,13 @@ tsubst_baselink (tree baselink, tree object_type,
true if the qualified-id will be a postfix-expression in-and-of
itself; false if more of the postfix-expression follows the
QUALIFIED_ID. ADDRESS_P is true if the qualified-id is the operand
- of "&". */
+ of "&". REFLECT_P is true if we are substituting the operand of
+ a reflect-expression. */
static tree
tsubst_qualified_id (tree qualified_id, tree args,
tsubst_flags_t complain, tree in_decl,
- bool done, bool address_p)
+ bool done, bool address_p, bool reflect_p = false)
{
tree expr;
tree scope;
@@ -18197,7 +18198,9 @@ tsubst_qualified_id (tree qualified_id, tree args,
if (expr == error_mark_node && complain & tf_error)
qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1),
expr, input_location);
- else if (TYPE_P (scope))
+ /* For ^^S::mem, we do not want to create the dummy object that
+ finish_non_static_data_member would give us. */
+ else if (TYPE_P (scope) && !reflect_p)
{
expr = (adjust_result_of_qualified_name_lookup
(expr, scope, current_nonlambda_class_type ()));
@@ -23155,6 +23158,10 @@ tsubst_expr (tree t, tree args, tsubst_flags_t
complain, tree in_decl)
instantiated entities and so no need to tsubst the annotation
attribute and we rely on pointer equality of that. */
;
+ else if (TREE_CODE (h) == SCOPE_REF)
+ h = tsubst_qualified_id (h, args, complain, in_decl,
+ /*done=*/true, /*address_p=*/false,
+ /*reflect_p=*/true);
else
{
/* [expr.reflect] The id-expression of a reflect-expression is
diff --git a/gcc/testsuite/g++.dg/reflect/compare11.C
b/gcc/testsuite/g++.dg/reflect/compare11.C
new file mode 100644
index 00000000000..d2339543d2c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/compare11.C
@@ -0,0 +1,15 @@
+// PR c++/124331
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+#include <meta>
+
+template <typename T>
+void f() {
+ constexpr auto ctx = std::meta::access_context::current();
+ static constexpr auto rng =
std::define_static_array(nonstatic_data_members_of(^^T, ctx));
+ static_assert(rng[0] == ^^T::mem);
+};
+
+struct S { int mem; };
+auto force_instantiation = (f<S>, 0);
diff --git a/gcc/testsuite/g++.dg/reflect/expr13.C
b/gcc/testsuite/g++.dg/reflect/expr13.C
index 6be27640ed7..14978bc1ecc 100644
--- a/gcc/testsuite/g++.dg/reflect/expr13.C
+++ b/gcc/testsuite/g++.dg/reflect/expr13.C
@@ -16,5 +16,4 @@ constexpr auto foo (S s) {
}
constexpr auto a = foo (Y { 42 });
-// TODO: This doesn't work: 'const struct X<^^Y::name>' is not the same as
'const struct X<^^Y::name>'
-//static_assert (std::is_same_v <decltype (a), const X <^^Y::name>>);
+static_assert (std::is_same_v <decltype (a), const X <^^Y::name>>);
diff --git a/gcc/testsuite/g++.dg/reflect/member21.C
b/gcc/testsuite/g++.dg/reflect/member21.C
new file mode 100644
index 00000000000..48ce3f1631d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/member21.C
@@ -0,0 +1,32 @@
+// PR c++/124331
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+struct B { consteval virtual int fn() const { return 1; } };
+struct D : B { consteval int fn() const override { return 2; } };
+
+constexpr D d;
+
+template<typename T, typename U>
+void
+f ()
+{
+ static_assert(d.[:^^U::fn:]() == 2);
+ static_assert(d.[:^^D::fn:]() == 2);
+ static_assert(d.U::fn() == 2);
+ static_assert(d.D::fn() == 2);
+ static_assert(d.fn() == 2);
+ // FIXME PR124440
+ //static_assert(d.[:^^T::fn:]() == 2);
+ static_assert(d.[:^^T:]::fn() == 1);
+ static_assert(d.T::fn() == 1);
+ //static_assert(d.[:^^B::fn:]() == 2);
+ static_assert(d.[:^^B:]::fn() == 1);
+ static_assert(d.B::fn() == 1);
+}
+
+void
+g ()
+{
+ f<B, D>();
+}
diff --git a/gcc/testsuite/g++.dg/reflect/serialize2.C
b/gcc/testsuite/g++.dg/reflect/serialize2.C
index 9b3ae685589..48a7b266b86 100644
--- a/gcc/testsuite/g++.dg/reflect/serialize2.C
+++ b/gcc/testsuite/g++.dg/reflect/serialize2.C
@@ -36,8 +36,7 @@ constexpr std::string
serialize (S s)
{
std::string result = " ";
-#if 0
- // TODO, this ICEs in tsubst_expr.
+#ifdef TEST_SERIALIZE3
impl::replicator <^^S::age, ^^S::name> >> [&] <auto m> {
#else
impl::replicator <^^Person::age, ^^Person::name> >> [&] <auto m> {
diff --git a/gcc/testsuite/g++.dg/reflect/serialize3.C
b/gcc/testsuite/g++.dg/reflect/serialize3.C
new file mode 100644
index 00000000000..13367b71572
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/serialize3.C
@@ -0,0 +1,5 @@
+// { dg-do run { target c++26 } }
+// { dg-additional-options "-freflection -O0" }
+
+#define TEST_SERIALIZE3
+#include "serialize2.C"
base-commit: 9c483886957cac7016dc404c2b6aab2ae94574a9
--
2.53.0