Here we were failing to deduce template arguments for a class, because the
code in build_new only handled the case when INIT had 1 element.  That works
for e.g. new auto (foo) or new Foo{1, 2}, but not new Foo(1, 2).  I noticed
that it works without "new" because we simply create a tree list of the
arguments and pass it down to do_auto_deduction (in build_functional_cast).
do_class_deduction is prepared to receive a tree list.

(Sorry if this is totally bogus.)

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2018-05-24  Marek Polacek  <pola...@redhat.com>

        PR c++/85883
        * init.c (build_new): Handle deducing a class with new
        with more than one argument.

        * g++.dg/cpp1z/class-deduction55.C: New test.
        * g++.dg/cpp1z/class-deduction56.C: New test.
        * g++.dg/cpp1z/class-deduction57.C: New test.

diff --git gcc/cp/init.c gcc/cp/init.c
index 3f1e49bae21..3b175f94ecb 100644
--- gcc/cp/init.c
+++ gcc/cp/init.c
@@ -3585,11 +3585,25 @@ build_new (vec<tree, va_gc> **placement, tree type, 
tree nelts,
       if (auto_node)
        {
          tree d_init = NULL_TREE;
-         if (vec_safe_length (*init) == 1)
+         const size_t len = vec_safe_length (*init);
+         /* E.g. new auto(x) must have exactly one element, or
+            a {} initializer will have one element.  */
+         if (len == 1)
            {
              d_init = (**init)[0];
              d_init = resolve_nondeduced_context (d_init, complain);
            }
+         /* For the rest, e.g. new A(1, 2, 3), create a list.  */
+         else if (len > 1)
+           {
+             unsigned int n;
+             tree t;
+             FOR_EACH_VEC_ELT (**init, n, t)
+               {
+                 t = resolve_nondeduced_context (t, complain);
+                 d_init = chainon (d_init, build_tree_list (NULL_TREE, t));
+               }
+           }
          type = do_auto_deduction (type, d_init, auto_node, complain);
        }
     }
diff --git gcc/testsuite/g++.dg/cpp1z/class-deduction55.C 
gcc/testsuite/g++.dg/cpp1z/class-deduction55.C
index e69de29bb2d..a93d7203681 100644
--- gcc/testsuite/g++.dg/cpp1z/class-deduction55.C
+++ gcc/testsuite/g++.dg/cpp1z/class-deduction55.C
@@ -0,0 +1,15 @@
+// PR c++/85883
+// { dg-options -std=c++17 }
+
+template <typename T>
+struct Bar
+{
+  Bar(T) { }
+};
+
+int
+main ()
+{
+  auto x = Bar(1);
+  auto y = new Bar(3);
+}
diff --git gcc/testsuite/g++.dg/cpp1z/class-deduction56.C 
gcc/testsuite/g++.dg/cpp1z/class-deduction56.C
index e69de29bb2d..71dbfa1904d 100644
--- gcc/testsuite/g++.dg/cpp1z/class-deduction56.C
+++ gcc/testsuite/g++.dg/cpp1z/class-deduction56.C
@@ -0,0 +1,15 @@
+// PR c++/85883
+// { dg-options -std=c++17 }
+
+template <typename T1, typename T2>
+struct Bar
+{
+  Bar(T1, T2) { }
+};
+
+int
+main ()
+{
+  auto x = Bar(1, 2);
+  auto y = new Bar(3, 4);
+}
diff --git gcc/testsuite/g++.dg/cpp1z/class-deduction57.C 
gcc/testsuite/g++.dg/cpp1z/class-deduction57.C
index e69de29bb2d..200ba6c3536 100644
--- gcc/testsuite/g++.dg/cpp1z/class-deduction57.C
+++ gcc/testsuite/g++.dg/cpp1z/class-deduction57.C
@@ -0,0 +1,15 @@
+// PR c++/85883
+// { dg-options -std=c++17 }
+
+template <typename T1, typename T2, typename T3>
+struct Bar
+{
+  Bar(T1, T2, T3) { }
+};
+
+int
+main ()
+{
+  auto x = Bar(1, 2, 3);
+  auto y = new Bar(3, 4, 5);
+}

Reply via email to