public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C++ PATCH for template conversion function call
@ 2015-10-23  2:13 Jason Merrill
  0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2015-10-23  2:13 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 266 bytes --]

A testcase in a comment for 67847 led me to realize that our code for 
calling the result of a conversion template to pointer-to-function type 
was fundamentally broken (and apparently untested).  This patch fixes it.

Tested x86_64-pc-linux-gnu, applying to trunk.

[-- Attachment #2: tmpl-conv-call.patch --]
[-- Type: text/x-patch, Size: 7903 bytes --]

commit 89411e903d2bfea13933ad1d7f0027e383a3009c
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Oct 22 13:48:01 2015 -1000

    	* call.c (add_template_conv_candidate): Pass DEDUCE_CALL.
    	(add_template_candidate_real): Handle it.
    	(fn_type_unification): Handle it.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 93dd86a..1223dcd 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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);
 }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 142245a..ffe02da 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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
index 0000000..7f866da
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/conv-tmpl1.C
@@ -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);
+}

commit ee11ebf3960f92d5c36d399fed81a09e7d7c53ed
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Oct 22 13:47:38 2015 -1000

    	* call.c (add_conv_candidate): Remove first_arg parm.
    	(add_template_conv_candidate): Likewise.
    	(add_template_candidate_real): Don't pass it.
    	(build_op_call_1): Likewise.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index b7cf031..93dd86a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -178,9 +178,6 @@ static struct z_candidate *add_template_candidate
 static struct z_candidate *add_template_candidate_real
 	(struct z_candidate **, tree, tree, tree, tree, const vec<tree, va_gc> *,
 	 tree, tree, tree, int, tree, unification_kind_t, tsubst_flags_t);
-static struct z_candidate *add_template_conv_candidate
-	(struct z_candidate **, tree, tree, tree, const vec<tree, va_gc> *,
-	 tree, tree, tree, tsubst_flags_t);
 static void add_builtin_candidates
 	(struct z_candidate **, enum tree_code, enum tree_code,
 	 tree, tree *, int, tsubst_flags_t);
@@ -192,7 +189,7 @@ static void build_builtin_candidate
 	(struct z_candidate **, tree, tree, tree, tree *, tree *,
 	 int, tsubst_flags_t);
 static struct z_candidate *add_conv_candidate
-	(struct z_candidate **, tree, tree, tree, const vec<tree, va_gc> *, tree,
+	(struct z_candidate **, tree, tree, const vec<tree, va_gc> *, tree,
 	 tree, tsubst_flags_t);
 static struct z_candidate *add_function_candidate
 	(struct z_candidate **, tree, tree, tree, const vec<tree, va_gc> *, tree,
@@ -2176,7 +2173,7 @@ add_function_candidate (struct z_candidate **candidates,
 
 static struct z_candidate *
 add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
-		    tree first_arg, const vec<tree, va_gc> *arglist,
+		    const vec<tree, va_gc> *arglist,
 		    tree access_path, tree conversion_path,
 		    tsubst_flags_t complain)
 {
@@ -2190,7 +2187,7 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
     parmlist = TREE_TYPE (parmlist);
   parmlist = TYPE_ARG_TYPES (parmlist);
 
-  len = vec_safe_length (arglist) + (first_arg != NULL_TREE ? 1 : 0) + 1;
+  len = vec_safe_length (arglist) + 1;
   convs = alloc_conversions (len);
   parmnode = parmlist;
   viable = 1;
@@ -2208,10 +2205,8 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
 
       if (i == 0)
 	arg = obj;
-      else if (i == 1 && first_arg != NULL_TREE)
-	arg = first_arg;
       else
-	arg = (*arglist)[i - (first_arg != NULL_TREE ? 1 : 0) - 1];
+	arg = (*arglist)[i - 1];
       argtype = lvalue_type (arg);
 
       if (i == 0)
@@ -2260,7 +2255,7 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
       reason = arity_rejection (NULL_TREE, i + remaining, len);
     }
 
-  return add_candidate (candidates, totype, first_arg, arglist, len, convs,
+  return add_candidate (candidates, totype, obj, arglist, len, convs,
 			access_path, conversion_path, viable, reason, flags);
 }
 
@@ -3122,7 +3117,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
 
   if (obj != NULL_TREE)
     /* Aha, this is a conversion function.  */
-    cand = add_conv_candidate (candidates, fn, obj, first_arg, arglist,
+    cand = add_conv_candidate (candidates, fn, obj, arglist,
 			       access_path, conversion_path, complain);
   else
     cand = add_function_candidate (candidates, fn, ctype,
@@ -3175,14 +3170,14 @@ add_template_candidate (struct z_candidate **candidates, tree tmpl, tree ctype,
 
 static struct z_candidate *
 add_template_conv_candidate (struct z_candidate **candidates, tree tmpl,
-			     tree obj, tree first_arg,
+			     tree obj,
 			     const vec<tree, va_gc> *arglist,
 			     tree return_type, tree access_path,
 			     tree conversion_path, tsubst_flags_t complain)
 {
   return
     add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
-				 first_arg, arglist, return_type, access_path,
+				 NULL_TREE, arglist, return_type, access_path,
 				 conversion_path, 0, obj, DEDUCE_CONV,
 				 complain);
 }
@@ -4335,11 +4330,11 @@ build_op_call_1 (tree obj, vec<tree, va_gc> **args, tsubst_flags_t complain)
 
 	    if (TREE_CODE (fn) == TEMPLATE_DECL)
 	      add_template_conv_candidate
-		(&candidates, fn, obj, NULL_TREE, *args, totype,
+		(&candidates, fn, obj, *args, totype,
 		 /*access_path=*/NULL_TREE,
 		 /*conversion_path=*/NULL_TREE, complain);
 	    else
-	      add_conv_candidate (&candidates, fn, obj, NULL_TREE,
+	      add_conv_candidate (&candidates, fn, obj,
 				  *args, /*conversion_path=*/NULL_TREE,
 				  /*access_path=*/NULL_TREE, complain);
 	  }

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2015-10-23  0:38 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-23  2:13 C++ PATCH for template conversion function call Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).