PR c++/92878 - Parenthesized init of aggregates in new-expression.
authorMarek Polacek <polacek@redhat.com>
Wed, 11 Dec 2019 18:40:55 +0000 (18:40 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Wed, 11 Dec 2019 18:40:55 +0000 (18:40 +0000)
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");

* init.c (build_new_1): Handle parenthesized initialization of
aggregates in new-expression.

* g++.dg/cpp2a/paren-init20.C: New test.

From-SVN: r279240

gcc/cp/ChangeLog
gcc/cp/init.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp2a/paren-init20.C [new file with mode: 0644]

index 7051a42831f537636b5dfd37fd49a1ba817cded2..5a2ba31a6e037f2a633629f65c343b3994451bb2 100644 (file)
@@ -1,3 +1,9 @@
+2019-12-11  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.
+
 2019-12-11  Jason Merrill  <jason@redhat.com>
 
        PR c++/92105 - decltype(decltype) error cascade.
index ecd09510adb6d253d66fcc6745028887e662e65b..6f4c918d5604e3311f33a435c4e2cb8ed4d87b99 100644 (file)
@@ -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);
            }
index 0942db0dc013b1dd810d2588ecde5fa02156f98d..aac5a76823c489b8f8e611fd55b04f42c2df79d6 100644 (file)
@@ -1,3 +1,8 @@
+2019-12-11  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/92878 - Parenthesized init of aggregates in new-expression.
+       * g++.dg/cpp2a/paren-init20.C: New test.
+
 2019-12-11  Martin Sebor  <msebor@redhat.com>
 
        PR middle-end/79221
diff --git a/gcc/testsuite/g++.dg/cpp2a/paren-init20.C b/gcc/testsuite/g++.dg/cpp2a/paren-init20.C
new file mode 100644 (file)
index 0000000..05da760
--- /dev/null
@@ -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());
+}