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.
commit 17f84bee70fb11ac0a34d50584cfcfb5035b5360
Author: Jason Merrill <ja...@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;