c++: ICE with -fno-elide-constructors and trivial fn [PR101073]
In constexpr-nsdmi3.C, with -fno-elide-constructors, we don't elide
the Y::Y(const Y&) call used to initialize o.c. So store_init_value
-> cxx_constant_init must constexpr-evaluate the call to Y::Y(const Y&)
in cxx_eval_call_expression. It's a trivial function, so we do the
"Shortcut trivial constructor/op=" code and rather than evaluating
the function, we just create an assignment
o.c = *(const struct Y &) (const struct Y *) &(&<PLACEHOLDER_EXPR struct X>)->b
which is a MODIFY_EXPR, so the preeval code in cxx_eval_store_expression
clears .ctor and .object, therefore we can't replace the PLACEHOLDER_EXPR
whereupon we crash at
/* A placeholder without a referent. We can get here when
checking whether NSDMIs are noexcept, or in massage_init_elt;
just say it's non-constant for now. */
gcc_assert (ctx->quiet);
The PLACEHOLDER_EXPR can also be on the LHS as in constexpr-nsdmi10.C.
I don't think we can do much here, but I noticed that the whole
trivial_fn_p (fun) block is only entered when -fno-elide-constructors.
This is true since GCC 9; it wasn't easy to bisect what changes made it
so, but r240845 is probably one of them. -fno-elide-constructors is an
option for experiments only so it's not clear to me why we'd still want
to shortcut trivial constructor/op=. I propose to remove the code and
add a checking assert to make sure we're not getting a trivial_fn_p
unless -fno-elide-constructors.
PR c++/101073
gcc/cp/ChangeLog:
* constexpr.cc (cxx_eval_call_expression): Replace shortcutting trivial
constructor/op= with a checking assert.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/constexpr-nsdmi3.C: New test.
* g++.dg/cpp1y/constexpr-nsdmi10.C: New test.