Update overload resolution with deduction guides.
authorJason Merrill <jason@redhat.com>
Fri, 3 Mar 2017 07:31:54 +0000 (02:31 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 3 Mar 2017 07:31:54 +0000 (02:31 -0500)
* pt.c (do_class_deduction): Always build the copy guide.
(copy_guide_p, template_guide_p): New.
(build_deduction_guide): Remember the original constructor.
* call.c (joust): Prefer the copy guide and non-template guides.

From-SVN: r245859

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp1z/class-deduction36.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/class-deduction38.C [new file with mode: 0644]

index 7b68b1395991e490fdb04dc2a9a0c499942e2255..be98880c96389e18821c1b6fcc8b1ed1fd50624c 100644 (file)
@@ -1,5 +1,11 @@
 2017-03-02  Jason Merrill  <jason@redhat.com>
 
+       Update overload resolution with deduction guides.
+       * pt.c (do_class_deduction): Always build the copy guide.
+       (copy_guide_p, template_guide_p): New.
+       (build_deduction_guide): Remember the original constructor.
+       * call.c (joust): Prefer the copy guide and non-template guides.
+
        Allow deduction guides to look into primary template.
        * cp-tree.h (struct saved_scope): Add deduction_guide_type.
        (struct cp_decl_specifier_seq): Add constructor_p.
index babab00158db18fa43e9fa7c02afcd1b3f8a75e4..dc629b96bb707a2df4b9e6e7ca7073bbbb4ff196 100644 (file)
@@ -9717,6 +9717,22 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
       int art2 = DECL_ARTIFICIAL (cand2->fn);
       if (art1 != art2)
        return art2 - art1;
+
+      if (art1)
+       {
+         /* Prefer the special copy guide over a declared copy/move
+            constructor.  */
+         if (copy_guide_p (cand1->fn))
+           return 1;
+         if (copy_guide_p (cand2->fn))
+           return -1;
+
+         /* Prefer a candidate generated from a non-template constructor.  */
+         int tg1 = template_guide_p (cand1->fn);
+         int tg2 = template_guide_p (cand2->fn);
+         if (tg1 != tg2)
+           return tg2 - tg1;
+       }
     }
 
   /* or, if not that, F2 is from a using-declaration, F1 is not, and the
index 31edc5f175b9a8ea625c022d0fb2dfc144eaa08f..75836727d804b6288331a10bc8708f5f77a74f6d 100644 (file)
@@ -6288,6 +6288,8 @@ extern tree template_parm_to_arg                (tree);
 extern tree dguide_name                                (tree);
 extern bool dguide_name_p                      (tree);
 extern bool deduction_guide_p                  (const_tree);
+extern bool copy_guide_p                       (const_tree);
+extern bool template_guide_p                   (const_tree);
 
 /* in repo.c */
 extern void init_repo                          (void);
index 3b320fc2b48e4df7f31c2c961a988f74798c31d1..13293ebd557a3d7a24a7ecd1300af77765ad802e 100644 (file)
@@ -24852,6 +24852,35 @@ deduction_guide_p (const_tree fn)
   return false;
 }
 
+/* True if FN is the copy deduction guide, i.e. A(A)->A.  */
+
+bool
+copy_guide_p (const_tree fn)
+{
+  gcc_assert (deduction_guide_p (fn));
+  if (!DECL_ARTIFICIAL (fn))
+    return false;
+  tree parms = FUNCTION_FIRST_USER_PARMTYPE (DECL_TI_TEMPLATE (fn));
+  return (TREE_CHAIN (parms) == void_list_node
+         && same_type_p (TREE_VALUE (parms), TREE_TYPE (DECL_NAME (fn))));
+}
+
+/* True if FN is a guide generated from a constructor template.  */
+
+bool
+template_guide_p (const_tree fn)
+{
+  gcc_assert (deduction_guide_p (fn));
+  if (!DECL_ARTIFICIAL (fn))
+    return false;
+  if (tree ctor = DECL_ABSTRACT_ORIGIN (fn))
+    {
+      tree tmpl = DECL_TI_TEMPLATE (ctor);
+      return PRIMARY_TEMPLATE_P (tmpl);
+    }
+  return false;
+}
+
 /* OLDDECL is a _DECL for a template parameter.  Return a similar parameter at
    LEVEL:INDEX, using tsubst_args and complain for substitution into non-type
    template parameter types.  Note that the handling of template template
@@ -25100,6 +25129,8 @@ build_deduction_guide (tree ctor, tree outer_args, tsubst_flags_t complain)
   TREE_TYPE (ded_tmpl) = TREE_TYPE (ded_fn);
   DECL_TEMPLATE_INFO (ded_fn) = build_template_info (ded_tmpl, targs);
   DECL_PRIMARY_TEMPLATE (ded_tmpl) = ded_tmpl;
+  if (DECL_P (ctor))
+    DECL_ABSTRACT_ORIGIN (ded_fn) = ctor;
   if (ci)
     set_constraints (ded_tmpl, ci);
 
@@ -25153,7 +25184,6 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
     }
 
   bool saw_ctor = false;
-  bool saw_copy = false;
   if (CLASSTYPE_METHOD_VEC (type))
     // FIXME cache artificial deduction guides
     for (tree fns = CLASSTYPE_CONSTRUCTORS (type); fns; fns = OVL_NEXT (fns))
@@ -25163,16 +25193,6 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
        cands = ovl_cons (guide, cands);
 
        saw_ctor = true;
-
-       tree parms = FUNCTION_FIRST_USER_PARMTYPE (fn);
-       if (parms && sufficient_parms_p (TREE_CHAIN (parms)))
-         {
-           tree pt = TREE_VALUE (parms);
-           if (TREE_CODE (pt) == REFERENCE_TYPE
-               && (same_type_ignoring_top_level_qualifiers_p
-                   (TREE_TYPE (pt), type)))
-             saw_copy = true;
-         }
       }
 
   if (!saw_ctor && args->length() == 0)
@@ -25180,7 +25200,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
       tree guide = build_deduction_guide (type, outer_args, complain);
       cands = ovl_cons (guide, cands);
     }
-  if (!saw_copy && args->length() == 1)
+  if (args->length() == 1)
     {
       tree guide = build_deduction_guide (build_reference_type (type),
                                          outer_args, complain);
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction36.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction36.C
new file mode 100644 (file)
index 0000000..129e29e
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-options -std=c++1z }
+
+template <class T> struct A {
+  A(T&);
+  A(const A&);
+};
+
+int i;
+A a = i;
+A a2 = a;
+
+template <class,class> struct same;
+template <class T> struct same<T,T> {};
+same<decltype(a),A<int>> s1;
+same<decltype(a2),A<int>> s2;
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction38.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction38.C
new file mode 100644 (file)
index 0000000..fe6c200
--- /dev/null
@@ -0,0 +1,27 @@
+// { dg-options -std=c++1z }
+
+template <class T> struct A {
+  using value_type = T;
+  A(value_type); // #1
+  A(const A&); // #2
+  A(T, T, int); // #3
+  template<class U> A(int, T, U); // #4
+}; // A(A); #5, the copy deduction candidate
+
+A x (1, 2, 3); // uses #3, generated from a non-template constructor
+
+template <class T> A(T) -> A<T>;  // #6, less specialized than #5
+
+A a (42); // uses #6 to deduce A<int> and #1 to initialize
+A b = a;  // uses #5 to deduce A<int> and #2 to initialize
+
+template <class T> A(A<T>) -> A<A<T>>;  // #7, as specialized as #5
+
+A b2 = a;  // uses #7 to deduce A<A<int>> and #1 to initialize
+
+template <class,class> struct same;
+template <class T> struct same<T,T> {};
+
+same<decltype(a),A<int>> s1;
+same<decltype(b),A<int>> s2;
+same<decltype(b2),A<A<int>>> s3;