US 19 - deduction guides and constructors
authorJason Merrill <jason@redhat.com>
Fri, 20 Jan 2017 04:43:13 +0000 (23:43 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 20 Jan 2017 04:43:13 +0000 (23:43 -0500)
* call.c (joust): Prefer deduction guides to constructors.
* pt.c (build_deduction_guide): Set DECL_ARTIFICIAL.
(deduction_guide_p): Check DECL_P.

From-SVN: r244681

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

index 90e230fc344ab0f7426aea4a8874dc616da33d39..e16853971fb30f906c5282e6d3dfca60f297c9f0 100644 (file)
@@ -1,5 +1,10 @@
 2017-01-19  Jason Merrill  <jason@redhat.com>
 
+       US 19 - deduction guides and constructors
+       * call.c (joust): Prefer deduction guides to constructors.
+       * pt.c (build_deduction_guide): Set DECL_ARTIFICIAL.
+       (deduction_guide_p): Check DECL_P.
+
        * decl.c (check_initializer): Always use build_aggr_init for array
        decomposition.
 
index 88d83dd8a5d056c61cdfd81f65f08be9203dffa3..0059a395ae4474d370b86e1209f8e6e1e61bdba7 100644 (file)
@@ -9633,6 +9633,18 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
        return winner;
     }
 
+  /* F1 is generated from a deduction-guide (13.3.1.8) and F2 is not */
+  if (deduction_guide_p (cand1->fn))
+    {
+      gcc_assert (deduction_guide_p (cand2->fn));
+      /* We distinguish between candidates from an explicit deduction guide and
+        candidates built from a constructor based on DECL_ARTIFICIAL.  */
+      int art1 = DECL_ARTIFICIAL (cand1->fn);
+      int art2 = DECL_ARTIFICIAL (cand2->fn);
+      if (art1 != art2)
+       return art2 - art1;
+    }
+
   /* or, if not that,
      F1 is a non-template function and F2 is a template function
      specialization.  */
index c679133850e3b0fde4d931706a64555e322df890..f683727e9775ecc0db4d6ad2f344d069333a7294 100644 (file)
@@ -24776,8 +24776,9 @@ dguide_name_p (tree name)
 bool
 deduction_guide_p (tree fn)
 {
-  if (tree name = DECL_NAME (fn))
-    return dguide_name_p (name);
+  if (DECL_P (fn))
+    if (tree name = DECL_NAME (fn))
+      return dguide_name_p (name);
   return false;
 }
 
@@ -24981,7 +24982,9 @@ build_deduction_guide (tree ctor, tree outer_args, tsubst_flags_t complain)
                                     FUNCTION_DECL,
                                     dguide_name (type), fntype);
   DECL_ARGUMENTS (ded_fn) = fargs;
+  DECL_ARTIFICIAL (ded_fn) = true;
   tree ded_tmpl = build_template_decl (ded_fn, tparms, /*member*/false);
+  DECL_ARTIFICIAL (ded_tmpl) = true;
   DECL_TEMPLATE_RESULT (ded_tmpl) = ded_fn;
   TREE_TYPE (ded_tmpl) = TREE_TYPE (ded_fn);
   DECL_TEMPLATE_INFO (ded_fn) = build_template_info (ded_tmpl, targs);
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction25.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction25.C
new file mode 100644 (file)
index 0000000..07ab5f5
--- /dev/null
@@ -0,0 +1,24 @@
+// Testcase from P0512R0 for C++17 NB comment US 19
+// { dg-options -std=c++1z }
+
+template<typename> struct remove_ref;
+template<typename _Tp> struct remove_ref { typedef _Tp type; };
+template<typename _Tp> struct remove_ref<_Tp&> { typedef _Tp type; };
+template<typename _Tp> struct remove_ref<_Tp&&> { typedef _Tp type; };
+template<typename _Tp> using remove_ref_t = typename remove_ref<_Tp>::type;
+
+template<class T> struct A {
+ A(T, int*); // #1
+ A(A<T>&, int*); // #2
+ enum { value };
+};
+template<class T, int N = remove_ref_t<T>::value> A(T&&, int*) -> A<T>; //#3
+
+A a{1,0}; // uses #1 to deduce A<int> and initializes with #1
+A b{a,0}; // uses #3 (not #2) to deduce A<A<int>&> and initializes with #1
+
+template <class,class> struct same;
+template <class T> struct same<T,T> {};
+
+same<decltype(a),A<int>> s1;
+same<decltype(b),A<A<int>&>> s2;