Message ID | 20191210191323.GF1118066@redhat.com |
---|---|
State | New |
Headers | show |
Series | [C++] c++/92878 - Parenthesized init of aggregates in new-expression. | expand |
On 12/10/19 2:13 PM, Marek Polacek wrote: > Ville pointed out that our paren init of aggregates doesn't work for > > auto a = new A(1, 2, 3); > > and I think it should: > > A new-expression that creates an object of type T initializes that object > as follows: > ... > -- Otherwise, the new-initializer is interpreted according to the > initialization rules of [dcl.init] for direct-initialization. > > so I think it follows that we should perform dcl.init#17.6.2.2. > > This doesn't work with new[]; we have: > error ("parenthesized initializer in array new"); > > Bootstrapped/regtested on x86_64-linux, ok for trunk? OK. > 2019-12-10 Marek Polacek <polacek@redhat.com> > > PR c++/92878 - Parenthesized init of aggregates in new-expression. > * init.c (build_new_1): Handle parenthesized initialization of > aggregates in new-expression. > > * g++.dg/cpp2a/paren-init20.C: New test. > > diff --git gcc/cp/init.c gcc/cp/init.c > index e40afe27e1a..b0331b8ba53 100644 > --- gcc/cp/init.c > +++ gcc/cp/init.c > @@ -3608,10 +3608,22 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, > tree ie; > > /* We are processing something like `new int (10)', which > - means allocate an int, and initialize it with 10. */ > + means allocate an int, and initialize it with 10. > > - ie = build_x_compound_expr_from_vec (*init, "new initializer", > - complain); > + In C++20, also handle `new A(1, 2)'. */ > + if (cxx_dialect >= cxx2a > + && AGGREGATE_TYPE_P (type) > + && (*init)->length () > 1) > + { > + ie = build_tree_list_vec (*init); > + ie = build_constructor_from_list (init_list_type_node, ie); > + CONSTRUCTOR_IS_DIRECT_INIT (ie) = true; > + CONSTRUCTOR_IS_PAREN_INIT (ie) = true; > + ie = digest_init (type, ie, complain); > + } > + else > + ie = build_x_compound_expr_from_vec (*init, "new initializer", > + complain); > init_expr = cp_build_modify_expr (input_location, init_expr, > INIT_EXPR, ie, complain); > } > diff --git gcc/testsuite/g++.dg/cpp2a/paren-init20.C gcc/testsuite/g++.dg/cpp2a/paren-init20.C > new file mode 100644 > index 00000000000..05da7604686 > --- /dev/null > +++ gcc/testsuite/g++.dg/cpp2a/paren-init20.C > @@ -0,0 +1,54 @@ > +// PR c++/92878 - Parenthesized init of aggregates in new-expression. > +// { dg-do compile { target c++2a } } > +// Test new TYPE(...). > + > +int f (); > + > +struct A > +{ > + int a; > + int b; > +}; > + > +void > +fn_A () > +{ > + int i = 0; > + auto y = new A(1, 2); > + auto x = new A(++i, ++i); > + auto z = new A(1, { ++i }); > + auto u = new A(1, f()); > +} > + > +struct B > +{ > + int a; > + int b; > + int c = 42; > +}; > + > +void > +fn_B () > +{ > + int i = 0; > + auto y = new B(1, 2); > + auto x = new B(++i, ++i); > + auto z = new B(1, { ++i }); > + auto u = new B(1, f()); > +} > + > +struct C > +{ > + int a; > + int b = 10; > +}; > + > +void > +fn_C () > +{ > + int i = 0; > + auto y = new C(1); > + auto x = new C(++i); > + auto z = new C({ ++i }); > + auto u = new C(f()); > +} >
diff --git gcc/cp/init.c gcc/cp/init.c index e40afe27e1a..b0331b8ba53 100644 --- gcc/cp/init.c +++ gcc/cp/init.c @@ -3608,10 +3608,22 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, tree ie; /* We are processing something like `new int (10)', which - means allocate an int, and initialize it with 10. */ + means allocate an int, and initialize it with 10. - ie = build_x_compound_expr_from_vec (*init, "new initializer", - complain); + In C++20, also handle `new A(1, 2)'. */ + if (cxx_dialect >= cxx2a + && AGGREGATE_TYPE_P (type) + && (*init)->length () > 1) + { + ie = build_tree_list_vec (*init); + ie = build_constructor_from_list (init_list_type_node, ie); + CONSTRUCTOR_IS_DIRECT_INIT (ie) = true; + CONSTRUCTOR_IS_PAREN_INIT (ie) = true; + ie = digest_init (type, ie, complain); + } + else + ie = build_x_compound_expr_from_vec (*init, "new initializer", + complain); init_expr = cp_build_modify_expr (input_location, init_expr, INIT_EXPR, ie, complain); } diff --git gcc/testsuite/g++.dg/cpp2a/paren-init20.C gcc/testsuite/g++.dg/cpp2a/paren-init20.C new file mode 100644 index 00000000000..05da7604686 --- /dev/null +++ gcc/testsuite/g++.dg/cpp2a/paren-init20.C @@ -0,0 +1,54 @@ +// PR c++/92878 - Parenthesized init of aggregates in new-expression. +// { dg-do compile { target c++2a } } +// Test new TYPE(...). + +int f (); + +struct A +{ + int a; + int b; +}; + +void +fn_A () +{ + int i = 0; + auto y = new A(1, 2); + auto x = new A(++i, ++i); + auto z = new A(1, { ++i }); + auto u = new A(1, f()); +} + +struct B +{ + int a; + int b; + int c = 42; +}; + +void +fn_B () +{ + int i = 0; + auto y = new B(1, 2); + auto x = new B(++i, ++i); + auto z = new B(1, { ++i }); + auto u = new B(1, f()); +} + +struct C +{ + int a; + int b = 10; +}; + +void +fn_C () +{ + int i = 0; + auto y = new C(1); + auto x = new C(++i); + auto z = new C({ ++i }); + auto u = new C(f()); +}