[gcc(refs/users/marxin/heads/marxin-gcc-benchmark-branch)] c++: Fix constexpr vs. omitted aggregate init.

Martin Liska marxin@gcc.gnu.org
Mon Mar 30 10:46:33 GMT 2020


https://gcc.gnu.org/g:0712ea6313bc44f9ae8feb235c1b02c92cdd0527

commit 0712ea6313bc44f9ae8feb235c1b02c92cdd0527
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Feb 4 15:54:17 2020 -0500

    c++: Fix constexpr vs. omitted aggregate init.
    
    Value-initialization is importantly different from {}-initialization for
    this testcase, where the former calls the deleted S constructor and the
    latter initializes S happily.
    
            PR c++/90951
            * constexpr.c (cxx_eval_array_reference): {}-initialize missing
            elements instead of value-initializing them.

Diff:
---
 gcc/cp/ChangeLog                               |  4 ++++
 gcc/cp/constexpr.c                             | 12 ++++++++++--
 gcc/testsuite/g++.dg/cpp0x/constexpr-array24.C | 10 ++++++++++
 3 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 53f414fc453..956e94b2337 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,9 @@
 2020-02-04  Jason Merrill  <jason@redhat.com>
 
+	PR c++/90951
+	* constexpr.c (cxx_eval_array_reference): {}-initialize missing
+	elements instead of value-initializing them.
+
 	PR c++/86917
 	* init.c (perform_member_init): Simplify.
 	* constexpr.c (cx_check_missing_mem_inits): Allow uninitialized
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index c35ec5acc97..8a02c6e0713 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -3324,8 +3324,16 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
     }
 
   /* If it's within the array bounds but doesn't have an explicit
-     initializer, it's value-initialized.  */
-  tree val = build_value_init (elem_type, tf_warning_or_error);
+     initializer, it's initialized from {}.  But use build_value_init
+     directly for non-aggregates to avoid creating a garbage CONSTRUCTOR.  */
+  tree val;
+  if (CP_AGGREGATE_TYPE_P (elem_type))
+    {
+      tree empty_ctor = build_constructor (init_list_type_node, NULL);
+      val = digest_init (elem_type, empty_ctor, tf_warning_or_error);
+    }
+  else
+    val = build_value_init (elem_type, tf_warning_or_error);
   return cxx_eval_constant_expression (ctx, val, lval, non_constant_p,
 				       overflow_p);
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array24.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array24.C
new file mode 100644
index 00000000000..538969830ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array24.C
@@ -0,0 +1,10 @@
+// PR c++/90951
+// { dg-do compile { target c++11 } }
+
+#define assert(expr) static_assert (expr, #expr)
+
+struct S { const char a[2]; };
+
+constexpr struct S a[1][1][1] = { };
+
+assert ('\0' == *a[0][0][0].a);


More information about the Gcc-cvs mailing list