diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7c4b0821732..e384cf7991e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2010-11-03 Jason Merrill + PR c++/46289 + * call.c (can_convert_array): New fn. + (build_aggr_conv): Use it. + PR c++/46289 * semantics.c (build_constexpr_constructor_member_initializers): Avoid ICE on error. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index a1c8682fe6c..4507f3d37b9 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -639,6 +639,29 @@ build_list_conv (tree type, tree ctor, int flags) return t; } +/* Subroutine of build_aggr_conv: check whether CTOR, a braced-init-list, + is a valid aggregate initializer for array type ATYPE. */ + +static bool +can_convert_array (tree atype, tree ctor, int flags) +{ + unsigned i; + tree elttype = TREE_TYPE (atype); + for (i = 0; i < CONSTRUCTOR_NELTS (ctor); ++i) + { + tree val = CONSTRUCTOR_ELT (ctor, i)->value; + bool ok; + if (TREE_CODE (elttype) == ARRAY_TYPE + && TREE_CODE (val) == CONSTRUCTOR) + ok = can_convert_array (elttype, val, flags); + else + ok = can_convert_arg (elttype, TREE_TYPE (val), val, flags); + if (!ok) + return false; + } + return true; +} + /* Represent a conversion from CTOR, a braced-init-list, to TYPE, an aggregate class, if such a conversion is possible. */ @@ -652,24 +675,31 @@ build_aggr_conv (tree type, tree ctor, int flags) for (; field; field = next_initializable_field (DECL_CHAIN (field))) { + tree ftype = TREE_TYPE (field); + tree val; + bool ok; + if (i < CONSTRUCTOR_NELTS (ctor)) - { - constructor_elt *ce = CONSTRUCTOR_ELT (ctor, i); - if (!can_convert_arg (TREE_TYPE (field), TREE_TYPE (ce->value), - ce->value, flags)) - return NULL; - ++i; - if (TREE_CODE (type) == UNION_TYPE) - break; - } + val = CONSTRUCTOR_ELT (ctor, i)->value; else { if (empty_ctor == NULL_TREE) empty_ctor = build_constructor (init_list_type_node, NULL); - if (!can_convert_arg (TREE_TYPE (field), TREE_TYPE (empty_ctor), - empty_ctor, flags)) - return NULL; + val = empty_ctor; } + ++i; + + if (TREE_CODE (ftype) == ARRAY_TYPE + && TREE_CODE (val) == CONSTRUCTOR) + ok = can_convert_array (ftype, val, flags); + else + ok = can_convert_arg (ftype, TREE_TYPE (val), val, flags); + + if (!ok) + return NULL; + + if (TREE_CODE (type) == UNION_TYPE) + break; } if (i < CONSTRUCTOR_NELTS (ctor)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f607bebd83d..0597d4718dc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-11-03 Jason Merrill + + PR c++/46289 + * g++.dg/cpp0x/initlist45.C: New. + 2010-11-03 Nicola Pero * objc.dg/property/dynamic-2.m: Updated for the fact that @dynamic diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist45.C b/gcc/testsuite/g++.dg/cpp0x/initlist45.C new file mode 100644 index 00000000000..0e34bc18977 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist45.C @@ -0,0 +1,13 @@ +// PR c++/46289 +// { dg-options -std=c++0x } + +struct A +{ + int i[2]; +}; + +struct B +{ + A a; + B(): a({{1,2}}) { } +};