https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126510

            Bug ID: 126510
           Summary: [c++26] constexpr dynamic_cast wrongly returns null
                    when operand is a virtual base subobject
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: egas at gcc dot gnu.org
            Blocks: 55004
  Target Milestone: ---

Since P3533R2 (PR120777) allows virtual bases in constant evaluation,
cxx_eval_dynamic_cast_fn can now be reached with hierarchies it doesn't
handle, and returns null where the runtime __dynamic_cast succeeds.

```cpp
struct S { int s; constexpr virtual ~S () {} };
struct C : virtual S { int c; };
struct MD : private C { int d; };

constexpr bool f ()
{
  MD obj;
  S *s = (S *) (C *) &obj;
  C *c = dynamic_cast<C *> (s);
  return c != nullptr && c == (C *) &obj;
}

static_assert (f ()); // fails, should succeed
```

The cast should succeed by [expr.dynamic.cast]/9.1: s points to a public base
subobject (S) of a C object, and exactly one C derives from that S. The
private C -> MD edge only matters for /9.2. The runtime agrees with this.

basically, we need to evaluate the access from C -> S, not from MD -> C, but
the implementation does the latter.

clause 1 probably needs to find the target binfo directly instead of walking
fields, then reuse clause 2's existing convert_to_base_statically tail (which
already handles virtual bases). Restricting the new search to only targeting
virtual-base operands would be enough, since the existing walk is fine
otherwise.


Referenced Bugs:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55004
[Bug 55004] [meta-bug] constexpr issues

Reply via email to