On 11/27/19 6:38 PM, Jakub Jelinek wrote:
Hi!

The OBJ_TYPE_REF constexpr handling looks through DECL_FIELD_IS_BASE
COMPONENT_REFs to find the actual object on which the method is called,
but as the following testcase shows, we need to do the similar thing also
for the argument passed as this, because cxx_eval_indirect_ref otherwise
fails to fold it.  It can handle going from derived to base, not not vice
versa.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

2019-11-27  Jakub Jelinek  <ja...@redhat.com>

        PR c++/92695
        * constexpr.c (cxx_bind_parameters_in_call): For virtual calls,
        adjust the first argument to point to the derived object rather
        than its base.

        * g++.dg/cpp2a/constexpr-virtual14.C: New test.

--- gcc/cp/constexpr.c.jj       2019-11-27 17:26:57.229014008 +0100
+++ gcc/cp/constexpr.c  2019-11-27 17:53:37.477566346 +0100
@@ -1441,6 +1441,24 @@ cxx_bind_parameters_in_call (const const
            arg = adjust_temp_type (type, arg);
          if (!TREE_CONSTANT (arg))
            *non_constant_args = true;
+         /* For virtual calls, adjust the this argument, so that it is
+            the object on which the method is called, rather than
+            one of its bases.  */
+         if (i == 0 && DECL_VIRTUAL_P (fun))
+           {
+             tree addr = arg;
+             STRIP_NOPS (addr);
+             if (TREE_CODE (addr) == ADDR_EXPR)
+               {
+                 tree obj = TREE_OPERAND (addr, 0);
+                 while (TREE_CODE (obj) == COMPONENT_REF
+                        && DECL_FIELD_IS_BASE (TREE_OPERAND (obj, 1)))
+                   obj = TREE_OPERAND (obj, 0);

Shouldn't this loop stop when we reach DECL_CONTEXT (fun)?

Relatedly, I notice that the OBJ_TYPE_REF code breaks with multiple inheritance: Adding a virtual function to Y in constexpr-virtual6.C leads to

> wa.ii:26:22: error: non-constant condition for static assertion
>    26 | static_assert(r2.f() == &r2);
>       |               ~~~~~~~^~~~~~
> wa.ii:26:19: error: call to non-'constexpr' function 'virtual void Y::dummy()'
>    26 | static_assert(r2.f() == &r2);
>       |               ~~~~^~
> wa.ii:12:16: note: 'virtual void Y::dummy()' declared here
>    12 |   virtual void dummy () { }

Reply via email to