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