Patchwork C++ PATCH to can_convert to support user-defined conversions

login
register
mail settings
Submitter Jason Merrill
Date July 13, 2013, 11:02 p.m.
Message ID <51E1DC84.20306@redhat.com>
Download mbox | patch
Permalink /patch/258870/
State New
Headers show

Comments

Jason Merrill - July 13, 2013, 11:02 p.m.
As came up in the review of the concepts lite code, can_convert 
currently doesn't allow user-defined conversions.  This is surprising, 
so we've renamed it to can_convert_standard and made the can_convert 
name allow them.  Users that could potentially call can_convert with 
arguments of class type have also been renamed; those that can only pass 
in pointers or the like have been left alone.  I also took the 
opportunity to tidy up a covariant return diagnostic.

Tested x86_64-pc-linux-gnu, applying to trunk.
Gabriel Dos Reis - July 15, 2013, 11:59 a.m.
On Sat, Jul 13, 2013 at 6:02 PM, Jason Merrill <jason@redhat.com> wrote:
> As came up in the review of the concepts lite code, can_convert currently
> doesn't allow user-defined conversions.  This is surprising, so we've
> renamed it to can_convert_standard and made the can_convert name allow them.
> Users that could potentially call can_convert with arguments of class type
> have also been renamed; those that can only pass in pointers or the like
> have been left alone.  I also took the opportunity to tidy up a covariant
> return diagnostic.
>
> Tested x86_64-pc-linux-gnu, applying to trunk.

Thanks, Jason.

-- Gaby

Patch

commit 17f84bee70fb11ac0a34d50584cfcfb5035b5360
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Jul 4 09:12:04 2013 -0700

    	* call.c (can_convert): Allow user-defined conversions.
    	(can_convert_standard): New.
    	* cp-tree.h: Declare it.
    	* cvt.c (convert_to_reference): Use it.
    	* pt.c (convert_nontype_argument): Likewise.
    	* search.c (check_final_overrider): Likewise.
    	Don't worry about user-defined conversions.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 78899ab..02daf82 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -8814,6 +8814,20 @@  tourney (struct z_candidate *candidates, tsubst_flags_t complain)
 bool
 can_convert (tree to, tree from, tsubst_flags_t complain)
 {
+  tree arg = NULL_TREE;
+  /* implicit_conversion only considers user-defined conversions
+     if it has an expression for the call argument list.  */
+  if (CLASS_TYPE_P (from) || CLASS_TYPE_P (to))
+    arg = build1 (CAST_EXPR, from, NULL_TREE);
+  return can_convert_arg (to, from, arg, LOOKUP_IMPLICIT, complain);
+}
+
+/* Returns nonzero if things of type FROM can be converted to TO with a
+   standard conversion.  */
+
+bool
+can_convert_standard (tree to, tree from, tsubst_flags_t complain)
+{
   return can_convert_arg (to, from, NULL_TREE, LOOKUP_IMPLICIT, complain);
 }
 
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1971bc5..a837d22 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5007,6 +5007,7 @@  extern tree build_op_delete_call		(enum tree_code, tree, tree,
 						 bool, tree, tree,
 						 tsubst_flags_t);
 extern bool can_convert				(tree, tree, tsubst_flags_t);
+extern bool can_convert_standard		(tree, tree, tsubst_flags_t);
 extern bool can_convert_arg			(tree, tree, tree, int,
 						 tsubst_flags_t);
 extern bool can_convert_arg_bad			(tree, tree, tree, int,
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index d9e905e..532e8fd 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -428,7 +428,7 @@  convert_to_reference (tree reftype, tree expr, int convtype,
 
   intype = TYPE_MAIN_VARIANT (intype);
 
-  can_convert_intype_to_type = can_convert (type, intype, complain);
+  can_convert_intype_to_type = can_convert_standard (type, intype, complain);
 
   if (!can_convert_intype_to_type
       && (convtype & CONV_IMPLICIT) && MAYBE_CLASS_TYPE_P (intype)
@@ -449,7 +449,8 @@  convert_to_reference (tree reftype, tree expr, int convtype,
 	}
     }
 
-  if (((convtype & CONV_STATIC) && can_convert (intype, type, complain))
+  if (((convtype & CONV_STATIC)
+       && can_convert_standard (intype, type, complain))
       || ((convtype & CONV_IMPLICIT) && can_convert_intype_to_type))
     {
       {
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 877d3b7..de054ac 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5854,7 +5854,7 @@  convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
 		 "because it is of type %qT", expr, type,
 		 TREE_TYPE (expr));
 	  /* If we are just one standard conversion off, explain.  */
-	  if (can_convert (type, TREE_TYPE (expr), complain))
+	  if (can_convert_standard (type, TREE_TYPE (expr), complain))
 	    inform (input_location,
 		    "standard conversions are not allowed in this context");
 	  return NULL_TREE;
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index b113477..166ac11 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -1889,22 +1889,16 @@  check_final_overrider (tree overrider, tree basefn)
 		fail = 1;
 	    }
 	}
-      else if (!pedantic
-	       && can_convert (TREE_TYPE (base_type), TREE_TYPE (over_type),
-			       tf_warning_or_error))
+      else if (can_convert_standard (TREE_TYPE (base_type),
+				     TREE_TYPE (over_type),
+				     tf_warning_or_error))
 	/* GNU extension, allow trivial pointer conversions such as
 	   converting to void *, or qualification conversion.  */
 	{
-	  /* can_convert will permit user defined conversion from a
-	     (reference to) class type. We must reject them.  */
-	  if (CLASS_TYPE_P (non_reference (over_return)))
-	    fail = 2;
-	  else
-	    {
-	      warning (0, "deprecated covariant return type for %q+#D",
-			     overrider);
-	      warning (0, "  overriding %q+#D", basefn);
-	    }
+	  if (pedwarn (DECL_SOURCE_LOCATION (overrider), 0,
+		       "invalid covariant return type for %q#D", overrider))
+	    inform (DECL_SOURCE_LOCATION (basefn),
+		    "  overriding %q+#D", basefn);
 	}
       else
 	fail = 2;