Hi! The following testcase is miscompiled (in particular the a and i initialization). The problem is that build_special_member_call due to the immediate constructors (but not evaluated in constant expression mode) doesn't create a CALL_EXPR, but returns a TARGET_EXPR with CONSTRUCTOR as the initializer for it, and then expand_default_init just emits the returned statement, but this one doesn't have any side-effects and does nothing. There is an if to handle constexpr ctors which emits an INIT_EXPR but constexpr ctors still show up as CALL_EXPR and need to be manually evaluated to constant expressions (if possible).
The following patch fixes that, though I'm not sure about several things. One is that the earlier if also has expr == true_exp && in the condition, not sure if we want it in this case or not. Another is that for delegating constructors, we emit two separate calls and build_if_in_charge them together. Not sure if consteval could come into play in that case. Bootstrapped/regtested on x86_64-linux and i686-linux. 2020-09-15 Jakub Jelinek <ja...@redhat.com> PR c++/96994 * init.c (expand_default_init): If rval is TARGET_EXPR with TREE_CONSTANT TARGET_EXPR_INITIAL, emit INIT_EXPR. * g++.dg/cpp2a/consteval18.C: New test. --- gcc/cp/init.c.jj 2020-09-10 11:24:05.019805303 +0200 +++ gcc/cp/init.c 2020-09-14 15:06:59.467341241 +0200 @@ -1999,6 +1999,9 @@ expand_default_init (tree binfo, tree tr rval = build2 (INIT_EXPR, type, exp, e); } } + else if (TREE_CODE (rval) == TARGET_EXPR + && TREE_CONSTANT (TARGET_EXPR_INITIAL (rval))) + rval = build2 (INIT_EXPR, type, exp, rval); /* FIXME put back convert_to_void? */ if (TREE_SIDE_EFFECTS (rval)) --- gcc/testsuite/g++.dg/cpp2a/consteval18.C.jj 2020-09-14 15:12:50.036282784 +0200 +++ gcc/testsuite/g++.dg/cpp2a/consteval18.C 2020-09-14 15:12:42.834386644 +0200 @@ -0,0 +1,26 @@ +// PR c++/96994 +// { dg-do run { target c++20 } } + +struct A { consteval A () { i = 1; } consteval A (int x) : i (x) {} int i = 0; }; +struct B { constexpr B () { i = 1; } constexpr B (int x) : i (x) {} int i = 0; }; +A const a; +constexpr A b; +B const c; +A const constinit d; +A const e = 2; +constexpr A f = 3; +B const g = 4; +A const constinit h = 5; +A i; +B j; +A k = 6; +B l = 7; +static_assert (b.i == 1 && f.i == 3); + +int +main() +{ + if (a.i != 1 || c.i != 1 || d.i != 1 || e.i != 2 || g.i != 4 || h.i != 5 + || i.i != 1 || j.i != 1 || k.i != 6 || l.i != 7) + __builtin_abort (); +} Jakub