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);