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