diff mbox

[C++] PR 52363

Message ID 4F90C34E.3030606@oracle.com
State New
Headers show

Commit Message

Paolo Carlini April 20, 2012, 2 a.m. UTC
On 04/19/2012 09:20 PM, Jason Merrill wrote:
> On 04/19/2012 03:00 PM, Paolo Carlini wrote:
>> Yes, that's life ;) Seriously, if we want to avoid all those having 
>> to do with implicit_conversion in one swoop, the eventual patch will 
>> be pretty big, should I just go on and on?
>
> I think so.  Once we start down this road, we should follow it to the end.
OK. Here is a new version of the work (three times as big ;) with which 
I'm personally rather happy: eg, no more tf_warning_or_error in the 
whole call.c, besides an handful of uses in build_* calls.

Booted and tested x86_64-linux

Thanks!
Paolo.

/////////////////////////
/cp
2012-04-20  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/52363
	* call.c (tourney, perform_overload_resolution,
	build_operator_new_call, build_user_type_conversion_1,
	build_user_type_conversion, perform_overload_resolution,
	add_template_candidate, add_template_candidate_real,
	add_template_conv_candidate, add_builtin_candidates,
	add_builtin_candidate, build_builtin_candidate,
	add_conv_candidate, add_function_candidate, implicit_conversion,
	reference_binding, build_list_conv, conditional_conversion,
	add_candidates, can_convert_array, build_aggr_conv,
	build_array_conv, build_complex_conv, conditional_conversion):
	Add tsubst_flags_t parameter.
	(joust): Likewise, use it to handle SFINAE as if pedantic.
	(add_list_candidates, build_integral_nontype_arg_conv,
	perform_overload_resolution, build_new_function_call,
	build_operator_new_call, build_op_call_1, 
	build_conditional_expr_1, build_new_op_1, convert_like_real,
	convert_arg_to_ellipsis, convert_default_arg,
	convert_for_arg_passing, build_over_call,
	build_new_method_call_1, can_convert_arg, can_convert_arg_bad,
	perform_implicit_conversion_flags,
	perform_direct_initialization_if_possible,
	initialize_reference): Adjust.
	* typeck.c (casts_away_constness, casts_away_constness_r):
	Add tsubst_flags_t parameter.
	(convert_arguments, check_for_casting_away_constness,
	build_static_cast_1, build_ptrmemfunc, convert_for_assignment):
	Adjust.
	* decl.c (reshape_init_r, check_default_argument): Likewise.
	* cp-gimplify.c (cxx_omp_clause_apply_fn): Likewise.
	* pt.c (convert_nontype_argument, check_non_deducible_conversion):
	Likewise.
	* init.c (build_new_1): Likewise.
	* cvt.c (convert_to_reference, ocp_convert, build_type_conversion,
	build_expr_type_conversion, ): Likewise.
	* search.c (check_final_overrider): Likewise.
	* cp-tree.h (build_user_type_conversion,
	build_operator_new_call, can_convert, can_convert_arg,
	can_convert_arg_bad, convert_default_arg,
	convert_arg_to_ellipsis, convert_for_arg_passing):
	Adjust declaration.

/testsuite
2012-04-20  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/52363
	* testsuite/g++.dg/cpp0x/sfinae35.C: New.
	* testsuite/g++.dg/cpp0x/sfinae36.C: Likewise.

Comments

Jason Merrill April 24, 2012, 3:33 p.m. UTC | #1
OK, thanks!

Jason
diff mbox

Patch

Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 186600)
+++ cp/typeck.c	(working copy)
@@ -55,8 +55,8 @@  static bool comp_except_types (tree, tree, bool);
 static bool comp_array_types (const_tree, const_tree, bool);
 static tree pointer_diff (tree, tree, tree);
 static tree get_delta_difference (tree, tree, bool, bool, tsubst_flags_t);
-static void casts_away_constness_r (tree *, tree *);
-static bool casts_away_constness (tree, tree);
+static void casts_away_constness_r (tree *, tree *, tsubst_flags_t);
+static bool casts_away_constness (tree, tree, tsubst_flags_t);
 static void maybe_warn_about_returning_address_of_local (tree);
 static tree lookup_destructor (tree, tree, tree);
 static void warn_args_num (location_t, tree, bool);
@@ -3489,7 +3489,7 @@  convert_arguments (tree typelist, VEC(tree,gc) **v
 	      parmval = convert_for_initialization
 		(NULL_TREE, type, val, flags,
 		 ICR_ARGPASS, fndecl, i, complain);
-	      parmval = convert_for_arg_passing (type, parmval);
+	      parmval = convert_for_arg_passing (type, parmval, complain);
 	    }
 
 	  if (parmval == error_mark_node)
@@ -3506,7 +3506,7 @@  convert_arguments (tree typelist, VEC(tree,gc) **v
 	       types.  */
 	    val = require_complete_type_sfinae (val, complain);
 	  else
-	    val = convert_arg_to_ellipsis (val);
+	    val = convert_arg_to_ellipsis (val, complain);
 
 	  VEC_replace (tree, *values, i, val);
 	}
@@ -3532,7 +3532,7 @@  convert_arguments (tree typelist, VEC(tree,gc) **v
 	      tree parmval
 		= convert_default_arg (TREE_VALUE (typetail),
 				       TREE_PURPOSE (typetail),
-				       fndecl, i);
+				       fndecl, i, complain);
 
 	      if (parmval == error_mark_node)
 		return -1;
@@ -5771,7 +5771,7 @@  check_for_casting_away_constness (tree src_type, t
   if (cast == CAST_EXPR && !warn_cast_qual)
     return false;
   
-  if (!casts_away_constness (src_type, dest_type))
+  if (!casts_away_constness (src_type, dest_type, complain))
     return false;
 
   switch (cast)
@@ -5921,7 +5921,8 @@  build_static_cast_1 (tree type, tree expr, bool c_
       && DERIVED_FROM_P (intype, TREE_TYPE (type))
       && can_convert (build_pointer_type (TYPE_MAIN_VARIANT (intype)),
 		      build_pointer_type (TYPE_MAIN_VARIANT
-					  (TREE_TYPE (type))))
+					  (TREE_TYPE (type))),
+		      complain)
       && (c_cast_p
 	  || at_least_as_qualified_p (TREE_TYPE (type), intype)))
     {
@@ -6048,7 +6049,8 @@  build_static_cast_1 (tree type, tree expr, bool c_
       && can_convert (build_pointer_type (TYPE_MAIN_VARIANT
 					  (TREE_TYPE (intype))),
 		      build_pointer_type (TYPE_MAIN_VARIANT
-					  (TREE_TYPE (type)))))
+					  (TREE_TYPE (type))),
+		      complain))
     {
       tree base;
 
@@ -6089,7 +6091,7 @@  build_static_cast_1 (tree type, tree expr, bool c_
 	  t1 = intype;
 	  t2 = type;
 	}
-      if (can_convert (t1, t2) || can_convert (t2, t1))
+      if (can_convert (t1, t2, complain) || can_convert (t2, t1, complain))
 	{
 	  if (!c_cast_p
 	      && check_for_casting_away_constness (intype, type,
@@ -7290,7 +7292,8 @@  build_ptrmemfunc (tree type, tree pfn, int force,
       tree n;
 
       if (!force
-	  && !can_convert_arg (to_type, TREE_TYPE (pfn), pfn, LOOKUP_NORMAL))
+	  && !can_convert_arg (to_type, TREE_TYPE (pfn), pfn,
+			       LOOKUP_NORMAL, complain))
 	error ("invalid conversion to type %qT from type %qT",
 	       to_type, pfn_type);
 
@@ -7555,7 +7558,7 @@  convert_for_assignment (tree type, tree rhs,
      We allow bad conversions here because by the time we get to this point
      we are committed to doing the conversion.  If we end up doing a bad
      conversion, convert_like will complain.  */
-  if (!can_convert_arg_bad (type, rhstype, rhs, flags))
+  if (!can_convert_arg_bad (type, rhstype, rhs, flags, complain))
     {
       /* When -Wno-pmf-conversions is use, we just silently allow
 	 conversions from pointers-to-members to plain pointers.  If
@@ -8408,7 +8411,7 @@  cp_apply_type_quals_to_decl (int type_quals, tree
    if and only if there is no implicit conversion from T1 to T2.  */
 
 static void
-casts_away_constness_r (tree *t1, tree *t2)
+casts_away_constness_r (tree *t1, tree *t2, tsubst_flags_t complain)
 {
   int quals1;
   int quals2;
@@ -8458,7 +8461,7 @@  static void
   else
     *t2 = TREE_TYPE (*t2);
 
-  casts_away_constness_r (t1, t2);
+  casts_away_constness_r (t1, t2, complain);
   *t1 = build_pointer_type (*t1);
   *t2 = build_pointer_type (*t2);
   *t1 = cp_build_qualified_type (*t1, quals1);
@@ -8474,7 +8477,7 @@  static void
 */
 
 static bool
-casts_away_constness (tree t1, tree t2)
+casts_away_constness (tree t1, tree t2, tsubst_flags_t complain)
 {
   if (TREE_CODE (t2) == REFERENCE_TYPE)
     {
@@ -8486,7 +8489,8 @@  static bool
 	 casts away constness.  */
       t1 = (TREE_CODE (t1) == REFERENCE_TYPE ? TREE_TYPE (t1) : t1);
       return casts_away_constness (build_pointer_type (t1),
-				   build_pointer_type (TREE_TYPE (t2)));
+				   build_pointer_type (TREE_TYPE (t2)),
+				   complain);
     }
 
   if (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2))
@@ -8499,7 +8503,8 @@  static bool
        constness.  */
     return casts_away_constness
       (build_pointer_type (TYPE_PTRMEM_POINTED_TO_TYPE (t1)),
-       build_pointer_type (TYPE_PTRMEM_POINTED_TO_TYPE (t2)));
+       build_pointer_type (TYPE_PTRMEM_POINTED_TO_TYPE (t2)),
+       complain);
 
   /* Casting away constness is only something that makes sense for
      pointer or reference types.  */
@@ -8510,8 +8515,8 @@  static bool
   /* Top-level qualifiers don't matter.  */
   t1 = TYPE_MAIN_VARIANT (t1);
   t2 = TYPE_MAIN_VARIANT (t2);
-  casts_away_constness_r (&t1, &t2);
-  if (!can_convert (t2, t1))
+  casts_away_constness_r (&t1, &t2, complain);
+  if (!can_convert (t2, t1, complain))
     return true;
 
   return false;
Index: cp/init.c
===================================================================
--- cp/init.c	(revision 186600)
+++ cp/init.c	(working copy)
@@ -2381,7 +2381,7 @@  build_new_1 (VEC(tree,gc) **placement, tree type,
 
 	  alloc_call = build_operator_new_call (fnname, placement,
 						&size, &cookie_size,
-						&alloc_fn);
+						&alloc_fn, complain);
 	}
     }
 
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 186600)
+++ cp/decl.c	(working copy)
@@ -5266,7 +5266,8 @@  reshape_init_r (tree type, reshape_iter *d, bool f
 	 valid aggregate initialization.  */
       && !first_initializer_p
       && (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (init))
-	  || can_convert_arg (type, TREE_TYPE (init), init, LOOKUP_NORMAL)))
+	  || can_convert_arg (type, TREE_TYPE (init), init, LOOKUP_NORMAL,
+			      complain)))
     {
       d->cur++;
       return init;
@@ -10602,7 +10603,8 @@  check_default_argument (tree decl, tree arg)
      A default argument expression is implicitly converted to the
      parameter type.  */
   if (!TREE_TYPE (arg)
-      || !can_convert_arg (decl_type, TREE_TYPE (arg), arg, LOOKUP_NORMAL))
+      || !can_convert_arg (decl_type, TREE_TYPE (arg), arg, LOOKUP_NORMAL,
+			   tf_warning_or_error))
     {
       if (decl)
 	error ("default argument for %q#D has type %qT",
Index: cp/cp-gimplify.c
===================================================================
--- cp/cp-gimplify.c	(revision 186600)
+++ cp/cp-gimplify.c	(working copy)
@@ -1273,7 +1273,8 @@  cxx_omp_clause_apply_fn (tree fn, tree arg1, tree
       for (parm = defparm; parm && parm != void_list_node;
 	   parm = TREE_CHAIN (parm), i++)
 	argarray[i] = convert_default_arg (TREE_VALUE (parm),
-					   TREE_PURPOSE (parm), fn, i);
+					   TREE_PURPOSE (parm), fn, i,
+					   tf_warning_or_error);
       t = build_call_a (fn, i, argarray);
       t = fold_convert (void_type_node, t);
       t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
@@ -1306,7 +1307,7 @@  cxx_omp_clause_apply_fn (tree fn, tree arg1, tree
 	   parm = TREE_CHAIN (parm), i++)
 	argarray[i] = convert_default_arg (TREE_VALUE (parm),
 					   TREE_PURPOSE (parm),
-					   fn, i);
+					   fn, i, tf_warning_or_error);
       t = build_call_a (fn, i, argarray);
       t = fold_convert (void_type_node, t);
       return fold_build_cleanup_point_expr (TREE_TYPE (t), t);
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 186600)
+++ cp/pt.c	(working copy)
@@ -6063,7 +6063,7 @@  convert_nontype_argument (tree type, tree expr, ts
 		 "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)))
+	  if (can_convert (type, TREE_TYPE (expr), complain))
 	    inform (input_location,
 		    "standard conversions are not allowed in this context");
 	  return NULL_TREE;
@@ -15128,14 +15128,15 @@  check_non_deducible_conversion (tree parm, tree ar
 
   if (strict == DEDUCE_CONV)
     {
-      if (can_convert_arg (type, parm, NULL_TREE, flags))
+      if (can_convert_arg (type, parm, NULL_TREE, flags,
+			   explain_p ? tf_warning_or_error : tf_none))
 	return unify_success (explain_p);
     }
   else if (strict != DEDUCE_EXACT)
     {
       if (can_convert_arg (parm, type,
 			   TYPE_P (arg) ? NULL_TREE : arg,
-			   flags))
+			   flags, explain_p ? tf_warning_or_error : tf_none))
 	return unify_success (explain_p);
     }
 
Index: cp/call.c
===================================================================
--- cp/call.c	(revision 186600)
+++ cp/call.c	(working copy)
@@ -142,9 +142,10 @@  static struct obstack conversion_obstack;
 static bool conversion_obstack_initialized;
 struct rejection_reason;
 
-static struct z_candidate * tourney (struct z_candidate *);
+static struct z_candidate * tourney (struct z_candidate *, tsubst_flags_t);
 static int equal_functions (tree, tree);
-static int joust (struct z_candidate *, struct z_candidate *, bool);
+static int joust (struct z_candidate *, struct z_candidate *, bool,
+		  tsubst_flags_t);
 static int compare_ics (conversion *, conversion *);
 static tree build_over_call (struct z_candidate *, int, tsubst_flags_t);
 static tree build_java_interface_fn_ref (tree, tree);
@@ -160,7 +161,8 @@  static tree convert_like_real (conversion *, tree,
 			       bool, tsubst_flags_t);
 static void op_error (enum tree_code, enum tree_code, tree, tree,
 		      tree, bool);
-static struct z_candidate *build_user_type_conversion_1 (tree, tree, int);
+static struct z_candidate *build_user_type_conversion_1 (tree, tree, int,
+							 tsubst_flags_t);
 static void print_z_candidate (const char *, struct z_candidate *);
 static void print_z_candidates (location_t, struct z_candidate *);
 static tree build_this (tree);
@@ -168,34 +170,36 @@  static struct z_candidate *splice_viable (struct z
 static bool any_strictly_viable (struct z_candidate *);
 static struct z_candidate *add_template_candidate
 	(struct z_candidate **, tree, tree, tree, tree, const VEC(tree,gc) *,
-	 tree, tree, tree, int, unification_kind_t);
+	 tree, tree, tree, int, unification_kind_t, tsubst_flags_t);
 static struct z_candidate *add_template_candidate_real
 	(struct z_candidate **, tree, tree, tree, tree, const VEC(tree,gc) *,
-	 tree, tree, tree, int, tree, unification_kind_t);
+	 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,gc) *, tree,
-	 tree, tree);
+	 tree, tree, tsubst_flags_t);
 static void add_builtin_candidates
 	(struct z_candidate **, enum tree_code, enum tree_code,
-	 tree, tree *, int);
+	 tree, tree *, int, tsubst_flags_t);
 static void add_builtin_candidate
 	(struct z_candidate **, enum tree_code, enum tree_code,
-	 tree, tree, tree, tree *, tree *, int);
+	 tree, tree, tree, tree *, tree *, int, tsubst_flags_t);
 static bool is_complete (tree);
 static void build_builtin_candidate
 	(struct z_candidate **, tree, tree, tree, tree *, tree *,
-	 int);
+	 int, tsubst_flags_t);
 static struct z_candidate *add_conv_candidate
 	(struct z_candidate **, tree, tree, tree, const VEC(tree,gc) *, tree,
-	 tree);
+	 tree, tsubst_flags_t);
 static struct z_candidate *add_function_candidate
 	(struct z_candidate **, tree, tree, tree, const VEC(tree,gc) *, tree,
-	 tree, int);
-static conversion *implicit_conversion (tree, tree, tree, bool, int);
+	 tree, int, tsubst_flags_t);
+static conversion *implicit_conversion (tree, tree, tree, bool, int,
+					tsubst_flags_t);
 static conversion *standard_conversion (tree, tree, tree, bool, int);
-static conversion *reference_binding (tree, tree, tree, bool, int);
+static conversion *reference_binding (tree, tree, tree, bool, int,
+				      tsubst_flags_t);
 static conversion *build_conv (conversion_kind, tree, conversion *);
-static conversion *build_list_conv (tree, tree, int);
+static conversion *build_list_conv (tree, tree, int, tsubst_flags_t);
 static conversion *next_conversion (conversion *);
 static bool is_subseq (conversion *, conversion *);
 static conversion *maybe_handle_ref_bind (conversion **);
@@ -208,11 +212,12 @@  static void add_warning (struct z_candidate *, str
 static bool reference_compatible_p (tree, tree);
 static conversion *direct_reference_binding (tree, conversion *);
 static bool promoted_arithmetic_type_p (tree);
-static conversion *conditional_conversion (tree, tree);
+static conversion *conditional_conversion (tree, tree, tsubst_flags_t);
 static char *name_as_c_string (tree, tree, bool *);
 static tree prep_operand (tree);
 static void add_candidates (tree, tree, const VEC(tree,gc) *, tree, tree, bool,
-			    tree, tree, int, struct z_candidate **);
+			    tree, tree, int, struct z_candidate **,
+			    tsubst_flags_t);
 static conversion *merge_conversion_sequences (conversion *, conversion *);
 static bool magic_varargs_p (tree);
 static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t);
@@ -793,7 +798,7 @@  build_conv (conversion_kind code, tree type, conve
    possible.  */
 
 static conversion *
-build_list_conv (tree type, tree ctor, int flags)
+build_list_conv (tree type, tree ctor, int flags, tsubst_flags_t complain)
 {
   tree elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (type), 0);
   unsigned len = CONSTRUCTOR_NELTS (ctor);
@@ -812,7 +817,7 @@  static conversion *
     {
       conversion *sub
 	= implicit_conversion (elttype, TREE_TYPE (val), val,
-			       false, flags);
+			       false, flags, complain);
       if (sub == NULL)
 	return NULL;
 
@@ -857,7 +862,7 @@  next_conversion (conversion *conv)
    is a valid aggregate initializer for array type ATYPE.  */
 
 static bool
-can_convert_array (tree atype, tree ctor, int flags)
+can_convert_array (tree atype, tree ctor, int flags, tsubst_flags_t complain)
 {
   unsigned i;
   tree elttype = TREE_TYPE (atype);
@@ -867,9 +872,10 @@  static bool
       bool ok;
       if (TREE_CODE (elttype) == ARRAY_TYPE
 	  && TREE_CODE (val) == CONSTRUCTOR)
-	ok = can_convert_array (elttype, val, flags);
+	ok = can_convert_array (elttype, val, flags, complain);
       else
-	ok = can_convert_arg (elttype, TREE_TYPE (val), val, flags);
+	ok = can_convert_arg (elttype, TREE_TYPE (val), val, flags,
+			      complain);
       if (!ok)
 	return false;
     }
@@ -880,7 +886,7 @@  static bool
    aggregate class, if such a conversion is possible.  */
 
 static conversion *
-build_aggr_conv (tree type, tree ctor, int flags)
+build_aggr_conv (tree type, tree ctor, int flags, tsubst_flags_t complain)
 {
   unsigned HOST_WIDE_INT i = 0;
   conversion *c;
@@ -909,9 +915,10 @@  static conversion *
 
       if (TREE_CODE (ftype) == ARRAY_TYPE
 	  && TREE_CODE (val) == CONSTRUCTOR)
-	ok = can_convert_array (ftype, val, flags);
+	ok = can_convert_array (ftype, val, flags, complain);
       else
-	ok = can_convert_arg (ftype, TREE_TYPE (val), val, flags);
+	ok = can_convert_arg (ftype, TREE_TYPE (val), val, flags,
+			      complain);
 
       if (!ok)
 	return NULL;
@@ -935,7 +942,7 @@  static conversion *
    array type, if such a conversion is possible.  */
 
 static conversion *
-build_array_conv (tree type, tree ctor, int flags)
+build_array_conv (tree type, tree ctor, int flags, tsubst_flags_t complain)
 {
   conversion *c;
   unsigned HOST_WIDE_INT len = CONSTRUCTOR_NELTS (ctor);
@@ -957,7 +964,7 @@  static conversion *
     {
       conversion *sub
 	= implicit_conversion (elttype, TREE_TYPE (val), val,
-			       false, flags);
+			       false, flags, complain);
       if (sub == NULL)
 	return NULL;
 
@@ -982,7 +989,8 @@  static conversion *
    complex type, if such a conversion is possible.  */
 
 static conversion *
-build_complex_conv (tree type, tree ctor, int flags)
+build_complex_conv (tree type, tree ctor, int flags,
+		    tsubst_flags_t complain)
 {
   conversion *c;
   unsigned HOST_WIDE_INT len = CONSTRUCTOR_NELTS (ctor);
@@ -1000,7 +1008,7 @@  static conversion *
     {
       conversion *sub
 	= implicit_conversion (elttype, TREE_TYPE (val), val,
-			       false, flags);
+			       false, flags, complain);
       if (sub == NULL)
 	return NULL;
 
@@ -1438,7 +1446,8 @@  direct_reference_binding (tree type, conversion *c
    conversion is coming from a C-style cast.  */
 
 static conversion *
-reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
+reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
+		   tsubst_flags_t complain)
 {
   conversion *conv = NULL;
   tree to = TREE_TYPE (rto);
@@ -1461,7 +1470,7 @@  static conversion *
     {
       maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
       conv = implicit_conversion (to, from, expr, c_cast_p,
-				  flags);
+				  flags, complain);
       if (!CLASS_TYPE_P (to)
 	  && CONSTRUCTOR_NELTS (expr) == 1)
 	{
@@ -1597,7 +1606,8 @@  static conversion *
 
 	the reference is bound to the lvalue result of the conversion
 	in the second case.  */
-      z_candidate *cand = build_user_type_conversion_1 (rto, expr, flags);
+      z_candidate *cand = build_user_type_conversion_1 (rto, expr, flags,
+							complain);
       if (cand)
 	return cand->second_conv;
     }
@@ -1652,7 +1662,7 @@  static conversion *
 
   if (!conv)
     conv = implicit_conversion (to, from, expr, c_cast_p,
-				flags);
+				flags, complain);
   if (!conv)
     return NULL;
 
@@ -1672,7 +1682,7 @@  static conversion *
 
 static conversion *
 implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
-		     int flags)
+		     int flags, tsubst_flags_t complain)
 {
   conversion *conv;
 
@@ -1687,7 +1697,7 @@  implicit_conversion (tree to, tree from, tree expr
 	    |LOOKUP_NO_NARROWING|LOOKUP_PROTECT);
 
   if (TREE_CODE (to) == REFERENCE_TYPE)
-    conv = reference_binding (to, from, expr, c_cast_p, flags);
+    conv = reference_binding (to, from, expr, c_cast_p, flags, complain);
   else
     conv = standard_conversion (to, from, expr, c_cast_p, flags);
 
@@ -1697,12 +1707,12 @@  implicit_conversion (tree to, tree from, tree expr
   if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr))
     {
       if (is_std_init_list (to))
-	return build_list_conv (to, expr, flags);
+	return build_list_conv (to, expr, flags, complain);
 
       /* As an extension, allow list-initialization of _Complex.  */
       if (TREE_CODE (to) == COMPLEX_TYPE)
 	{
-	  conv = build_complex_conv (to, expr, flags);
+	  conv = build_complex_conv (to, expr, flags, complain);
 	  if (conv)
 	    return conv;
 	}
@@ -1722,7 +1732,7 @@  implicit_conversion (tree to, tree from, tree expr
 	    elt = error_mark_node;
 
 	  conv = implicit_conversion (to, TREE_TYPE (elt), elt,
-				      c_cast_p, flags);
+				      c_cast_p, flags, complain);
 	  if (conv)
 	    {
 	      conv->check_narrowing = true;
@@ -1733,7 +1743,7 @@  implicit_conversion (tree to, tree from, tree expr
 	    }
 	}
       else if (TREE_CODE (to) == ARRAY_TYPE)
-	return build_array_conv (to, expr, flags);
+	return build_array_conv (to, expr, flags, complain);
     }
 
   if (expr != NULL_TREE
@@ -1746,9 +1756,9 @@  implicit_conversion (tree to, tree from, tree expr
       if (CLASS_TYPE_P (to)
 	  && BRACE_ENCLOSED_INITIALIZER_P (expr)
 	  && !CLASSTYPE_NON_AGGREGATE (complete_type (to)))
-	return build_aggr_conv (to, expr, flags);
+	return build_aggr_conv (to, expr, flags, complain);
 
-      cand = build_user_type_conversion_1 (to, expr, flags);
+      cand = build_user_type_conversion_1 (to, expr, flags, complain);
       if (cand)
 	conv = cand->second_conv;
 
@@ -1818,7 +1828,8 @@  static struct z_candidate *
 add_function_candidate (struct z_candidate **candidates,
 			tree fn, tree ctype, tree first_arg,
 			const VEC(tree,gc) *args, tree access_path,
-			tree conversion_path, int flags)
+			tree conversion_path, int flags,
+			tsubst_flags_t complain)
 {
   tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
   int i, len;
@@ -1977,7 +1988,7 @@  add_function_candidate (struct z_candidate **candi
 	    lflags |= LOOKUP_ONLYCONVERTING;
 
 	  t = implicit_conversion (parmtype, argtype, arg,
-				   /*c_cast_p=*/false, lflags);
+				   /*c_cast_p=*/false, lflags, complain);
 	  to_type = parmtype;
 	}
       else
@@ -2025,7 +2036,8 @@  add_function_candidate (struct z_candidate **candi
 static struct z_candidate *
 add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
 		    tree first_arg, const VEC(tree,gc) *arglist,
-		    tree access_path, tree conversion_path)
+		    tree access_path, tree conversion_path,
+		    tsubst_flags_t complain)
 {
   tree totype = TREE_TYPE (TREE_TYPE (fn));
   int i, len, viable, flags;
@@ -2065,7 +2077,7 @@  add_conv_candidate (struct z_candidate **candidate
       if (i == 0)
 	{
 	  t = implicit_conversion (totype, argtype, arg, /*c_cast_p=*/false,
-				   flags);
+				   flags, complain);
 	  convert_type = totype;
 	}
       else if (parmnode == void_list_node)
@@ -2073,7 +2085,7 @@  add_conv_candidate (struct z_candidate **candidate
       else if (parmnode)
 	{
 	  t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg,
-				   /*c_cast_p=*/false, flags);
+				   /*c_cast_p=*/false, flags, complain);
 	  convert_type = TREE_VALUE (parmnode);
 	}
       else
@@ -2115,7 +2127,7 @@  add_conv_candidate (struct z_candidate **candidate
 static void
 build_builtin_candidate (struct z_candidate **candidates, tree fnname,
 			 tree type1, tree type2, tree *args, tree *argtypes,
-			 int flags)
+			 int flags, tsubst_flags_t complain)
 {
   conversion *t;
   conversion **convs;
@@ -2144,18 +2156,20 @@  build_builtin_candidate (struct z_candidate **cand
 	break;
 
       t = implicit_conversion (types[i], argtypes[i], args[i],
-			       /*c_cast_p=*/false, flags);
+			       /*c_cast_p=*/false, flags, complain);
       if (! t)
 	{
 	  viable = 0;
 	  /* We need something for printing the candidate.  */
 	  t = build_identity_conv (types[i], NULL_TREE);
-	  reason = arg_conversion_rejection (NULL_TREE, i, argtypes[i], types[i]);
+	  reason = arg_conversion_rejection (NULL_TREE, i, argtypes[i],
+					     types[i]);
 	}
       else if (t->bad_p)
 	{
 	  viable = 0;
-	  reason = bad_arg_conversion_rejection (NULL_TREE, i, argtypes[i], types[i]);
+	  reason = bad_arg_conversion_rejection (NULL_TREE, i, argtypes[i],
+						 types[i]);
 	}
       convs[i] = t;
     }
@@ -2166,7 +2180,8 @@  build_builtin_candidate (struct z_candidate **cand
       convs[2] = convs[1];
       convs[1] = convs[0];
       t = implicit_conversion (boolean_type_node, argtypes[2], args[2],
-			       /*c_cast_p=*/false, flags);
+			       /*c_cast_p=*/false, flags,
+			       complain);
       if (t)
 	convs[0] = t;
       else
@@ -2220,7 +2235,8 @@  promoted_arithmetic_type_p (tree type)
 static void
 add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
 		       enum tree_code code2, tree fnname, tree type1,
-		       tree type2, tree *args, tree *argtypes, int flags)
+		       tree type2, tree *args, tree *argtypes, int flags,
+		       tsubst_flags_t complain)
 {
   switch (code)
     {
@@ -2614,20 +2630,21 @@  add_builtin_candidate (struct z_candidate **candid
 	  if (cptype != error_mark_node)
 	    {
 	      build_builtin_candidate
-		(candidates, fnname, cptype, cptype, args, argtypes, flags);
+		(candidates, fnname, cptype, cptype, args, argtypes,
+		 flags, complain);
 	      return;
 	    }
 	}
 
       build_builtin_candidate
-	(candidates, fnname, type1, type1, args, argtypes, flags);
+	(candidates, fnname, type1, type1, args, argtypes, flags, complain);
       build_builtin_candidate
-	(candidates, fnname, type2, type2, args, argtypes, flags);
+	(candidates, fnname, type2, type2, args, argtypes, flags, complain);
       return;
     }
 
   build_builtin_candidate
-    (candidates, fnname, type1, type2, args, argtypes, flags);
+    (candidates, fnname, type1, type2, args, argtypes, flags, complain);
 }
 
 tree
@@ -2656,7 +2673,7 @@  type_decays_to (tree type)
 static void
 add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
 			enum tree_code code2, tree fnname, tree *args,
-			int flags)
+			int flags, tsubst_flags_t complain)
 {
   int ref1, i;
   int enum_p = 0;
@@ -2697,14 +2714,14 @@  add_builtin_candidates (struct z_candidate **candi
     case TRUTH_NOT_EXPR:
       build_builtin_candidate
 	(candidates, fnname, boolean_type_node,
-	 NULL_TREE, args, argtypes, flags);
+	 NULL_TREE, args, argtypes, flags, complain);
       return;
 
     case TRUTH_ORIF_EXPR:
     case TRUTH_ANDIF_EXPR:
       build_builtin_candidate
 	(candidates, fnname, boolean_type_node,
-	 boolean_type_node, args, argtypes, flags);
+	 boolean_type_node, args, argtypes, flags, complain);
       return;
 
     case ADDR_EXPR:
@@ -2810,11 +2827,11 @@  add_builtin_candidates (struct z_candidate **candi
 	FOR_EACH_VEC_ELT_REVERSE (tree, types[1], jx, u)
 	  add_builtin_candidate
 	    (candidates, code, code2, fnname, t,
-	     u, args, argtypes, flags);
+	     u, args, argtypes, flags, complain);
       else
 	add_builtin_candidate
 	  (candidates, code, code2, fnname, t,
-	   NULL_TREE, args, argtypes, flags);
+	   NULL_TREE, args, argtypes, flags, complain);
     }
 
   release_tree_vector (types[0]);
@@ -2837,7 +2854,8 @@  add_template_candidate_real (struct z_candidate **
 			     tree ctype, tree explicit_targs, tree first_arg,
 			     const VEC(tree,gc) *arglist, tree return_type,
 			     tree access_path, tree conversion_path,
-			     int flags, tree obj, unification_kind_t strict)
+			     int flags, tree obj, unification_kind_t strict,
+			     tsubst_flags_t complain)
 {
   int ntparms = DECL_NTPARMS (tmpl);
   tree targs = make_tree_vec (ntparms);
@@ -2958,11 +2976,11 @@  add_template_candidate_real (struct z_candidate **
   if (obj != NULL_TREE)
     /* Aha, this is a conversion function.  */
     cand = add_conv_candidate (candidates, fn, obj, first_arg, arglist,
-			       access_path, conversion_path);
+			       access_path, conversion_path, complain);
   else
     cand = add_function_candidate (candidates, fn, ctype,
 				   first_arg, arglist, access_path,
-				   conversion_path, flags);
+				   conversion_path, flags, complain);
   if (DECL_TI_TEMPLATE (fn) != tmpl)
     /* This situation can occur if a member template of a template
        class is specialized.  Then, instantiate_template might return
@@ -2998,13 +3016,13 @@  add_template_candidate (struct z_candidate **candi
 			tree explicit_targs, tree first_arg,
 			const VEC(tree,gc) *arglist, tree return_type,
 			tree access_path, tree conversion_path, int flags,
-			unification_kind_t strict)
+			unification_kind_t strict, tsubst_flags_t complain)
 {
   return
     add_template_candidate_real (candidates, tmpl, ctype,
 				 explicit_targs, first_arg, arglist,
 				 return_type, access_path, conversion_path,
-				 flags, NULL_TREE, strict);
+				 flags, NULL_TREE, strict, complain);
 }
 
 
@@ -3013,12 +3031,13 @@  add_template_conv_candidate (struct z_candidate **
 			     tree obj, tree first_arg,
 			     const VEC(tree,gc) *arglist,
 			     tree return_type, tree access_path,
-			     tree conversion_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,
-				 conversion_path, 0, obj, DEDUCE_CONV);
+				 conversion_path, 0, obj, DEDUCE_CONV,
+				 complain);
 }
 
 /* The CANDS are the set of candidates that were considered for
@@ -3341,7 +3360,8 @@  add_list_candidates (tree fns, tree first_arg,
 		     tree explicit_targs, bool template_only,
 		     tree conversion_path, tree access_path,
 		     int flags,
-		     struct z_candidate **candidates)
+		     struct z_candidate **candidates,
+		     tsubst_flags_t complain)
 {
   VEC(tree,gc) *args;
 
@@ -3365,7 +3385,7 @@  add_list_candidates (tree fns, tree first_arg,
       args = make_tree_vector_single (init_list);
       add_candidates (fns, first_arg, args, NULL_TREE,
 		      explicit_targs, template_only, conversion_path,
-		      access_path, flags, candidates);
+		      access_path, flags, candidates, complain);
       if (any_strictly_viable (*candidates))
 	return;
     }
@@ -3379,7 +3399,7 @@  add_list_candidates (tree fns, tree first_arg,
 
   add_candidates (fns, first_arg, args, NULL_TREE,
 		  explicit_targs, template_only, conversion_path,
-		  access_path, flags, candidates);
+		  access_path, flags, candidates, complain);
 }
 
 /* Returns the best overload candidate to perform the requested
@@ -3389,7 +3409,8 @@  add_list_candidates (tree fns, tree first_arg,
    per [dcl.init.ref], so we ignore temporary bindings.  */
 
 static struct z_candidate *
-build_user_type_conversion_1 (tree totype, tree expr, int flags)
+build_user_type_conversion_1 (tree totype, tree expr, int flags,
+			      tsubst_flags_t complain)
 {
   struct z_candidate *candidates, *cand;
   tree fromtype;
@@ -3460,14 +3481,14 @@  static struct z_candidate *
 	  /* List-initialization.  */
 	  add_list_candidates (ctors, first_arg, expr, totype, NULL_TREE,
 			       false, TYPE_BINFO (totype), TYPE_BINFO (totype),
-			       ctorflags, &candidates);
+			       ctorflags, &candidates, complain);
 	}
       else
 	{
 	  args = make_tree_vector_single (expr);
 	  add_candidates (ctors, first_arg, args, NULL_TREE, NULL_TREE, false,
 			  TYPE_BINFO (totype), TYPE_BINFO (totype),
-			  ctorflags, &candidates);
+			  ctorflags, &candidates, complain);
 	}
 
       for (cand = candidates; cand; cand = cand->next)
@@ -3508,7 +3529,7 @@  static struct z_candidate *
       add_candidates (TREE_VALUE (conv_fns), first_arg, NULL, totype,
 		      NULL_TREE, false,
 		      conversion_path, TYPE_BINFO (fromtype),
-		      flags, &candidates);
+		      flags, &candidates, complain);
 
       for (cand = candidates; cand != old_candidates; cand = cand->next)
 	{
@@ -3517,7 +3538,8 @@  static struct z_candidate *
 	    = implicit_conversion (totype,
 				   rettype,
 				   0,
-				   /*c_cast_p=*/false, convflags);
+				   /*c_cast_p=*/false, convflags,
+				   complain);
 
 	  /* If LOOKUP_NO_TEMP_BIND isn't set, then this is
 	     copy-initialization.  In that case, "The result of the
@@ -3582,13 +3604,14 @@  static struct z_candidate *
       return NULL;
     }
 
-  cand = tourney (candidates);
+  cand = tourney (candidates, complain);
   if (cand == 0)
     {
-      if (flags & LOOKUP_COMPLAIN)
+      if ((flags & LOOKUP_COMPLAIN)
+	  && (complain & tf_error))
 	{
 	  error ("conversion from %qT to %qT is ambiguous",
-		    fromtype, totype);
+		 fromtype, totype);
 	  print_z_candidates (location_of (expr), candidates);
 	}
 
@@ -3628,13 +3651,14 @@  static struct z_candidate *
 /* Wrapper for above. */
 
 tree
-build_user_type_conversion (tree totype, tree expr, int flags)
+build_user_type_conversion (tree totype, tree expr, int flags,
+			    tsubst_flags_t complain)
 {
   struct z_candidate *cand;
   tree ret;
 
   bool subtime = timevar_cond_start (TV_OVERLOAD);
-  cand = build_user_type_conversion_1 (totype, expr, flags);
+  cand = build_user_type_conversion_1 (totype, expr, flags, complain);
 
   if (cand)
     {
@@ -3642,7 +3666,7 @@  tree
 	ret = error_mark_node;
       else
         {
-          expr = convert_like (cand->second_conv, expr, tf_warning_or_error);
+          expr = convert_like (cand->second_conv, expr, complain);
           ret = convert_from_reference (expr);
         }
     }
@@ -3679,7 +3703,7 @@  build_integral_nontype_arg_conv (tree type, tree e
 
   conv = implicit_conversion (type, TREE_TYPE (expr), expr,
 			      /*c_cast_p=*/false,
-			      LOOKUP_IMPLICIT);
+			      LOOKUP_IMPLICIT, complain);
 
   /* for a non-type template-parameter of integral or
      enumeration type, integral promotions (4.5) and integral
@@ -3763,7 +3787,7 @@  static struct z_candidate *
 perform_overload_resolution (tree fn,
 			     const VEC(tree,gc) *args,
 			     struct z_candidate **candidates,
-			     bool *any_viable_p)
+			     bool *any_viable_p, tsubst_flags_t complain)
 {
   struct z_candidate *cand;
   tree explicit_targs;
@@ -3796,11 +3820,11 @@  perform_overload_resolution (tree fn,
 		  /*conversion_path=*/NULL_TREE,
 		  /*access_path=*/NULL_TREE,
 		  LOOKUP_NORMAL,
-		  candidates);
+		  candidates, complain);
 
   *candidates = splice_viable (*candidates, pedantic, any_viable_p);
   if (*any_viable_p)
-    cand = tourney (*candidates);
+    cand = tourney (*candidates, complain);
   else
     cand = NULL;
 
@@ -3872,7 +3896,8 @@  build_new_function_call (tree fn, VEC(tree,gc) **a
   /* Get the high-water mark for the CONVERSION_OBSTACK.  */
   p = conversion_obstack_alloc (0);
 
-  cand = perform_overload_resolution (fn, *args, &candidates, &any_viable_p);
+  cand = perform_overload_resolution (fn, *args, &candidates, &any_viable_p,
+				      complain);
 
   if (!cand)
     {
@@ -3918,7 +3943,7 @@  build_new_function_call (tree fn, VEC(tree,gc) **a
 tree
 build_operator_new_call (tree fnname, VEC(tree,gc) **args,
 			 tree *size, tree *cookie_size,
-			 tree *fn)
+			 tree *fn, tsubst_flags_t complain)
 {
   tree fns;
   struct z_candidate *candidates;
@@ -3928,7 +3953,7 @@  build_operator_new_call (tree fnname, VEC(tree,gc)
   if (fn)
     *fn = NULL_TREE;
   VEC_safe_insert (tree, gc, *args, 0, *size);
-  *args = resolve_args (*args, tf_warning_or_error);
+  *args = resolve_args (*args, complain);
   if (*args == NULL)
     return error_mark_node;
 
@@ -3944,13 +3969,15 @@  build_operator_new_call (tree fnname, VEC(tree,gc)
   fns = lookup_function_nonclass (fnname, *args, /*block_p=*/false);
 
   /* Figure out what function is being called.  */
-  cand = perform_overload_resolution (fns, *args, &candidates, &any_viable_p);
+  cand = perform_overload_resolution (fns, *args, &candidates, &any_viable_p,
+				      complain);
 
   /* If no suitable function could be found, issue an error message
      and give up.  */
   if (!cand)
     {
-      print_error_for_call_failure (fns, *args, any_viable_p, candidates);
+      if (complain & tf_error)
+	print_error_for_call_failure (fns, *args, any_viable_p, candidates);
       return error_mark_node;
     }
 
@@ -4001,7 +4028,7 @@  build_operator_new_call (tree fnname, VEC(tree,gc)
      *fn = cand->fn;
 
    /* Build the CALL_EXPR.  */
-   return build_over_call (cand, LOOKUP_NORMAL, tf_warning_or_error);
+   return build_over_call (cand, LOOKUP_NORMAL, complain);
 }
 
 /* Build a new call to operator().  This may change ARGS.  */
@@ -4057,7 +4084,7 @@  build_op_call_1 (tree obj, VEC(tree,gc) **args, ts
 		      first_mem_arg, *args, NULL_TREE,
 		      NULL_TREE, false,
 		      BASELINK_BINFO (fns), BASELINK_ACCESS_BINFO (fns),
-		      LOOKUP_NORMAL, &candidates);
+		      LOOKUP_NORMAL, &candidates, complain);
     }
 
   convs = lookup_conversions (type);
@@ -4085,11 +4112,11 @@  build_op_call_1 (tree obj, VEC(tree,gc) **args, ts
 	      add_template_conv_candidate
 		(&candidates, fn, obj, NULL_TREE, *args, totype,
 		 /*access_path=*/NULL_TREE,
-		 /*conversion_path=*/NULL_TREE);
+		 /*conversion_path=*/NULL_TREE, complain);
 	    else
 	      add_conv_candidate (&candidates, fn, obj, NULL_TREE,
 				  *args, /*conversion_path=*/NULL_TREE,
-				  /*access_path=*/NULL_TREE);
+				  /*access_path=*/NULL_TREE, complain);
 	  }
     }
 
@@ -4106,7 +4133,7 @@  build_op_call_1 (tree obj, VEC(tree,gc) **args, ts
     }
   else
     {
-      cand = tourney (candidates);
+      cand = tourney (candidates, complain);
       if (cand == 0)
 	{
           if (complain & tf_error)
@@ -4251,7 +4278,7 @@  op_error (enum tree_code code, enum tree_code code
    convert E1 to E2 in [expr.cond].  */
 
 static conversion *
-conditional_conversion (tree e1, tree e2)
+conditional_conversion (tree e1, tree e2, tsubst_flags_t complain)
 {
   tree t1 = non_reference (TREE_TYPE (e1));
   tree t2 = non_reference (TREE_TYPE (e2));
@@ -4271,7 +4298,8 @@  static conversion *
 				  e1,
 				  /*c_cast_p=*/false,
 				  LOOKUP_NO_TEMP_BIND|LOOKUP_NO_RVAL_BIND
-				  |LOOKUP_ONLYCONVERTING);
+				  |LOOKUP_ONLYCONVERTING,
+				  complain);
       if (conv)
 	return conv;
     }
@@ -4309,7 +4337,7 @@  static conversion *
        converted to the type that expression E2 would have if E2 were
        converted to an rvalue (or the type it has, if E2 is an rvalue).  */
     return implicit_conversion (t2, t1, e1, /*c_cast_p=*/false,
-				LOOKUP_IMPLICIT);
+				LOOKUP_IMPLICIT, complain);
 }
 
 /* Implement [expr.cond].  ARG1, ARG2, and ARG3 are the three
@@ -4455,8 +4483,8 @@  build_conditional_expr_1 (tree arg1, tree arg2, tr
       /* Get the high-water mark for the CONVERSION_OBSTACK.  */
       p = conversion_obstack_alloc (0);
 
-      conv2 = conditional_conversion (arg2, arg3);
-      conv3 = conditional_conversion (arg3, arg2);
+      conv2 = conditional_conversion (arg2, arg3, complain);
+      conv3 = conditional_conversion (arg3, arg2, complain);
 
       /* [expr.cond]
 
@@ -4568,7 +4596,7 @@  build_conditional_expr_1 (tree arg1, tree arg2, tr
 			      NOP_EXPR,
 			      ansi_opname (COND_EXPR),
 			      args,
-			      LOOKUP_NORMAL);
+			      LOOKUP_NORMAL, complain);
 
       /* [expr.cond]
 
@@ -4584,7 +4612,7 @@  build_conditional_expr_1 (tree arg1, tree arg2, tr
             }
 	  return error_mark_node;
 	}
-      cand = tourney (candidates);
+      cand = tourney (candidates, complain);
       if (!cand)
 	{
           if (complain & tf_error)
@@ -4793,7 +4821,8 @@  add_candidates (tree fns, tree first_arg, const VE
 		tree explicit_targs, bool template_only,
 		tree conversion_path, tree access_path,
 		int flags,
-		struct z_candidate **candidates)
+		struct z_candidate **candidates,
+		tsubst_flags_t complain)
 {
   tree ctype;
   const VEC(tree,gc) *non_static_args;
@@ -4899,7 +4928,8 @@  add_candidates (tree fns, tree first_arg, const VE
 				access_path,
 				conversion_path,
 				flags,
-				strict);
+				strict,
+				complain);
       else if (!template_only)
 	add_function_candidate (candidates,
 				fn,
@@ -4908,7 +4938,8 @@  add_candidates (tree fns, tree first_arg, const VE
 				fn_args,
 				access_path,
 				conversion_path,
-				flags);
+				flags,
+				complain);
     }
 }
 
@@ -4999,7 +5030,7 @@  build_new_op_1 (enum tree_code code, int flags, tr
   add_candidates (lookup_function_nonclass (fnname, arglist, /*block_p=*/true),
 		  NULL_TREE, arglist, NULL_TREE,
 		  NULL_TREE, false, NULL_TREE, NULL_TREE,
-		  flags, &candidates);
+		  flags, &candidates, complain);
   /* Add class-member operators to the candidate set.  */
   if (CLASS_TYPE_P (TREE_TYPE (arg1)))
     {
@@ -5017,14 +5048,15 @@  build_new_op_1 (enum tree_code code, int flags, tr
 			NULL_TREE, false,
 			BASELINK_BINFO (fns),
 			BASELINK_ACCESS_BINFO (fns),
-			flags, &candidates);
+			flags, &candidates, complain);
     }
 
   args[0] = arg1;
   args[1] = arg2;
   args[2] = NULL_TREE;
 
-  add_builtin_candidates (&candidates, code, code2, fnname, args, flags);
+  add_builtin_candidates (&candidates, code, code2, fnname, args,
+			  flags, complain);
 
   switch (code)
     {
@@ -5113,7 +5145,7 @@  build_new_op_1 (enum tree_code code, int flags, tr
     }
   else
     {
-      cand = tourney (candidates);
+      cand = tourney (candidates, complain);
       if (cand == 0)
 	{
 	  if ((flags & LOOKUP_COMPLAIN) && (complain & tf_error))
@@ -5140,7 +5172,7 @@  build_new_op_1 (enum tree_code code, int flags, tr
 	    {
 	      struct candidate_warning *w;
 	      for (w = cand->warnings; w; w = w->next)
-		joust (cand, w->loser, 1);
+		joust (cand, w->loser, 1, complain);
 	    }
 
 	  /* Check for comparison of different enum types.  */
@@ -5770,7 +5802,8 @@  convert_like_real (conversion *convs, tree expr, t
       if (complain & tf_error)
 	{
 	  /* Call build_user_type_conversion again for the error.  */
-	  build_user_type_conversion (totype, convs->u.expr, LOOKUP_NORMAL);
+	  build_user_type_conversion (totype, convs->u.expr, LOOKUP_NORMAL,
+				      complain);
 	  if (fn)
 	    error ("  initializing argument %P of %q+D", argnum, fn);
 	}
@@ -6010,7 +6043,7 @@  convert_like_real (conversion *convs, tree expr, t
    required.  Return the converted value.  */
 
 tree
-convert_arg_to_ellipsis (tree arg)
+convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain)
 {
   tree arg_type;
 
@@ -6018,7 +6051,7 @@  tree
 
      The lvalue-to-rvalue, array-to-pointer, and function-to-pointer
      standard conversions are performed.  */
-  arg = decay_conversion (arg, tf_warning_or_error);
+  arg = decay_conversion (arg, complain);
   arg_type = TREE_TYPE (arg);
   /* [expr.call]
 
@@ -6032,7 +6065,8 @@  tree
 	  < TYPE_PRECISION (double_type_node))
       && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (arg_type)))
     {
-      if (warn_double_promotion && !c_inhibit_evaluation_warnings)
+      if ((complain & tf_warning)
+	  && warn_double_promotion && !c_inhibit_evaluation_warnings)
 	warning (OPT_Wdouble_promotion,
 		 "implicit conversion from %qT to %qT when passing "
 		 "argument to function",
@@ -6045,8 +6079,9 @@  tree
     {
       if (SCOPED_ENUM_P (arg_type) && !abi_version_at_least (6))
 	{
-	  warning (OPT_Wabi, "scoped enum %qT will not promote to an "
-		   "integral type in a future version of GCC", arg_type);
+	  if (complain & tf_warning)
+	    warning (OPT_Wabi, "scoped enum %qT will not promote to an "
+		     "integral type in a future version of GCC", arg_type);
 	  arg = cp_convert (ENUM_UNDERLYING_TYPE (arg_type), arg);
 	}
       arg = perform_integral_promotions (arg);
@@ -6064,7 +6099,7 @@  tree
       /* Build up a real lvalue-to-rvalue conversion in case the
 	 copy constructor is trivial but not callable.  */
       if (!cp_unevaluated_operand && CLASS_TYPE_P (arg_type))
-	force_rvalue (arg, tf_warning_or_error);
+	force_rvalue (arg, complain);
 
       /* [expr.call] 5.2.2/7:
 	 Passing a potentially-evaluated argument of class type (Clause 9)
@@ -6080,8 +6115,13 @@  tree
       if (cp_unevaluated_operand == 0
 	  && (type_has_nontrivial_copy_init (arg_type)
 	      || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (arg_type)))
-	error ("cannot pass objects of non-trivially-copyable "
-	       "type %q#T through %<...%>", arg_type);
+	{
+	  if (complain & tf_error)
+	    error ("cannot pass objects of non-trivially-copyable "
+		   "type %q#T through %<...%>", arg_type);
+	  else
+	    return error_mark_node;
+	}
     }
 
   return arg;
@@ -6153,7 +6193,8 @@  pop_defarg_context (void)
 { VEC_pop (tree, default_arg_context); }
 
 tree
-convert_default_arg (tree type, tree arg, tree fn, int parmnum)
+convert_default_arg (tree type, tree arg, tree fn, int parmnum,
+		     tsubst_flags_t complain)
 {
   int i;
   tree t;
@@ -6165,7 +6206,8 @@  tree
   FOR_EACH_VEC_ELT (tree, default_arg_context, i, t)
     if (t == fn)
       {
-	error ("recursive evaluation of default argument for %q#D", fn);
+	if (complain & tf_error)
+	  error ("recursive evaluation of default argument for %q#D", fn);
 	return error_mark_node;
       }
 
@@ -6173,8 +6215,9 @@  tree
      conversion cannot be performed.  */
   if (TREE_CODE (arg) == DEFAULT_ARG)
     {
-      error ("call to %qD uses the default argument for parameter %P, which "
-	     "is not yet defined", fn, parmnum);
+      if (complain & tf_error)
+	error ("call to %qD uses the default argument for parameter %P, which "
+	       "is not yet defined", fn, parmnum);
       return error_mark_node;
     }
 
@@ -6198,17 +6241,17 @@  tree
   arg = break_out_target_exprs (arg);
   if (TREE_CODE (arg) == CONSTRUCTOR)
     {
-      arg = digest_init (type, arg, tf_warning_or_error);
+      arg = digest_init (type, arg, complain);
       arg = convert_for_initialization (0, type, arg, LOOKUP_IMPLICIT,
 					ICR_DEFAULT_ARGUMENT, fn, parmnum,
-                                        tf_warning_or_error);
+                                        complain);
     }
   else
     {
       arg = convert_for_initialization (0, type, arg, LOOKUP_IMPLICIT,
 					ICR_DEFAULT_ARGUMENT, fn, parmnum,
-                                        tf_warning_or_error);
-      arg = convert_for_arg_passing (type, arg);
+                                        complain);
+      arg = convert_for_arg_passing (type, arg, complain);
     }
   pop_deferring_access_checks();
 
@@ -6243,7 +6286,7 @@  type_passed_as (tree type)
 /* Actually perform the appropriate conversion.  */
 
 tree
-convert_for_arg_passing (tree type, tree val)
+convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
 {
   tree bitfield_type;
 
@@ -6277,7 +6320,8 @@  tree
 	   && INT_CST_LT_UNSIGNED (TYPE_SIZE (type),
 				   TYPE_SIZE (integer_type_node)))
     val = perform_integral_promotions (val);
-  if (warn_missing_format_attribute)
+  if ((complain & tf_warning)
+      && warn_missing_format_attribute)
     {
       tree rhstype = TREE_TYPE (val);
       const enum tree_code coder = TREE_CODE (rhstype);
@@ -6383,7 +6427,7 @@  build_over_call (struct z_candidate *cand, int fla
     {
       struct candidate_warning *w;
       for (w = cand->warnings; w; w = w->next)
-	joust (cand, w->loser, 1);
+	joust (cand, w->loser, 1, complain);
     }
 
   /* Make =delete work with SFINAE.  */
@@ -6611,7 +6655,7 @@  build_over_call (struct z_candidate *cand, int fla
 				       ? complain
 				       : complain & (~tf_warning));
 
-      val = convert_for_arg_passing (type, val);
+      val = convert_for_arg_passing (type, val, complain);
       if (val == error_mark_node)
         return error_mark_node;
       else
@@ -6625,7 +6669,8 @@  build_over_call (struct z_candidate *cand, int fla
 	return error_mark_node;
       argarray[j++] = convert_default_arg (TREE_VALUE (parm),
 					   TREE_PURPOSE (parm),
-					   fn, i - is_method);
+					   fn, i - is_method,
+					   complain);
     }
 
   /* Ellipsis */
@@ -6636,7 +6681,7 @@  build_over_call (struct z_candidate *cand, int fla
 	/* Do no conversions for magic varargs.  */
 	a = mark_type_use (a);
       else
-	a = convert_arg_to_ellipsis (a);
+	a = convert_arg_to_ellipsis (a, complain);
       argarray[j++] = a;
     }
 
@@ -7275,13 +7320,14 @@  build_new_method_call_1 (tree instance, tree fns,
       /* Otherwise go ahead with overload resolution.  */
       add_list_candidates (fns, first_mem_arg, init_list,
 			   basetype, explicit_targs, template_only,
-			   conversion_path, access_binfo, flags, &candidates);
+			   conversion_path, access_binfo, flags,
+			   &candidates, complain);
     }
   else
     {
       add_candidates (fns, first_mem_arg, user_args, optype,
 		      explicit_targs, template_only, conversion_path,
-		      access_binfo, flags, &candidates);
+		      access_binfo, flags, &candidates, complain);
     }
   any_viable_p = false;
   candidates = splice_viable (candidates, pedantic, &any_viable_p);
@@ -7318,7 +7364,7 @@  build_new_method_call_1 (tree instance, tree fns,
     }
   else
     {
-      cand = tourney (candidates);
+      cand = tourney (candidates, complain);
       if (cand == 0)
 	{
 	  char *pretty_name;
@@ -8013,7 +8059,8 @@  add_warning (struct z_candidate *winner, struct z_
       0: cand1 and cand2 are indistinguishable */
 
 static int
-joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn)
+joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
+       tsubst_flags_t complain)
 {
   int winner = 0;
   int off1 = 0, off2 = 0;
@@ -8076,7 +8123,8 @@  static int
 
       if (comp != 0)
 	{
-	  if (warn_sign_promo
+	  if ((complain & tf_warning)
+	      && warn_sign_promo
 	      && (CONVERSION_RANK (t1) + CONVERSION_RANK (t2)
 		  == cr_std + cr_promotion)
 	      && t1->kind == ck_std
@@ -8121,7 +8169,8 @@  static int
   /* warn about confusing overload resolution for user-defined conversions,
      either between a constructor and a conversion op, or between two
      conversion ops.  */
-  if (winner && warn_conversion && cand1->second_conv
+  if ((complain & tf_warning)
+      && winner && warn_conversion && cand1->second_conv
       && (!DECL_CONSTRUCTOR_P (cand1->fn) || !DECL_CONSTRUCTOR_P (cand2->fn))
       && winner != compare_ics (cand1->second_conv, cand2->second_conv))
     {
@@ -8283,12 +8332,18 @@  static int
 	    {
 	      if (warn)
 		{
-		  permerror (input_location, "default argument mismatch in "
-			     "overload resolution");
-		  inform (input_location,
-			  " candidate 1: %q+#F", cand1->fn);
-		  inform (input_location,
-			  " candidate 2: %q+#F", cand2->fn);
+		  if (complain & tf_error)
+		    {
+		      permerror (input_location,
+				 "default argument mismatch in "
+				 "overload resolution");
+		      inform (input_location,
+			      " candidate 1: %q+#F", cand1->fn);
+		      inform (input_location,
+			      " candidate 2: %q+#F", cand2->fn);
+		    }
+		  else
+		    return 0;
 		}
 	      else
 		add_warning (cand1, cand2);
@@ -8305,7 +8360,7 @@  tweak:
 
   /* Extension: If the worst conversion for one candidate is worse than the
      worst conversion for the other, take the first.  */
-  if (!pedantic)
+  if (!pedantic && (complain & tf_warning_or_error))
     {
       conversion_rank rank1 = cr_identity, rank2 = cr_identity;
       struct z_candidate *w = 0, *l = 0;
@@ -8351,7 +8406,7 @@  tweak:
    algorithm.  */
 
 static struct z_candidate *
-tourney (struct z_candidate *candidates)
+tourney (struct z_candidate *candidates, tsubst_flags_t complain)
 {
   struct z_candidate *champ = candidates, *challenger;
   int fate;
@@ -8362,7 +8417,7 @@  static struct z_candidate *
 
   for (challenger = champ->next; challenger; )
     {
-      fate = joust (champ, challenger, 0);
+      fate = joust (champ, challenger, 0, complain);
       if (fate == 1)
 	challenger = challenger->next;
       else
@@ -8392,7 +8447,7 @@  static struct z_candidate *
 	 && !(champ_compared_to_predecessor && challenger->next == champ);
        challenger = challenger->next)
     {
-      fate = joust (champ, challenger, 0);
+      fate = joust (champ, challenger, 0, complain);
       if (fate != 1)
 	return NULL;
     }
@@ -8403,15 +8458,16 @@  static struct z_candidate *
 /* Returns nonzero if things of type FROM can be converted to TO.  */
 
 bool
-can_convert (tree to, tree from)
+can_convert (tree to, tree from, tsubst_flags_t complain)
 {
-  return can_convert_arg (to, from, NULL_TREE, LOOKUP_IMPLICIT);
+  return can_convert_arg (to, from, NULL_TREE, LOOKUP_IMPLICIT, complain);
 }
 
 /* Returns nonzero if ARG (of type FROM) can be converted to TO.  */
 
 bool
-can_convert_arg (tree to, tree from, tree arg, int flags)
+can_convert_arg (tree to, tree from, tree arg, int flags,
+		 tsubst_flags_t complain)
 {
   conversion *t;
   void *p;
@@ -8421,7 +8477,7 @@  bool
   p = conversion_obstack_alloc (0);
 
   t  = implicit_conversion (to, from, arg, /*c_cast_p=*/false,
-			    flags);
+			    flags, complain);
   ok_p = (t && !t->bad_p);
 
   /* Free all the conversions we allocated.  */
@@ -8433,7 +8489,8 @@  bool
 /* Like can_convert_arg, but allows dubious conversions as well.  */
 
 bool
-can_convert_arg_bad (tree to, tree from, tree arg, int flags)
+can_convert_arg_bad (tree to, tree from, tree arg, int flags,
+		     tsubst_flags_t complain)
 {
   conversion *t;
   void *p;
@@ -8442,7 +8499,7 @@  bool
   p = conversion_obstack_alloc (0);
   /* Try to perform the conversion.  */
   t  = implicit_conversion (to, from, arg, /*c_cast_p=*/false,
-			    flags);
+			    flags, complain);
   /* Free all the conversions we allocated.  */
   obstack_free (&conversion_obstack, p);
 
@@ -8456,7 +8513,8 @@  bool
    doing a bad conversion, convert_like will complain.  */
 
 tree
-perform_implicit_conversion_flags (tree type, tree expr, tsubst_flags_t complain, int flags)
+perform_implicit_conversion_flags (tree type, tree expr,
+				   tsubst_flags_t complain, int flags)
 {
   conversion *conv;
   void *p;
@@ -8469,7 +8527,7 @@  tree
 
   conv = implicit_conversion (type, TREE_TYPE (expr), expr,
 			      /*c_cast_p=*/false,
-			      flags);
+			      flags, complain);
 
   if (!conv)
     {
@@ -8510,7 +8568,8 @@  tree
 tree
 perform_implicit_conversion (tree type, tree expr, tsubst_flags_t complain)
 {
-  return perform_implicit_conversion_flags (type, expr, complain, LOOKUP_IMPLICIT);
+  return perform_implicit_conversion_flags (type, expr, complain,
+					    LOOKUP_IMPLICIT);
 }
 
 /* Convert EXPR to TYPE (as a direct-initialization) if that is
@@ -8554,7 +8613,7 @@  perform_direct_initialization_if_possible (tree ty
 
   conv = implicit_conversion (type, TREE_TYPE (expr), expr,
 			      c_cast_p,
-			      LOOKUP_NORMAL);
+			      LOOKUP_NORMAL, complain);
   if (!conv || conv->bad_p)
     expr = NULL_TREE;
   else
@@ -8768,7 +8827,7 @@  initialize_reference (tree type, tree expr,
   p = conversion_obstack_alloc (0);
 
   conv = reference_binding (type, TREE_TYPE (expr), expr, /*c_cast_p=*/false,
-			    flags);
+			    flags, complain);
   if (!conv || conv->bad_p)
     {
       if (complain & tf_error)
Index: cp/cvt.c
===================================================================
--- cp/cvt.c	(revision 186600)
+++ cp/cvt.c	(working copy)
@@ -408,12 +408,12 @@  convert_to_reference (tree reftype, tree expr, int
   tree rval = NULL_TREE;
   tree rval_as_conversion = NULL_TREE;
   bool can_convert_intype_to_type;
+  tsubst_flags_t complain = ((flags & LOOKUP_COMPLAIN)
+			     ? tf_warning_or_error : tf_none);
 
   if (TREE_CODE (type) == FUNCTION_TYPE
       && TREE_TYPE (expr) == unknown_type_node)
-    expr = instantiate_type (type, expr,
-			     (flags & LOOKUP_COMPLAIN)
-			     ? tf_warning_or_error : tf_none);
+    expr = instantiate_type (type, expr, complain);
 
   if (expr == error_mark_node)
     return error_mark_node;
@@ -425,7 +425,8 @@  convert_to_reference (tree reftype, tree expr, int
 
   intype = TYPE_MAIN_VARIANT (intype);
 
-  can_convert_intype_to_type = can_convert (type, intype);
+  can_convert_intype_to_type = can_convert (type, intype, complain);
+
   if (!can_convert_intype_to_type
       && (convtype & CONV_IMPLICIT) && MAYBE_CLASS_TYPE_P (intype)
       && ! (flags & LOOKUP_NO_CONVERSION))
@@ -445,7 +446,7 @@  convert_to_reference (tree reftype, tree expr, int
 	}
     }
 
-  if (((convtype & CONV_STATIC) && can_convert (intype, type))
+  if (((convtype & CONV_STATIC) && can_convert (intype, type, complain))
       || ((convtype & CONV_IMPLICIT) && can_convert_intype_to_type))
     {
       if (flags & LOOKUP_COMPLAIN)
@@ -821,7 +822,8 @@  ocp_convert (tree type, tree expr, int convtype, i
 	/* For copy-initialization, first we create a temp of the proper type
 	   with a user-defined conversion sequence, then we direct-initialize
 	   the target with the temp (see [dcl.init]).  */
-	ctor = build_user_type_conversion (type, ctor, flags);
+	ctor = build_user_type_conversion (type, ctor, flags,
+					   tf_warning_or_error);
       else
 	{
 	  VEC(tree,gc) *ctor_vec = make_tree_vector_single (ctor);
@@ -1451,7 +1453,8 @@  build_type_conversion (tree xtype, tree expr)
 {
   /* C++: check to see if we can convert this aggregate type
      into the required type.  */
-  return build_user_type_conversion (xtype, expr, LOOKUP_NORMAL);
+  return build_user_type_conversion (xtype, expr, LOOKUP_NORMAL,
+				     tf_warning_or_error);
 }
 
 /* Convert the given EXPR to one of a group of types suitable for use in an
@@ -1609,7 +1612,8 @@  build_expr_type_conversion (int desires, tree expr
   if (winner)
     {
       tree type = non_reference (TREE_TYPE (TREE_TYPE (winner)));
-      return build_user_type_conversion (type, expr, LOOKUP_NORMAL);
+      return build_user_type_conversion (type, expr, LOOKUP_NORMAL,
+					 tf_warning_or_error);
     }
 
   return NULL_TREE;
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 186600)
+++ cp/cp-tree.h	(working copy)
@@ -4862,11 +4862,13 @@  extern bool null_ptr_cst_p			(tree);
 extern bool null_member_pointer_value_p		(tree);
 extern bool sufficient_parms_p			(const_tree);
 extern tree type_decays_to			(tree);
-extern tree build_user_type_conversion		(tree, tree, int);
+extern tree build_user_type_conversion		(tree, tree, int,
+						 tsubst_flags_t);
 extern tree build_new_function_call		(tree, VEC(tree,gc) **, bool, 
 						 tsubst_flags_t);
 extern tree build_operator_new_call		(tree, VEC(tree,gc) **, tree *,
-						 tree *, tree *);
+						 tree *, tree *,
+						 tsubst_flags_t);
 extern tree build_new_method_call		(tree, tree, VEC(tree,gc) **,
 						 tree, int, tree *,
 						 tsubst_flags_t);
@@ -4878,18 +4880,21 @@  extern tree build_new_op			(enum tree_code, int, t
 extern tree build_op_call			(tree, VEC(tree,gc) **,
 						 tsubst_flags_t);
 extern tree build_op_delete_call		(enum tree_code, tree, tree, bool, tree, tree);
-extern bool can_convert				(tree, tree);
-extern bool can_convert_arg			(tree, tree, tree, int);
-extern bool can_convert_arg_bad			(tree, tree, tree, int);
+extern bool can_convert				(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,
+						 tsubst_flags_t);
 extern bool enforce_access			(tree, tree, tree);
 extern void push_defarg_context			(tree);
 extern void pop_defarg_context			(void);
-extern tree convert_default_arg			(tree, tree, tree, int);
-extern tree convert_arg_to_ellipsis		(tree);
+extern tree convert_default_arg			(tree, tree, tree, int,
+						 tsubst_flags_t);
+extern tree convert_arg_to_ellipsis		(tree, tsubst_flags_t);
 extern tree build_x_va_arg			(tree, tree);
 extern tree cxx_type_promotes_to		(tree);
 extern tree type_passed_as			(tree);
-extern tree convert_for_arg_passing		(tree, tree);
+extern tree convert_for_arg_passing		(tree, tree, tsubst_flags_t);
 extern bool is_properly_derived_from		(tree, tree);
 extern tree initialize_reference		(tree, tree, int,
 						 tsubst_flags_t);
Index: cp/search.c
===================================================================
--- cp/search.c	(revision 186600)
+++ cp/search.c	(working copy)
@@ -1,7 +1,8 @@ 
 /* Breadth-first and depth-first routines for
    searching multiple-inheritance lattice for GNU C++.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
+   1999, 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011,
+   2012
    Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
@@ -1891,7 +1892,8 @@  check_final_overrider (tree overrider, tree basefn
 	    }
 	}
       else if (!pedantic
-	       && can_convert (TREE_TYPE (base_type), TREE_TYPE (over_type)))
+	       && can_convert (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.  */
 	{