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)

Reply via email to