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.
commit 5d38d5961241cdca385f95199c3c77a9aa5778a4
Author: Jason Merrill <ja...@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);

Reply via email to