diff options
author | Jason Merrill <jason@redhat.com> | 2016-10-04 21:24:38 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2016-10-04 21:24:38 -0400 |
commit | f1644724b57aa559f71a22402b3eeb776be106e5 (patch) | |
tree | 52c454f1c5de6d7762449bf5b461ac803afb4a43 /gcc | |
parent | 1c84b79889a10503e5adf0e78d0509a88ca08868 (diff) | |
download | gcc-f1644724b57aa559f71a22402b3eeb776be106e5.zip gcc-f1644724b57aa559f71a22402b3eeb776be106e5.tar.gz gcc-f1644724b57aa559f71a22402b3eeb776be106e5.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/c-family/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 12 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 1 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/pt.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1z/class-deduction14.C | 15 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1z/class-deduction15.C | 9 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1z/class-deduction16.C | 9 |
8 files changed, 67 insertions, 8 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index d39e036..1a16c6a 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2016-10-04 Jason Merrill <jason@redhat.com> + + * c-common.c (make_tree_vector_from_ctor): New. + * c-common.h: Declare it. + 2016-10-04 Jakub Jelinek <jakub@redhat.com> * 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 491c637..2fce793 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<tree, va_gc> * +make_tree_vector_from_ctor (tree ctor) +{ + vec<tree,va_gc> *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<tree, va_gc> * diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index c88619b..28aebec 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1111,6 +1111,7 @@ extern vec<tree, va_gc> *make_tree_vector (void); extern void release_tree_vector (vec<tree, va_gc> *); extern vec<tree, va_gc> *make_tree_vector_single (tree); extern vec<tree, va_gc> *make_tree_vector_from_list (tree); +extern vec<tree, va_gc> *make_tree_vector_from_ctor (tree); extern vec<tree, va_gc> *make_tree_vector_copy (const vec<tree, va_gc> *); /* Used for communication between c_common_type_for_mode and diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b7a57e0..acd1a78 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,11 +1,15 @@ -2016-09-30 Jason Merrill <jason@redhat.com> +2016-10-04 Jason Merrill <jason@redhat.com> + + 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 <jason@redhat.com> - 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 f923666..e6b1368 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<tree,va_gc> *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 0000000..1c7e34e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction14.C @@ -0,0 +1,15 @@ +// { dg-options -std=c++1z } + +#include <vector> + +template<class T> struct container { + container(T t) {} + template<class Iter> container(Iter beg, Iter end); +}; +template<class Iter> +container(Iter b, Iter e) // { dg-message "iterator_traits.int" } + -> container<typename std::iterator_traits<Iter>::value_type>; +std::vector<double> 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 0000000..72ed478 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction15.C @@ -0,0 +1,9 @@ +// { dg-options -std=c++1z } + +#include <utility> + +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 0000000..b32869f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction16.C @@ -0,0 +1,9 @@ +// { dg-options -std=c++1z } + +template <class... T> +struct A +{ + template <class...Us> A(Us&&...); +}; + +A a(1,2); |