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.