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

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2019-11-27
                 CC|                            |jakub at gcc dot gnu.org,
                   |                            |mpolacek at gcc dot gnu.org
     Ever confirmed|0                           |1

--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Doesn't have to be an array,
struct A {
  constexpr virtual int get () = 0;
  constexpr virtual int set (A *o) = 0;
};
struct B : A {
  constexpr int get () override { return 10; }
  constexpr int set (A *o) override { a = o; return 20; }
  A *a{};
};
constexpr auto addressof = [] (A &n) { return &n; };
struct Foo {
  B b;
  A *c { addressof (b) };
  constexpr int add () { return c->set (addressof (b)); }
};
constexpr int get () { Foo f; return f.add (); }
constexpr auto a = get ();
static_assert (a == 20);
is rejected too.

I think the problem is that the r264408 testcase coverage doesn't try to
dereference this arguments of the virtual methods, which is what happens in
this testcase (the store to this->a in B::set(A *)).
The OBJ_TYPE_REF handling in cxx_eval_constant_expression has:
        obj = TREE_OPERAND (obj, 0);
        while (TREE_CODE (obj) == COMPONENT_REF
               && DECL_FIELD_IS_BASE (TREE_OPERAND (obj, 1)))
          obj = TREE_OPERAND (obj, 0);
but something similar isn't done in cxx_eval_indirect_ref and I think generally
shouldn't be done there, it is (is it?) only the special case of virtual
method's first argument.  So, I'd say this DECL_FIELD_IS_BASE handling should
be done in cxx_eval_call_expression.

Reply via email to