From 0655c6d5561026bf5b3749d69cc3f30ea09ff66e Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 19 Jan 2017 09:37:51 -0500 Subject: [PATCH] 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. From-SVN: r244635 --- gcc/cp/ChangeLog | 9 +++++ gcc/cp/init.c | 51 +++++++++++++++++----------- gcc/cp/parser.c | 3 -- gcc/testsuite/g++.dg/cpp1z/decomp6.C | 36 ++++++++++++++++++++ 4 files changed, 76 insertions(+), 23 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f8377e25b4c..5b8eb7c891a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2017-01-19 Jason Merrill + + 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 PR c++/68666 - member variable template-id diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 8f68c88b38a..15388b14264 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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. */ diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 6d3b8777cf2..29dcfea283f 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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) { diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp6.C b/gcc/testsuite/g++.dg/cpp1z/decomp6.C index ed6fce49ec5..7a8a239d9e1 100644 --- a/gcc/testsuite/g++.dg/cpp1z/decomp6.C +++ b/gcc/testsuite/g++.dg/cpp1z/decomp6.C @@ -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 (); } -- 2.30.2