constexpr.c (cxx_eval_store_expression): Don't set CONSTRUCTOR_NO_IMPLICIT_ZERO if...
authorJason Merrill <jason@redhat.com>
Mon, 17 Aug 2015 18:41:59 +0000 (14:41 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 17 Aug 2015 18:41:59 +0000 (14:41 -0400)
* constexpr.c (cxx_eval_store_expression): Don't set
CONSTRUCTOR_NO_IMPLICIT_ZERO if we have an enclosing CONSTRUCTOR
without it.
(cxx_eval_array_reference): Check it.

From-SVN: r226948

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

index 595781cdb3ecf5bbb40e760c7793d88ee757ebfa..c6bd397748a00cf630052a3313ed05c3523eaa01 100644 (file)
@@ -1,5 +1,10 @@
 2015-08-17  Jason Merrill  <jason@redhat.com>
 
+       * constexpr.c (cxx_eval_store_expression): Don't set
+       CONSTRUCTOR_NO_IMPLICIT_ZERO if we have an enclosing CONSTRUCTOR
+       without it.
+       (cxx_eval_array_reference): Check it.
+
        * except.c (check_noexcept_r): Assert that fn is POINTER_TYPE_P.
 
 2015-08-14  Jason Merrill  <jason@redhat.com>
index 6048f0625934bba295d6a882a1d70cc1be01f6d6..35875a84361b2d86b46c04f4d745f78976fe5dcf 100644 (file)
@@ -1732,6 +1732,18 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
     {
       if (tree_int_cst_lt (index, array_type_nelts_top (TREE_TYPE (ary))))
        {
+         if (TREE_CODE (ary) == CONSTRUCTOR
+             && CONSTRUCTOR_NO_IMPLICIT_ZERO (ary))
+           {
+             /* 'ary' is part of the aggregate initializer we're currently
+                building; if there's no initializer for this element yet,
+                that's an error. */
+             if (!ctx->quiet)
+               error ("accessing uninitialized array element");
+             *non_constant_p = true;
+             return 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);
@@ -2674,13 +2686,17 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
       return t;
     }
   type = TREE_TYPE (object);
+  bool no_zero_init = true;
   while (!refs->is_empty())
     {
       if (*valp == NULL_TREE)
        {
          *valp = build_constructor (type, NULL);
-         CONSTRUCTOR_NO_IMPLICIT_ZERO (*valp) = true;
+         CONSTRUCTOR_NO_IMPLICIT_ZERO (*valp) = no_zero_init;
        }
+      /* If the value of object is already zero-initialized, any new ctors for
+        subobjects will also be zero-initialized.  */
+      no_zero_init = CONSTRUCTOR_NO_IMPLICIT_ZERO (*valp);
 
       constructor_elt ce;
       type = refs->pop();
@@ -2708,7 +2724,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
       new_ctx.ctor = build_constructor (type, NULL);
       if (*valp == NULL_TREE)
        *valp = new_ctx.ctor;
-      CONSTRUCTOR_NO_IMPLICIT_ZERO (new_ctx.ctor) = true;
+      CONSTRUCTOR_NO_IMPLICIT_ZERO (new_ctx.ctor) = no_zero_init;
       new_ctx.object = target;
     }
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array12.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array12.C
new file mode 100644 (file)
index 0000000..347ee54
--- /dev/null
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++11 } }
+
+struct A { int ar[3]; };
+int main()
+{
+  constexpr A a1 = { 0, a1.ar[0] };
+  constexpr A a2 = { a2.ar[0] };       // { dg-error "uninitialized" }
+}