[PATCH] c++: Fix up default initialization with consteval default ctor [PR96994]

Jakub Jelinek jakub@redhat.com
Tue Sep 15 07:57:06 GMT 2020


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  <jakub@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



More information about the Gcc-patches mailing list