Here, when we look at the value of an empty base, we would first make sure that the complete object is constant. But we were in the middle of initializing one of the fields of the complete object, so the corresponding CONSTRUCTOR value was NULL, leading to a crash when trying to determine if it's constant.
There are two issues here: 1) We shouldn't crash. We should treat a field under initialization as non-constant. 2) We shouldn't require that the complete object be constant. It's fine to use the value of a fully constructed subobject while initializing another member. Tested x86_64-pc-linux-gnu, applying to trunk.
commit 5d650f368849196d53af19decdfcc5217ca0301b Author: Jason Merrill <ja...@redhat.com> Date: Sun Apr 9 00:49:10 2017 -0400 PR c++/80294 - ICE with constexpr and inheritance. * constexpr.c (reduced_constant_expression_p): A null constructor element is non-constant. (cxx_eval_indirect_ref): Don't VERIFY_CONSTANT before returning an empty base. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 3ca3560..9dde4a4 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1716,8 +1716,13 @@ reduced_constant_expression_p (tree t) /* And we need to handle PTRMEM_CST wrapped in a CONSTRUCTOR. */ tree elt; unsigned HOST_WIDE_INT idx; FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (t), idx, elt) - if (!reduced_constant_expression_p (elt)) - return false; + { + if (!elt) + /* We're in the middle of initializing this element. */ + return false; + if (!reduced_constant_expression_p (elt)) + return false; + } return true; default: @@ -3153,12 +3158,10 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, if (*non_constant_p) return t; - /* If we're pulling out the value of an empty base, make sure - that the whole object is constant and then return an empty + /* If we're pulling out the value of an empty base, just return an empty CONSTRUCTOR. */ if (empty_base && !lval) { - VERIFY_CONSTANT (r); r = build_constructor (TREE_TYPE (t), NULL); TREE_CONSTANT (r) = true; } diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-empty3.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-empty3.C new file mode 100644 index 0000000..37e4a53 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-empty3.C @@ -0,0 +1,14 @@ +// PR c++/80294 +// { dg-do compile { target c++14 } } +// { dg-final { scan-assembler-not "static_init" } } + +struct A { + constexpr int f() { A a = *this; return 42; } +}; +struct B: A +{ + int i; + constexpr B(): i(f()) {} +}; + +B b;