On 6/24/25 7:22 AM, Jakub Jelinek wrote:
Hi!

The following patch attempts to implement the C++26
P3533R2 - constexpr virtual inheritance
paper.
The changes include not rejecting it for C++26, tweaking the
error wording to show that it is valid in C++26, adjusting
synthesized_method_walk not to make synthetized cdtors non-constexpr
just because of virtual base classes in C++26 and various tweaks in
constexpr.cc so that it can deal with the expressions used for
virtual base member accesses or cdtor calls which need __in_chrg
and/or __vtt_parm arguments to be passed in some cases implicitly when
they aren't passed explicitly.

There are two places where I'm not sure what to do:

1) one can be seen on the constexpr-ice21.C testcase:
struct NoMut1 { int a, b; };
struct NoMut3 : virtual NoMut1 { constexpr NoMut3(int a, int b) : NoMut1{a, b} 
{} };
void mutable_subobjects() {
   constexpr NoMut3 nm3 = {1, 2};
   struct A {
     void f() {
       static_assert(nm3.a == 1, ""); // ERROR here: "local variable"
     }
   };
}
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).

Plus whether the fact
if nm3.a is odr-use or not is somehow affected by the (so far unimplemented)
part of P2686R4 paper.

2) another one can be seen on the constexpr-dynamic10.C testcase
struct C { virtual void a(); };
struct B { virtual void b(); };
struct A : virtual B, C { virtual void c(); };
constexpr A a;
constexpr bool b1 = (dynamic_cast<C&>((B&)a), false);   // ERROR here "reference 
'dynamic_cast' failed"
I think the error is incorrect here, because
struct C { virtual void a(); };
struct B { virtual void b(); };
struct A : virtual B, C { virtual void c(); };
A a;
bool b1 = (dynamic_cast<C&>((B&)a), false);
int
main ()
{
   C &c = dynamic_cast<C&>((B&)a);
   C &c2 = dynamic_cast<C&>(a);
}
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.

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.

Jason

Reply via email to