On Tue, Jun 24, 2025 at 11:57:01AM -0400, Jason Merrill wrote:
> > The two other errors on the testcase are expectedly gone with C++26,
> > but the last one remains.  The problem is that when parsing nm3.a
> > inside of mutable_subobjects()::A::f()
> > build_class_member_access_expr calls build_base_path which calls
> > cp_build_addr_expr and that makes nm3 odr-used.  I must say I have
> > no idea whether nm3 ought to be odr-used or not just because of nm3.a
> > use and if not, how that should be changed.
> 
> build_simple_base_path is how we avoid this odr-use; seems we also need to
> use it early in the case of (v_binfo && !virtual_access).

--- gcc/cp/class.cc.jj  2025-06-18 17:24:03.973867379 +0200
+++ gcc/cp/class.cc     2025-06-24 20:11:21.728169508 +0200
@@ -349,7 +349,11 @@ build_base_path (enum tree_code code,
 
   /* For a non-pointer simple base reference, express it as a COMPONENT_REF
      without taking its address (and so causing lambda capture, 91933).  */
-  if (code == PLUS_EXPR && !v_binfo && !want_pointer && !has_empty && !uneval)
+  if (code == PLUS_EXPR
+      && !want_pointer
+      && !has_empty
+      && !uneval
+      && (!v_binfo || resolves_to_fixed_type_p (expr) > 0))
     return build_simple_base_path (expr, binfo);
 
   if (!want_pointer)

seems to fix that and doesn't regress anything else in make check-g++.
I guess it can be handled separately from the rest.
Or do you prefer some other way to avoid calling resolves_to_fixed_type_p
twice in some cases?

> > works at runtime.  In the patch I've adjusted the function
> > comment of cxx_eval_dynamic_cast_fn because with virtual bases
> > I believe hint -1 might be possible, though I'm afraid I don't
> 
> Yes, we would get -1 for dynamic_cast from B to A.

The routine then has some
  /* Given dynamic_cast<T>(v),

     [expr.dynamic.cast] If C is the class type to which T points or refers,
     the runtime check logically executes as follows:

     If, in the most derived object pointed (referred) to by v, v points
     (refers) to a public base class subobject of a C object, and if only
     one object of type C is derived from the subobject pointed (referred)
     to by v the result points (refers) to that C object.

     In this case, HINT >= 0 or -3.  */
  if (hint >= 0 || hint == -3)
Should that include the hint == -1 case too (so effectively if (hint != -2)
or is -1 not relevant to that block.

> > know enough about dynamic_cast and cxx_eval_dynamic_cast_fn
> > to figure out what needs to change there.  It is hint -2 that
> > fails, not hint -1.
> 
> Yes, this is a -2 case because C does not derive from B.
> 
> How does cxx_eval_dynamic_cast_fn fail in this case?  From looking at the
> function it seems like it ought to work.

I'll study it in detail tomorrow.

        Jakub

Reply via email to