call.c (add_template_conv_candidate): Pass DEDUCE_CALL.
authorJason Merrill <jason@redhat.com>
Fri, 23 Oct 2015 00:51:14 +0000 (20:51 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 23 Oct 2015 00:51:14 +0000 (20:51 -0400)
* call.c (add_template_conv_candidate): Pass DEDUCE_CALL.
(add_template_candidate_real): Handle it.
(fn_type_unification): Handle it.

From-SVN: r229210

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp0x/conv-tmpl1.C [new file with mode: 0644]

index 05ffbdc4d5a5b8fff56a88d180383104d2999695..e2fd1614744b1d3c0ca1e5322fcc0964cb9212f4 100644 (file)
@@ -1,5 +1,9 @@
 2015-10-22  Jason Merrill  <jason@redhat.com>
 
+       * call.c (add_template_conv_candidate): Pass DEDUCE_CALL.
+       (add_template_candidate_real): Handle it.
+       (fn_type_unification): Handle it.
+
        * call.c (add_conv_candidate): Remove first_arg parm.
        (add_template_conv_candidate): Likewise.
        (add_template_candidate_real): Don't pass it.
index 9304aac5f3fdfe570af20361825f2d44bdb70560..5b57dc97b54b945fc33dc3ac47936d74279ddb27 100644 (file)
@@ -3027,6 +3027,9 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
     {
       if (first_arg_without_in_chrg != NULL_TREE)
        first_arg_without_in_chrg = NULL_TREE;
+      else if (return_type && strict == DEDUCE_CALL)
+       /* We're deducing for a call to the result of a template conversion
+          function, so the args don't contain 'this'; leave them alone.  */;
       else
        ++skip_without_in_chrg;
     }
@@ -3167,6 +3170,11 @@ add_template_candidate (struct z_candidate **candidates, tree tmpl, tree ctype,
                                 flags, NULL_TREE, strict, complain);
 }
 
+/* Create an overload candidate for the conversion function template TMPL,
+   returning RETURN_TYPE, which will be invoked for expression OBJ to produce a
+   pointer-to-function which will in turn be called with the argument list
+   ARGLIST, and add it to CANDIDATES.  This does not change ARGLIST.  FLAGS is
+   passed on to implicit_conversion.  */
 
 static struct z_candidate *
 add_template_conv_candidate (struct z_candidate **candidates, tree tmpl,
@@ -3178,7 +3186,7 @@ add_template_conv_candidate (struct z_candidate **candidates, tree tmpl,
   return
     add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
                                 NULL_TREE, arglist, return_type, access_path,
-                                conversion_path, 0, obj, DEDUCE_CONV,
+                                conversion_path, 0, obj, DEDUCE_CALL,
                                 complain);
 }
 
index 142245ad8e0c8a2d377a3d28622b239f9850e81d..ffe02da00db4b5fb4bcc2b73062a03311c7f01cf 100644 (file)
@@ -17235,7 +17235,9 @@ pack_deducible_p (tree parm, tree fn)
 
    DEDUCE_CALL:
      We are deducing arguments for a function call, as in
-     [temp.deduct.call].
+     [temp.deduct.call].  If RETURN_TYPE is non-null, we are
+     deducing arguments for a call to the result of a conversion
+     function template, as in [over.call.object].
 
    DEDUCE_CONV:
      We are deducing arguments for a conversion function, as in
@@ -17402,7 +17404,15 @@ fn_type_unification (tree fn,
   /* Never do unification on the 'this' parameter.  */
   parms = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (fntype));
 
-  if (return_type)
+  if (return_type && strict == DEDUCE_CALL)
+    {
+      /* We're deducing for a call to the result of a template conversion
+         function.  The parms we really want are in return_type.  */
+      if (POINTER_TYPE_P (return_type))
+       return_type = TREE_TYPE (return_type);
+      parms = TYPE_ARG_TYPES (return_type);
+    }
+  else if (return_type)
     {
       tree *new_args;
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/conv-tmpl1.C b/gcc/testsuite/g++.dg/cpp0x/conv-tmpl1.C
new file mode 100644 (file)
index 0000000..7f866da
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++11 } }
+
+template <class T>
+using Fn = void (*)(T);
+
+struct A
+{
+  template <class T>
+  operator Fn<T>();
+};
+
+int main()
+{
+  A()(42);
+}