diff mbox

C++ PATCH for C++17 class template placeholders

Message ID CADzB+2kWX900+N7gkhwpmj8EFJMDgu+Mj1DAk2tq8RaZH9hFQQ@mail.gmail.com
State New
Headers show

Commit Message

Jason Merrill Oct. 5, 2016, 3:11 a.m. UTC
On Tue, Oct 4, 2016 at 4:42 PM, Jason Merrill <jason@redhat.com> wrote:
> C++17 adds the ability to omit the template arguments for a class
> template when declaring a variable with an initializer, much like auto
> but supporting a wider variety of initialization.  This is intended to
> replace functions like make_tuple.
>
> Tested x86_64-pc-linux-gnu, applying to trunk.

A few tweaks...
commit 492ab670ad2c1ddc11c59bb77220c5a996b0f87a
Author: jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Wed Oct 5 01:24:38 2016 +0000

            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.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@240765 138bc75d-0d04-0410-961f-82ee72b054a4
diff mbox

Patch

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/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);