PR c++/79130 - decomposition and direct-initialization
authorJason Merrill <jason@redhat.com>
Thu, 19 Jan 2017 14:37:51 +0000 (09:37 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 19 Jan 2017 14:37:51 +0000 (09:37 -0500)
* init.c (build_aggr_init): Communicate direct-initialization to
build_vec_init.
(build_vec_init): Check for array copy sooner.
* parser.c (cp_parser_decomposition_declaration): Remove call to
build_x_compound_expr_from_list.

From-SVN: r244635

gcc/cp/ChangeLog
gcc/cp/init.c
gcc/cp/parser.c
gcc/testsuite/g++.dg/cpp1z/decomp6.C

index f8377e25b4ce59b9d634d5c121b85ba42a937208..5b8eb7c891af409f816f08f0b623994b0e19030d 100644 (file)
@@ -1,3 +1,12 @@
+2017-01-19  Jason Merrill  <jason@redhat.com>
+
+       PR c++/79130 - decomposition and direct-initialization
+       * init.c (build_aggr_init): Communicate direct-initialization to
+       build_vec_init.
+       (build_vec_init): Check for array copy sooner.
+       * parser.c (cp_parser_decomposition_declaration): Remove call to
+       build_x_compound_expr_from_list.
+
 2017-01-18  Jason Merrill  <jason@redhat.com>
 
        PR c++/68666 - member variable template-id
index 8f68c88b38af5b64707a44fbb3d7d8425817ceb5..15388b1426440a6b3093e0b238a26093fede28ce 100644 (file)
@@ -1574,20 +1574,24 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
   TREE_READONLY (exp) = 0;
   TREE_THIS_VOLATILE (exp) = 0;
 
-  if (init && init != void_type_node
-      && TREE_CODE (init) != TREE_LIST
-      && !(TREE_CODE (init) == TARGET_EXPR
-          && TARGET_EXPR_DIRECT_INIT_P (init))
-      && !DIRECT_LIST_INIT_P (init))
-    flags |= LOOKUP_ONLYCONVERTING;
-
   if (TREE_CODE (type) == ARRAY_TYPE)
     {
       tree itype = init ? TREE_TYPE (init) : NULL_TREE;
       int from_array = 0;
 
       if (VAR_P (exp) && DECL_DECOMPOSITION_P (exp))
-       from_array = 1;
+       {
+         from_array = 1;
+         if (init && DECL_P (init)
+             && !(flags & LOOKUP_ONLYCONVERTING))
+           {
+             /* Wrap the initializer in a CONSTRUCTOR so that build_vec_init
+                recognizes it as direct-initialization.  */
+             init = build_constructor_single (init_list_type_node,
+                                              NULL_TREE, init);
+             CONSTRUCTOR_IS_DIRECT_INIT (init) = true;
+           }
+       }
       else
        {
          /* An array may not be initialized use the parenthesized
@@ -1621,6 +1625,13 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
       return stmt_expr;
     }
 
+  if (init && init != void_type_node
+      && TREE_CODE (init) != TREE_LIST
+      && !(TREE_CODE (init) == TARGET_EXPR
+          && TARGET_EXPR_DIRECT_INIT_P (init))
+      && !DIRECT_LIST_INIT_P (init))
+    flags |= LOOKUP_ONLYCONVERTING;
+
   if ((VAR_P (exp) || TREE_CODE (exp) == PARM_DECL)
       && !lookup_attribute ("warn_unused", TYPE_ATTRIBUTES (type)))
     /* Just know that we've seen something for this node.  */
@@ -3825,6 +3836,18 @@ build_vec_init (tree base, tree maxindex, tree init,
       && from_array != 2)
     init = TARGET_EXPR_INITIAL (init);
 
+  bool direct_init = false;
+  if (from_array && init && BRACE_ENCLOSED_INITIALIZER_P (init)
+      && CONSTRUCTOR_NELTS (init) == 1)
+    {
+      tree elt = CONSTRUCTOR_ELT (init, 0)->value;
+      if (TREE_CODE (TREE_TYPE (elt)) == ARRAY_TYPE)
+       {
+         direct_init = DIRECT_LIST_INIT_P (init);
+         init = elt;
+       }
+    }
+
   /* If we have a braced-init-list, make sure that the array
      is big enough for all the initializers.  */
   bool length_check = (init && TREE_CODE (init) == CONSTRUCTOR
@@ -3905,18 +3928,6 @@ build_vec_init (tree base, tree maxindex, tree init,
   base = get_temp_regvar (ptype, rval);
   iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
 
-  bool direct_init = false;
-  if (from_array && init && BRACE_ENCLOSED_INITIALIZER_P (init)
-      && CONSTRUCTOR_NELTS (init) == 1)
-    {
-      tree elt = CONSTRUCTOR_ELT (init, 0)->value;
-      if (TREE_CODE (TREE_TYPE (elt)) == ARRAY_TYPE)
-       {
-         direct_init = DIRECT_LIST_INIT_P (init);
-         init = elt;
-       }
-    }
-
   /* If initializing one array from another, initialize element by
      element.  We rely upon the below calls to do the argument
      checking.  Evaluate the initializer before entering the try block.  */
index 6d3b8777cf2897e402dcabdbc6119d112e6e173a..29dcfea283fa3f6aa2b51db50a4afad4cc80f9ce 100644 (file)
@@ -13026,9 +13026,6 @@ cp_parser_decomposition_declaration (cp_parser *parser,
       *init_loc = cp_lexer_peek_token (parser->lexer)->location;
       tree initializer = cp_parser_initializer (parser, &is_direct_init,
                                                &non_constant_p);
-      if (TREE_CODE (initializer) == TREE_LIST)
-       initializer = build_x_compound_expr_from_list (initializer, ELK_INIT,
-                                                      tf_warning_or_error);
 
       if (decl != error_mark_node)
        {
index ed6fce49ec5b5fa5d0ab25e0acc2ab23bd954591..7a8a239d9e17c952be26c12a31121d0ae838c3c5 100644 (file)
@@ -89,4 +89,40 @@ main ()
   }
   if (ccnt != 12 || dcnt != 24 || cccnt != 6 || tccnt != 6)
     __builtin_abort ();
+
+  {
+    A a[6];
+    if (ccnt != 18 || dcnt != 24 || cccnt != 6 || tccnt != 6)
+      __builtin_abort ();
+    {
+      auto [b,c,d,e,f,g] ( a );                // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+      if (ccnt != 18 || dcnt != 24 || cccnt != 12 || tccnt != 6)
+       __builtin_abort ();
+      b.a++;
+      c.a += 2;
+      f.a += 3;
+      if (b.a != 7 || c.a != 8 || d.a != 6 || e.a != 6 || f.a != 9 || g.a != 6)
+       __builtin_abort ();
+      if (&b == &a[0] || &c == &a[1] || &d == &a[2] || &e == &a[3] || &f == &a[4] || &g == &a[5])
+       __builtin_abort ();
+      {
+       auto&[ h, i, j, k, l, m ] (a);  // { dg-warning "decomposition declaration only available with" "" { target c++14_down } }
+       if (ccnt != 18 || dcnt != 24 || cccnt != 12 || tccnt != 6)
+         __builtin_abort ();
+       j.a += 4;
+       k.a += 5;
+       m.a += 6;
+       if (a[0].a != 6 || a[1].a != 6 || a[2].a != 10 || a[3].a != 11 || a[4].a != 6 || a[5].a != 12)
+         __builtin_abort ();
+       if (&h != &a[0] || &i != &a[1] || &j != &a[2] || &k != &a[3] || &l != &a[4] || &m != &a[5])
+         __builtin_abort ();
+      }
+      if (ccnt != 18 || dcnt != 24 || cccnt != 12 || tccnt != 6)
+       __builtin_abort ();
+    }
+    if (ccnt != 18 || dcnt != 30 || cccnt != 12 || tccnt != 6)
+      __builtin_abort ();
+  }
+  if (ccnt != 18 || dcnt != 36 || cccnt != 12 || tccnt != 6)
+    __builtin_abort ();
 }