Hi! ARRAY_REF is a handled component, so when a virtual call is on an array element (or some component thereof), the loop to look through handled components will look through the ARRAY_REFs too and then TREE_TYPE (obj) might be an ARRAY_TYPE. The code wants to look at the class type instead though.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2018-09-25 Jakub Jelinek <ja...@redhat.com> PR c++/87398 * constexpr.c (cxx_eval_constant_expression) <case OBJ_TYPE_REF>: Use strip_array_types before checking TYPE_BINFO. * g++.dg/other/pr87398.C: New test. * g++.dg/cpp2a/constexpr-virtual10.C: New test. --- gcc/cp/constexpr.c.jj 2018-09-24 10:36:53.687031261 +0200 +++ gcc/cp/constexpr.c 2018-09-24 11:01:34.035268597 +0200 @@ -4814,7 +4814,7 @@ cxx_eval_constant_expression (const cons obj = TREE_OPERAND (obj, 0); while (handled_component_p (obj)) obj = TREE_OPERAND (obj, 0); - tree objtype = TREE_TYPE (obj); + tree objtype = strip_array_types (TREE_TYPE (obj)); /* Find the function decl in the virtual functions list. TOKEN is the DECL_VINDEX that says which function we're looking for. */ tree virtuals = BINFO_VIRTUALS (TYPE_BINFO (objtype)); --- gcc/testsuite/g++.dg/other/pr87398.C.jj 2018-09-24 10:53:41.605170048 +0200 +++ gcc/testsuite/g++.dg/other/pr87398.C 2018-09-24 10:53:14.642621001 +0200 @@ -0,0 +1,12 @@ +// PR c++/87398 +// { dg-do compile } + +struct A { virtual int foo (); }; + +int +bar (int x) +{ + A e[5][2]; + int f = e[4][x].foo (); + return f; +} --- gcc/testsuite/g++.dg/cpp2a/constexpr-virtual10.C.jj 2018-09-24 10:56:15.604594387 +0200 +++ gcc/testsuite/g++.dg/cpp2a/constexpr-virtual10.C 2018-09-24 10:56:54.882937453 +0200 @@ -0,0 +1,18 @@ +// P1064R0 +// { dg-do compile } +// { dg-options "-std=c++2a" } + +struct X +{ + constexpr virtual int f() const { return 1; }; +}; + +struct Y : public X +{ + constexpr virtual int f() const { return 2; }; +}; + +constexpr X a[2][1][3]; +constexpr Y b[3][12]; +static_assert (a[1][0][1].f() == 1); +static_assert (b[2][11].f() == 2); Jakub