Hi again,
Thus, if I don't ear from you, I'm probably going to add complain to build_user_type_conversion_1, hopefully I can manage, I remember that earlier today I tried and was dragging in a lot of changes...
The below adds complain to build_user_type_conversion_1 and build_user_type_conversion too (besides perform_overload_resolution, etc) thus convert_like_real can propagate complain down to the former. This version too passes testing.

Thanks!
Paolo.

///////////////////////
/cp
2012-04-18  Paolo Carlini  <paolo.carl...@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 tsubst_flags_t parameter.
        (joust): Likewise, use it to handle SFINAE as if pedantic.
        (reference_binding, implicit_conversion,
        build_new_function_call, build_new_function_call,
        build_op_call_1, build_conditional_expr_1,
        build_new_op_1, convert_like_real, build_over_call,
        build_new_method_call_1): Adjust.
        * init.c (build_new_1): Likewise.
        * cvt.c (ocp_convert, build_type_conversion,
        build_expr_type_conversion): Likewise.
        * cp-tree.h (build_user_type_conversion,
        build_operator_new_call): Adjust declaration.

/testsuite
2012-04-18  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/52363
        * testsuite/g++.dg/cpp0x/sfinae35.C: New.
        * testsuite/g++.dg/cpp0x/sfinae36.C: Likewise.
Index: testsuite/g++.dg/cpp0x/sfinae35.C
===================================================================
--- testsuite/g++.dg/cpp0x/sfinae35.C   (revision 0)
+++ testsuite/g++.dg/cpp0x/sfinae35.C   (revision 0)
@@ -0,0 +1,13 @@
+// PR c++/52363
+// { dg-options -std=c++11 }
+
+#include <type_traits>
+
+struct proxy
+{
+  void operator=(int const&);
+  void operator=(int&&) const;
+};
+
+static_assert( !std::is_assignable<proxy, int>::value, "" );
+static_assert( std::is_assignable<const proxy, int>::value, "" );
Index: testsuite/g++.dg/cpp0x/sfinae36.C
===================================================================
--- testsuite/g++.dg/cpp0x/sfinae36.C   (revision 0)
+++ testsuite/g++.dg/cpp0x/sfinae36.C   (revision 0)
@@ -0,0 +1,13 @@
+// PR c++/52363
+// { dg-options "-std=c++11 -pedantic" }
+
+#include <type_traits>
+
+struct proxy
+{
+  void operator=(int const&);
+  void operator=(int&&) const;
+};
+
+static_assert( !std::is_assignable<proxy, int>::value, "" );
+static_assert( std::is_assignable<const proxy, int>::value, "" );
Index: cp/init.c
===================================================================
--- cp/init.c   (revision 186573)
+++ 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/call.c
===================================================================
--- cp/call.c   (revision 186573)
+++ 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);
@@ -1597,7 +1599,8 @@ reference_binding (tree rto, tree rfrom, tree expr
 
        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,
+                                                       tf_warning_or_error);
       if (cand)
        return cand->second_conv;
     }
@@ -1748,7 +1751,8 @@ implicit_conversion (tree to, tree from, tree expr
          && !CLASSTYPE_NON_AGGREGATE (complete_type (to)))
        return build_aggr_conv (to, expr, flags);
 
-      cand = build_user_type_conversion_1 (to, expr, flags);
+      cand = build_user_type_conversion_1 (to, expr, flags,
+                                          tf_warning_or_error);
       if (cand)
        conv = cand->second_conv;
 
@@ -3389,7 +3393,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;
@@ -3582,13 +3587,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 +3634,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 +3649,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);
         }
     }
@@ -3763,7 +3770,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;
@@ -3800,7 +3807,7 @@ perform_overload_resolution (tree fn,
 
   *candidates = splice_viable (*candidates, pedantic, any_viable_p);
   if (*any_viable_p)
-    cand = tourney (*candidates);
+    cand = tourney (*candidates, complain);
   else
     cand = NULL;
 
@@ -3872,7 +3879,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 +3926,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 +3936,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 +3952,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 +4011,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.  */
@@ -4106,7 +4116,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)
@@ -4584,7 +4594,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)
@@ -5113,7 +5123,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 +5150,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 +5780,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);
        }
@@ -6383,7 +6394,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.  */
@@ -7318,7 +7329,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 +8024,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 +8088,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 +8134,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 +8297,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 +8325,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 +8371,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 +8382,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 +8412,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;
     }
Index: cp/cvt.c
===================================================================
--- cp/cvt.c    (revision 186573)
+++ cp/cvt.c    (working copy)
@@ -821,7 +821,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 +1452,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 +1611,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 186573)
+++ 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);

Reply via email to