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
This commit is contained in:
Jason Merrill 2017-01-19 09:37:51 -05:00 committed by Jason Merrill
parent 332429c807
commit 0655c6d556
4 changed files with 76 additions and 23 deletions

View 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> 2017-01-18 Jason Merrill <jason@redhat.com>
PR c++/68666 - member variable template-id PR c++/68666 - member variable template-id

View File

@ -1574,20 +1574,24 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
TREE_READONLY (exp) = 0; TREE_READONLY (exp) = 0;
TREE_THIS_VOLATILE (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) if (TREE_CODE (type) == ARRAY_TYPE)
{ {
tree itype = init ? TREE_TYPE (init) : NULL_TREE; tree itype = init ? TREE_TYPE (init) : NULL_TREE;
int from_array = 0; int from_array = 0;
if (VAR_P (exp) && DECL_DECOMPOSITION_P (exp)) 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 else
{ {
/* An array may not be initialized use the parenthesized /* 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; 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) if ((VAR_P (exp) || TREE_CODE (exp) == PARM_DECL)
&& !lookup_attribute ("warn_unused", TYPE_ATTRIBUTES (type))) && !lookup_attribute ("warn_unused", TYPE_ATTRIBUTES (type)))
/* Just know that we've seen something for this node. */ /* 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) && from_array != 2)
init = TARGET_EXPR_INITIAL (init); 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 /* If we have a braced-init-list, make sure that the array
is big enough for all the initializers. */ is big enough for all the initializers. */
bool length_check = (init && TREE_CODE (init) == CONSTRUCTOR 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); base = get_temp_regvar (ptype, rval);
iterator = get_temp_regvar (ptrdiff_type_node, maxindex); 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 /* If initializing one array from another, initialize element by
element. We rely upon the below calls to do the argument element. We rely upon the below calls to do the argument
checking. Evaluate the initializer before entering the try block. */ checking. Evaluate the initializer before entering the try block. */

View File

@ -13026,9 +13026,6 @@ cp_parser_decomposition_declaration (cp_parser *parser,
*init_loc = cp_lexer_peek_token (parser->lexer)->location; *init_loc = cp_lexer_peek_token (parser->lexer)->location;
tree initializer = cp_parser_initializer (parser, &is_direct_init, tree initializer = cp_parser_initializer (parser, &is_direct_init,
&non_constant_p); &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) if (decl != error_mark_node)
{ {

View File

@ -89,4 +89,40 @@ main ()
} }
if (ccnt != 12 || dcnt != 24 || cccnt != 6 || tccnt != 6) if (ccnt != 12 || dcnt != 24 || cccnt != 6 || tccnt != 6)
__builtin_abort (); __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 ();
} }