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);