We weren't protecting all errors in convert_like_real with a complain
check. So this patch adds one at the top of the file to handle all
bad_p cases. The second patch then removes various checks in the rest
of the function that are now redundant.
Tested x86_64-pc-linux-gnu, applying to trunk. Also applying the first
patch to 4.6.
commit 1ad44870bd7ed3478efa5c0feb0c14e19a4060da
Author: Jason Merrill <ja...@redhat.com>
Date: Wed Aug 24 06:15:19 2011 -0400
PR c++/50157
* call.c (convert_like_real): Exit early if bad and !tf_error.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index e5f65b3..d911b3a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5642,6 +5642,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
diagnostic_t diag_kind;
int flags;
+ if (convs->bad_p && !(complain & tf_error))
+ return error_mark_node;
+
if (convs->bad_p
&& convs->kind != ck_user
&& convs->kind != ck_list
@@ -5688,15 +5691,12 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
else if (t->kind == ck_identity)
break;
}
- if (complain & tf_error)
- {
- permerror (input_location, "invalid conversion from %qT to %qT", TREE_TYPE (expr), totype);
- if (fn)
- permerror (DECL_SOURCE_LOCATION (fn),
- " initializing argument %P of %qD", argnum, fn);
- }
- else
- return error_mark_node;
+
+ permerror (input_location, "invalid conversion from %qT to %qT",
+ TREE_TYPE (expr), totype);
+ if (fn)
+ permerror (DECL_SOURCE_LOCATION (fn),
+ " initializing argument %P of %qD", argnum, fn);
return cp_convert (totype, expr);
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae27.C b/gcc/testsuite/g++.dg/cpp0x/sfinae27.C
new file mode 100644
index 0000000..93327ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae27.C
@@ -0,0 +1,20 @@
+// PR c++/50157
+// { dg-options -std=c++0x }
+
+template<class T>
+T val();
+
+template<class T, class Arg, class =
+ decltype(::new T(val<Arg>()))
+>
+auto test(int) -> char;
+
+template<class, class>
+auto test(...) -> char (&)[2];
+
+struct P {
+ explicit operator bool(); // (#13)
+};
+
+typedef decltype(test<bool, P>(0)) type; // OK
+typedef decltype(test<float, P>(0)) type2; // Error (#17)
commit abc6432b98ce7b149d52c00c4e9285f88da8e96c
Author: Jason Merrill <ja...@redhat.com>
Date: Wed Aug 24 12:15:46 2011 -0400
* call.c (convert_like_real): Remove redundant complain checks.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index d911b3a..dc35824 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5733,11 +5733,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
empty list, since that is handled separately in 8.5.4. */
&& cand->num_convs > 0)
{
- if (complain & tf_error)
- error ("converting to %qT from initializer list would use "
- "explicit constructor %qD", totype, convfn);
- else
- return error_mark_node;
+ error ("converting to %qT from initializer list would use "
+ "explicit constructor %qD", totype, convfn);
}
/* Set user_conv_p on the argument conversions, so rvalue/base
@@ -5789,6 +5786,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
}
return expr;
case ck_ambig:
+ /* We leave bad_p off ck_ambig because overload resolution considers
+ it valid, it just fails when we try to perform it. So we need to
+ check complain here, too. */
if (complain & tf_error)
{
/* Call build_user_type_conversion again for the error. */
@@ -5899,14 +5899,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
/* Copy-list-initialization doesn't actually involve a copy. */
return expr;
expr = build_temp (expr, totype, flags, &diag_kind, complain);
- if (diag_kind && fn)
- {
- if ((complain & tf_error))
- emit_diagnostic (diag_kind, DECL_SOURCE_LOCATION (fn), 0,
- " initializing argument %P of %qD", argnum, fn);
- else if (diag_kind == DK_ERROR)
- return error_mark_node;
- }
+ if (diag_kind && fn && complain)
+ emit_diagnostic (diag_kind, DECL_SOURCE_LOCATION (fn), 0,
+ " initializing argument %P of %qD", argnum, fn);
return build_cplus_new (totype, expr, complain);
case ck_ref_bind:
@@ -5916,13 +5911,10 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
if (convs->bad_p && TYPE_REF_IS_RVALUE (ref_type)
&& real_lvalue_p (expr))
{
- if (complain & tf_error)
- {
- error ("cannot bind %qT lvalue to %qT",
- TREE_TYPE (expr), totype);
- if (fn)
- error (" initializing argument %P of %q+D", argnum, fn);
- }
+ error ("cannot bind %qT lvalue to %qT",
+ TREE_TYPE (expr), totype);
+ if (fn)
+ error (" initializing argument %P of %q+D", argnum, fn);
return error_mark_node;
}
@@ -5948,19 +5940,16 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
if (!CP_TYPE_CONST_NON_VOLATILE_P (type)
&& !TYPE_REF_IS_RVALUE (ref_type))
{
- if (complain & tf_error)
- {
- /* If the reference is volatile or non-const, we
- cannot create a temporary. */
- if (lvalue & clk_bitfield)
- error ("cannot bind bitfield %qE to %qT",
- expr, ref_type);
- else if (lvalue & clk_packed)
- error ("cannot bind packed field %qE to %qT",
- expr, ref_type);
- else
- error ("cannot bind rvalue %qE to %qT", expr, ref_type);
- }
+ /* If the reference is volatile or non-const, we
+ cannot create a temporary. */
+ if (lvalue & clk_bitfield)
+ error ("cannot bind bitfield %qE to %qT",
+ expr, ref_type);
+ else if (lvalue & clk_packed)
+ error ("cannot bind packed field %qE to %qT",
+ expr, ref_type);
+ else
+ error ("cannot bind rvalue %qE to %qT", expr, ref_type);
return error_mark_node;
}
/* If the source is a packed field, and we must use a copy
@@ -5973,9 +5962,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
&& CLASS_TYPE_P (type)
&& type_has_nontrivial_copy_init (type))
{
- if (complain & tf_error)
- error ("cannot bind packed field %qE to %qT",
- expr, ref_type);
+ error ("cannot bind packed field %qE to %qT",
+ expr, ref_type);
return error_mark_node;
}
if (lvalue & clk_bitfield)