The following patch is supposed to fix the problem related to initializing an array of aggregates with members, which have user-defined default constructors.
Bootstrapped and regtested on x86_64-unknown-linux-gnu. diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 0274663..0f53146 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -3716,11 +3716,9 @@ build_vec_init (tree base, tree maxindex, tree init, { if (cxx_dialect >= cxx11 && AGGREGATE_TYPE_P (type)) { - if (BRACE_ENCLOSED_INITIALIZER_P (init) - && CONSTRUCTOR_NELTS (init) == 0) - /* Reuse it. */; - else - init = build_constructor (init_list_type_node, NULL); + /* We cannot reuse INIT here, because it must not be shared + with member initializers. */ + init = build_constructor (init_list_type_node, NULL); CONSTRUCTOR_IS_DIRECT_INIT (init) = true; } else diff --git a/gcc/testsuite/g++.dg/init/array39.C b/gcc/testsuite/g++.dg/init/array39.C new file mode 100644 index 0000000..2fd8937 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array39.C @@ -0,0 +1,46 @@ +// PR c++/65154 +// { dg-do run { target c++11 } } + +int cnt1 = 0, + cnt2 = 0; + +struct S_empty +{ + S_empty () { + cnt1++; + }; +}; + +struct C1 +{ + S_empty s; +}; + +struct S_init +{ + S_init () : i(42) + { + cnt2++; + }; + int i; +}; + +struct C2 +{ + S_init a, b; +}; + +int +main () +{ + C1 c1[5]{}; + C2 c2[1]{}; + + if (c2[0].a.i != 42 || c2[0].b.i != 42) + return 1; + + if (cnt1 != 5 || cnt2 != 2) + return 1; + + return 0; +} Changelog record: 2015-03-02 Mikhail Maltsev <malts...@gmail.com> PR c++/65154 * gcc/cp/init.c (build_vec_init): Fixed initializing aggregates with empty init list. * gcc/testsuite/g++.dg/init/array39.C: New test. N.B.: Consider the test case. The constructors of S_init and S_empty are called from main (this can be seen in GIMPLE dump, right after gimplification), while clang, for example, generates an explicit call to constructors of C1 and C2. GCC does the same, if direct initializers are removed. I don't know, if such behavior is OK or not. -- Regards, Mikhail Maltsev