c++: Fix ICE from verify_ctor_sanity [PR98295]
authorPatrick Palka <ppalka@redhat.com>
Mon, 1 Feb 2021 15:27:45 +0000 (10:27 -0500)
committerPatrick Palka <ppalka@redhat.com>
Mon, 1 Feb 2021 15:27:45 +0000 (10:27 -0500)
In this testcase we're crashing during constexpr evaluation of the
ARRAY_REF b[0] as part of evaluation of the lambda's by-copy capture of b
(which is encoded as a VEC_INIT_EXPR<b>).  Since A's constexpr default
constructor is not yet defined, b's initialization is not actually
constant, but because A is an empty type, evaluation of b from
cxx_eval_array_ref is successful and yields an empty CONSTRUCTOR.
And since this CONSTRUCTOR is empty, we {}-initialize the desired array
element, and end up crashing from verify_ctor_sanity during evaluation
of this initializer because we updated new_ctx.ctor without updating
new_ctx.object: the former now has type A[3] and the latter is still the
target of a TARGET_EXPR for b[0][0] created from cxx_eval_vec_init
(and so has type A).

This patch fixes this by setting new_ctx.object appropriately at the
same time that we set new_ctx.ctor from cxx_eval_array_reference.

gcc/cp/ChangeLog:

PR c++/98295
* constexpr.c (cxx_eval_array_reference): Also set
new_ctx.object when setting new_ctx.ctor.

gcc/testsuite/ChangeLog:

PR c++/98295
* g++.dg/cpp0x/constexpr-98295.C: New test.

gcc/cp/constexpr.c
gcc/testsuite/g++.dg/cpp0x/constexpr-98295.C [new file with mode: 0644]

index baa97a0..1dbc2db 100644 (file)
@@ -3760,6 +3760,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
       tree empty_ctor = build_constructor (init_list_type_node, NULL);
       val = digest_init (elem_type, empty_ctor, tf_warning_or_error);
       new_ctx = *ctx;
+      new_ctx.object = t;
       new_ctx.ctor = build_constructor (elem_type, NULL);
       ctx = &new_ctx;
     }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-98295.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-98295.C
new file mode 100644 (file)
index 0000000..930bd5a
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/98295
+// { dg-do compile { target c++11 } }
+
+struct A { constexpr A(); };
+
+void f() {
+  A b[2][3];
+  [b] { };
+}
+
+constexpr A::A() {}