Hi! The comment in OBJ_TYPE_REF handling code correctly says that we are looking for x.D.2103.D.2094, but it is important that x is not an INDIRECT_REF or something similar as in the following testcase - we can't really devirtualize in that case because we really don't know what it points to. The following patch ensures that the argument got evaluated to address of some field of (ultimately) a decl, which is all we should get during valid constexpr evaluation.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2018-11-20 Jakub Jelinek <ja...@redhat.com> PR c++/88110 * constexpr.c (cxx_eval_constant_expression) <case OBJ_TYPE_REF>: Punt if get_base_address of ADDR_EXPR operand is not a DECL_P. * g++.dg/cpp2a/constexpr-virtual13.C: New test. --- gcc/cp/constexpr.c.jj 2018-11-19 14:24:49.000000000 +0100 +++ gcc/cp/constexpr.c 2018-11-20 15:03:26.968152935 +0100 @@ -4815,7 +4815,8 @@ cxx_eval_constant_expression (const cons obj = cxx_eval_constant_expression (ctx, obj, lval, non_constant_p, overflow_p); /* We expect something in the form of &x.D.2103.D.2094; get x. */ - if (TREE_CODE (obj) != ADDR_EXPR) + if (TREE_CODE (obj) != ADDR_EXPR + || !DECL_P (get_base_address (TREE_OPERAND (obj, 0)))) { if (!ctx->quiet) error_at (cp_expr_loc_or_loc (t, input_location), --- gcc/testsuite/g++.dg/cpp2a/constexpr-virtual13.C.jj 2018-11-20 15:07:17.558386765 +0100 +++ gcc/testsuite/g++.dg/cpp2a/constexpr-virtual13.C 2018-11-20 15:05:30.188140420 +0100 @@ -0,0 +1,20 @@ +// PR c++/88110 +// { dg-do compile } + +struct A { + virtual int foo () const = 0; +}; +struct B { + virtual int bar () const = 0; + virtual int baz () const = 0; +}; +struct C : public A { }; +struct D : public C { }; +struct E : public D, public B { }; + +void +qux (const E *x) +{ + if (x->baz ()) + ; +} Jakub