On 10/6/26 5:55 PM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/16?

OK.

-- >8 --
We ICE in perform_or_defer_access_check on a null binfo of the object
type here:

   struct A { int m{}; };
   template <int> struct E : A {};

   template <class W>
   int get(W *o) {
       return o->[:^^A::m:];
   }
   int main() { return get((E<2> *)0); }

The problem is that in tsubst_expr we call finish_non_static_data_member
on any FIELD_DECL, but when the FIELD_DECL is coming from o->[:^^A::m:],
the object's type may not have been instantiated yet.  I think we should
just send COMPONENT_REFs with a splice expression down the
finish_class_member_access_expr path which has:

   if (!currently_open_class (object_type)
       && !complete_type_or_maybe_complain (object_type, object, complain))
     return error_mark_node;

so it will instantiate the class and create a TREE_BINFO.

With that, the dependent_splice_p check should be unreachable.

        PR c++/126794

gcc/cp/ChangeLog:

        * pt.cc (tsubst_expr) <case COMPONENT_REF>: Don't call
        finish_non_static_data_member on a FIELD_DECL of a COMPONENT_REF
        when COMPONENT_REF_SPLICE_P is set.  Don't check
        dependent_splice_p in an assert.

gcc/testsuite/ChangeLog:

        * g++.dg/reflect/member16.C: Adjust dg-error.
        * g++.dg/reflect/member25.C: New test.
---
  gcc/cp/pt.cc                            |  8 ++--
  gcc/testsuite/g++.dg/reflect/member16.C |  4 +-
  gcc/testsuite/g++.dg/reflect/member25.C | 61 +++++++++++++++++++++++++
  3 files changed, 68 insertions(+), 5 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/reflect/member25.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index c7f5d55b14f..d68cf5aeb23 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -22905,13 +22905,15 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
            r = build_ptrmemfunc_access_expr (object, DECL_NAME (member));
            RETURN (r);
          }
-       else if (TREE_CODE (member) == FIELD_DECL)
+       /* For obj->[:^^A::m:], go down the finish_class_member_access_expr
+          path because object's type may not be instantiated yet.  */
+       else if (TREE_CODE (member) == FIELD_DECL
+                && !COMPONENT_REF_SPLICE_P (t))
          {
            /* Assume access of this FIELD_DECL has already been checked; we
               don't recheck it to avoid bogus access errors when substituting
               a reduced constant initializer (97740).  */
-           gcc_checking_assert (TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL
-                                || dependent_splice_p (TREE_OPERAND (t, 1)));
+           gcc_checking_assert (TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL);
            push_deferring_access_checks (dk_deferred);
            r = finish_non_static_data_member (member, object, NULL_TREE,
                                               complain);
diff --git a/gcc/testsuite/g++.dg/reflect/member16.C 
b/gcc/testsuite/g++.dg/reflect/member16.C
index 2679cdc6714..473363d72a4 100644
--- a/gcc/testsuite/g++.dg/reflect/member16.C
+++ b/gcc/testsuite/g++.dg/reflect/member16.C
@@ -46,7 +46,7 @@ bar (S &c, T &d, U &g, V &h)
    d.[: ^^B::b :] = 5;                 // { dg-error "'B' is an ambiguous base of 
'D'" }
    d.[: ^^C::c :] = 6;
    d.[: ^^D::d :] = 7;
-  d.[: ^^I::i :] = 8;                  // { dg-error "invalid use of non-static 
data member 'I::i'" }
+  d.[: ^^I::i :] = 8;                  // { dg-error "'I' is not a base of 
'D'" }
    g.[: ^^E::_ :] = 1;
    g.[: ^^F::_ :] = 2;
    g.[: ^^G::_ :] = 3;
@@ -54,7 +54,7 @@ bar (S &c, T &d, U &g, V &h)
    h.[: ^^F::_ :] = 5;                 // { dg-error "'F' is an ambiguous base of 
'H'" }
    h.[: ^^G::_ :] = 6;
    h.[: ^^H::_ :] = 7;
-  h.[: ^^J::_ :] = 8;                  // { dg-error "invalid use of non-static 
data member 'J::_'" }
+  h.[: ^^J::_ :] = 8;                  // { dg-error "'J' is not a base of 
'H'" }
  }
void
diff --git a/gcc/testsuite/g++.dg/reflect/member25.C 
b/gcc/testsuite/g++.dg/reflect/member25.C
new file mode 100644
index 00000000000..4db05cebdd3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/member25.C
@@ -0,0 +1,61 @@
+// PR c++/126794
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+template<class, class> struct same_type;
+template<class T> struct same_type<T, T> {};
+
+struct A { int m{}; };
+template<int> struct E : A {};
+
+int
+f1 ()
+{
+  E<2> *o = 0;
+  return o->[:^^A::m:];
+}
+
+template<class W>
+int
+get (W *o)
+{
+  return o->[:^^A::m:];
+}
+
+int
+f2 ()
+{
+  return get ((E<2> *) 0);
+}
+
+template<class W>
+void
+f3 (W *o)
+{
+  same_type<decltype (o->[:^^A::m:]), int>();
+  same_type<decltype ((o->[:^^A::m:])), int &>();
+}
+template void f3 (E<3> *);
+
+template<int> struct F;
+
+template<class W>
+int
+f4 (W *o)
+{
+  return o->[:^^A::m:];   // { dg-error "invalid use of incomplete type" }
+}
+
+int
+f5 ()
+{
+  return f4 ((F<0> *) 0);
+}
+
+template<class W>
+int
+f6 (W &o)
+{
+  return o.[:^^A::m:];
+}
+template int f6 (E<4> &);

base-commit: 1b961bf9d7e76de9a36f93d8749dbe7fae302246

Reply via email to