PR c++/77852 - class deduction from list-init
authorJason Merrill <jason@redhat.com>
Wed, 5 Oct 2016 01:24:38 +0000 (21:24 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 5 Oct 2016 01:24:38 +0000 (21:24 -0400)
* 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

gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp1z/class-deduction14.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/class-deduction15.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/class-deduction16.C [new file with mode: 0644]

index d39e036c1a970866b6cc7d7fd4af7784ee7c3789..1a16c6aaeb8c2d78bdb054ae1125aefe0e181c5e 100644 (file)
@@ -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
index 491c637b5605cef48c184104570faf612c321ba6..2fce7933d5b2a70e7680e5a09fa1d63ee8283497 100644 (file)
@@ -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> *
index c88619b5acaf0e663b9549a5bae7ee3e0aee058d..28aebec6e2e2d43a3d5ef9e4dbd5abee8eaf0246 100644 (file)
@@ -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
index b7a57e072da300a962933f75effed78ec8163c5a..acd1a78696c38963556eec39867aea09621f8331 100644 (file)
@@ -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.
index f92366658c9eaa2b7b9aabd880bf648f2dab4bff..e6b1368daf75f47a85eb977597eae53bad8a2172 100644 (file)
@@ -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 (file)
index 0000000..1c7e34e
--- /dev/null
@@ -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 (file)
index 0000000..72ed478
--- /dev/null
@@ -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 (file)
index 0000000..b32869f
--- /dev/null
@@ -0,0 +1,9 @@
+// { dg-options -std=c++1z }
+
+template <class... T>
+struct A
+{
+  template <class...Us> A(Us&&...);
+};
+
+A a(1,2);