From: Jason Merrill Date: Wed, 5 Oct 2016 01:24:38 +0000 (-0400) Subject: PR c++/77852 - class deduction from list-init X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f1644724b57aa559f71a22402b3eeb776be106e5;p=gcc.git PR c++/77852 - class deduction from list-init * pt.c (do_class_deduction): Handle list-initialization. (do_auto_deduction): Call it sooner. (build_deduction_guide): Use tsubst_arg_types. (rewrite_template_parm): Don't copy_type. From-SVN: r240765 --- diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index d39e036c1a9..1a16c6aaeb8 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2016-10-04 Jason Merrill + + * c-common.c (make_tree_vector_from_ctor): New. + * c-common.h: Declare it. + 2016-10-04 Jakub Jelinek * c-cppbuiltin.c (c_cpp_builtins): Don't define diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 491c637b560..2fce7933d5b 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -12612,6 +12612,18 @@ make_tree_vector_from_list (tree list) return ret; } +/* Get a new tree vector of the values of a CONSTRUCTOR. */ + +vec * +make_tree_vector_from_ctor (tree ctor) +{ + vec *ret = make_tree_vector (); + vec_safe_reserve (ret, CONSTRUCTOR_NELTS (ctor)); + for (unsigned i = 0; i < CONSTRUCTOR_NELTS (ctor); ++i) + ret->quick_push (CONSTRUCTOR_ELT (ctor, i)->value); + return ret; +} + /* Get a new tree vector which is a copy of an existing one. */ vec * diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index c88619b5aca..28aebec6e2e 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1111,6 +1111,7 @@ extern vec *make_tree_vector (void); extern void release_tree_vector (vec *); extern vec *make_tree_vector_single (tree); extern vec *make_tree_vector_from_list (tree); +extern vec *make_tree_vector_from_ctor (tree); extern vec *make_tree_vector_copy (const vec *); /* Used for communication between c_common_type_for_mode and diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b7a57e072da..acd1a78696c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,11 +1,15 @@ -2016-09-30 Jason Merrill +2016-10-04 Jason Merrill + + PR c++/77852 + * pt.c (do_class_deduction): Handle list-initialization. + (do_auto_deduction): Call it sooner. + (build_deduction_guide): Use tsubst_arg_types. + (rewrite_template_parm): Don't copy_type. PR c++/77775 * constexpr.c (cxx_eval_component_reference): Use name matching for PMFs. -2016-10-04 Jason Merrill - Implement P0091R2, Template argument deduction for class templates. * parser.c (cp_parser_simple_type_specifier): Parse class placeholder. Use the location of the beginning of the type-specifier. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f92366658c9..e6b1368daf7 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -24178,7 +24178,7 @@ rewrite_template_parm (tree olddecl, unsigned index, unsigned level, if (TREE_CODE (olddecl) == TYPE_DECL || TREE_CODE (olddecl) == TEMPLATE_DECL) { - newtype = copy_type (TREE_TYPE (olddecl)); + newtype = cxx_make_type (TREE_CODE (TREE_TYPE (olddecl))); TYPE_MAIN_VARIANT (newtype) = newtype; } else @@ -24340,7 +24340,8 @@ build_deduction_guide (tree ctor, tree outer_args, tsubst_flags_t complain) /* Now we have a final set of template parms to substitute into the function signature. */ targs = template_parms_to_args (tparms); - fparms = tsubst (fparms, tsubst_args, complain, ctor); + fparms = tsubst_arg_types (fparms, tsubst_args, NULL_TREE, + complain, ctor); fargs = tsubst (fargs, tsubst_args, complain, ctor); if (ci) ci = tsubst_constraint_info (ci, tsubst_args, complain, ctor); @@ -24376,6 +24377,8 @@ do_class_deduction (tree tmpl, tree init, tsubst_flags_t complain) vec *args; if (TREE_CODE (init) == TREE_LIST) args = make_tree_vector_from_list (init); + else if (BRACE_ENCLOSED_INITIALIZER_P (init)) + args = make_tree_vector_from_ctor (init); else args = make_tree_vector_single (init); @@ -24465,6 +24468,10 @@ do_auto_deduction (tree type, tree init, tree auto_node, from ahead of time isn't worth the trouble. */ return type; + if (tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node)) + /* C++17 class template argument deduction. */ + return do_class_deduction (tmpl, init, complain); + /* [dcl.spec.auto]: Obtain P from T by replacing the occurrences of auto with either a new invented type template parameter U or, if the initializer is a braced-init-list (8.5.4), with @@ -24510,9 +24517,6 @@ do_auto_deduction (tree type, tree init, tree auto_node, return error_mark_node; } } - else if (tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node)) - /* C++17 class template argument deduction. */ - return do_class_deduction (tmpl, init, complain); else { tree parms = build_tree_list (NULL_TREE, type); diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction14.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction14.C new file mode 100644 index 00000000000..1c7e34e17c6 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction14.C @@ -0,0 +1,15 @@ +// { dg-options -std=c++1z } + +#include + +template struct container { + container(T t) {} + template container(Iter beg, Iter end); +}; +template +container(Iter b, Iter e) // { dg-message "iterator_traits.int" } + -> container::value_type>; +std::vector v = { /* ... */ }; +container c(7); // OK, deduces int for T +auto d = container(v.begin(), v.end()); // OK, deduces double for T +container e{5, 6}; // { dg-error "" } int is not an iterator diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction15.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction15.C new file mode 100644 index 00000000000..72ed478a1c2 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction15.C @@ -0,0 +1,9 @@ +// { dg-options -std=c++1z } + +#include + +int main() +{ + std::pair x{42, 666}; +} + diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction16.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction16.C new file mode 100644 index 00000000000..b32869f3fb6 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction16.C @@ -0,0 +1,9 @@ +// { dg-options -std=c++1z } + +template +struct A +{ + template A(Us&&...); +}; + +A a(1,2);