diff mbox series

[C++] c++/92878 - Parenthesized init of aggregates in new-expression.

Message ID 20191210191323.GF1118066@redhat.com
State New
Headers show
Series [C++] c++/92878 - Parenthesized init of aggregates in new-expression. | expand

Commit Message

Marek Polacek Dec. 10, 2019, 7:13 p.m. UTC
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?

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.

Comments

Jason Merrill Dec. 11, 2019, 6:30 p.m. UTC | #1
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 mbox series

Patch

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());
+}