diff mbox

C++ PATCH for c++/64899 (constexpr default-initialized array)

Message ID 54D90759.9010204@redhat.com
State New
Headers show

Commit Message

Jason Merrill Feb. 9, 2015, 7:15 p.m. UTC
build_vec_init works to evaluate constant values for elements of a 
vector initializer, but it wasn't working properly for a 
default-initialized array with a constexpr default constructor.  First I 
needed to add that case to the try_const condition; then I needed to 
change tho form of the initialization because when building the 
constructor call to refer to *iterator, constexpr evaluation saw that 
'iterator' isn't constant and gave up.  To completely solve this for 
cases where we refer to the address of the object or the value of a 
previous element we should hand the whole initialization loop to 
constexpr evaluation, but just using the value-init path fixes this 
testcase.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit 5d38d5961241cdca385f95199c3c77a9aa5778a4
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Feb 4 07:45:02 2015 -0500

    	PR c++/64899
    	* init.c (build_vec_init): Handle default-initialized array with
    	constexpr default constructor.

diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index e600472..0274663 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -3539,7 +3539,9 @@  build_vec_init (tree base, tree maxindex, tree init,
   /* Should we try to create a constant initializer?  */
   bool try_const = (TREE_CODE (atype) == ARRAY_TYPE
 		    && TREE_CONSTANT (maxindex)
-		    && init && TREE_CODE (init) == CONSTRUCTOR
+		    && (init ? TREE_CODE (init) == CONSTRUCTOR
+			: (type_has_constexpr_default_constructor
+			   (inner_elt_type)))
 		    && (literal_type_p (inner_elt_type)
 			|| TYPE_HAS_CONSTEXPR_CTOR (inner_elt_type)));
   vec<constructor_elt, va_gc> *const_vec = NULL;
@@ -3677,6 +3679,12 @@  build_vec_init (tree base, tree maxindex, tree init,
 
      We do need to keep going if we're copying an array.  */
 
+  if (try_const && !init)
+    /* With a constexpr default constructor, which we checked for when
+       setting try_const above, default-initialization is equivalent to
+       value-initialization, and build_value_init gives us something more
+       friendly to maybe_constant_init.  */
+    explicit_value_init_p = true;
   if (from_array
       || ((type_build_ctor_call (type) || init || explicit_value_init_p)
 	  && ! (tree_fits_shwi_p (maxindex)
@@ -3781,6 +3789,7 @@  build_vec_init (tree base, tree maxindex, tree init,
 
       if (try_const)
 	{
+	  /* FIXME refs to earlier elts */
 	  tree e = maybe_constant_init (elt_init);
 	  if (reduced_constant_expression_p (e))
 	    {
@@ -3795,6 +3804,8 @@  build_vec_init (tree base, tree maxindex, tree init,
 	      saw_non_const = true;
 	      if (do_static_init)
 		e = build_zero_init (TREE_TYPE (e), NULL_TREE, true);
+	      else
+		e = NULL_TREE;
 	    }
 
 	  if (e)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array10.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array10.C
new file mode 100644
index 0000000..f7aaa4b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array10.C
@@ -0,0 +1,12 @@ 
+// PR c++/64899
+// { dg-do compile { target c++11 } }
+
+struct S
+{
+  int i;
+  constexpr S (): i(42) {}
+};
+
+constexpr S sa[2];
+#define SA(X) static_assert((X),#X)
+SA(sa[1].i == 42);