On 7/24/26 6:48 PM, Odysseas Georgoudis wrote:
This patch adjusts successful scalar virtual-call results to the static
call type after caching the underlying function result.  The cache
therefore retains the final overrider's declared result type for direct
calls.
+  /* A virtual call with a covariant return type can evaluate the final
+     overrider directly, whose result has its declared type rather than
+     the static type of the call.  Adjust after caching so a direct call
+     can reuse the result with its original type.  */
+  if (!*non_constant_p
+      && !*overflow_p
+      && !*jump_target
+      && DECL_VIRTUAL_P (fun)
+      && result != void_node
+      && scalarish_type_p (TREE_TYPE (t))
+      && !same_type_ignoring_top_level_qualifiers_p
+          (TREE_TYPE (result), TREE_TYPE (t)))
+    result = adjust_temp_type (TREE_TYPE (t), result);

What if the base is at a non-zero offset from the derived type?
If I change your testcase to add another base, i.e.

struct B
{
  virtual constexpr B *clone(bool null)
  {
    return null ? nullptr : this;
  }
};

struct C
{
  virtual void dummy () { }
};

struct D : C, B
{
  constexpr D *clone(bool null) override
  {
    return null ? nullptr : this;
  }
};

then we still hit the same ICE.

Jason

Reply via email to