re PR c++/8700 (unhelpful error message for binding temp to reference)

PR c++/8700
	* call.c (convert_class_to_reference): Adjust usage of
	splice_viable.
	(any_viable): Remove.
	(splice_viable): Combine with any_viable.
	(print_z_candidates): Avoid printing duplicates.
	(build_user_type_conversion_1): Adjust usage of splice_viable.
	(build_new_function_call): Likewise.
	(build_operator_new_call): Likewise.
	(build_object_call): Likewise.
	(build_conditional_expr): Likewise.
	(build_new_op): Likewise.
	(build_new_method_call): Likewise.
	(joust): Remove spurious comment.
	* cp-tree.h (DECL_FRIENDLIST): Correct documentation.
	* decl2.c (arg_assoc_class): Simplify.
	* friend.c (add_friend): Likewise.

From-SVN: r64173
This commit is contained in:
Mark Mitchell 2003-03-11 15:43:14 +00:00 committed by Mark Mitchell
parent 1be4def3c6
commit 436f8a4ce0
5 changed files with 132 additions and 83 deletions

View File

@ -1,3 +1,23 @@
2003-03-11 Mark Mitchell <mark@codesourcery.com>
PR c++/8700
* call.c (convert_class_to_reference): Adjust usage of
splice_viable.
(any_viable): Remove.
(splice_viable): Combine with any_viable.
(print_z_candidates): Avoid printing duplicates.
(build_user_type_conversion_1): Adjust usage of splice_viable.
(build_new_function_call): Likewise.
(build_operator_new_call): Likewise.
(build_object_call): Likewise.
(build_conditional_expr): Likewise.
(build_new_op): Likewise.
(build_new_method_call): Likewise.
(joust): Remove spurious comment.
* cp-tree.h (DECL_FRIENDLIST): Correct documentation.
* decl2.c (arg_assoc_class): Simplify.
* friend.c (add_friend): Likewise.
2003-03-11 Jason Merrill <jason@redhat.com>
PR c++/8660

View File

@ -58,8 +58,7 @@ static tree resolve_args (tree);
static struct z_candidate *build_user_type_conversion_1 (tree, tree, int);
static void print_z_candidates (struct z_candidate *);
static tree build_this (tree);
static struct z_candidate *splice_viable (struct z_candidate *);
static bool any_viable (struct z_candidate *);
static struct z_candidate *splice_viable (struct z_candidate *, bool, bool *);
static bool any_strictly_viable (struct z_candidate *);
static struct z_candidate *add_template_candidate
(struct z_candidate **, tree, tree, tree, tree, tree,
@ -958,6 +957,7 @@ convert_class_to_reference (tree t, tree s, tree expr)
tree reference_type;
struct z_candidate *candidates;
struct z_candidate *cand;
bool any_viable_p;
conversions = lookup_conversions (s);
if (!conversions)
@ -1053,12 +1053,12 @@ convert_class_to_reference (tree t, tree s, tree expr)
conversions = TREE_CHAIN (conversions);
}
candidates = splice_viable (candidates, pedantic, &any_viable_p);
/* If none of the conversion functions worked out, let our caller
know. */
if (!any_viable (candidates))
if (!any_viable_p)
return NULL_TREE;
candidates = splice_viable (candidates);
cand = tourney (candidates);
if (!cand)
return NULL_TREE;
@ -2373,14 +2373,42 @@ add_template_conv_candidate (struct z_candidate **candidates, tree tmpl,
conversion_path, 0, obj, DEDUCE_CONV);
}
/* The CANDS are the set of candidates that were considered for
overload resolution. Return the set of viable candidates. If none
of the candidates were viable, set *ANY_VIABLE_P to true. STRICT_P
is true if a candidate should be considered viable only if it is
strictly viable. */
static bool
any_viable (struct z_candidate *cands)
static struct z_candidate*
splice_viable (struct z_candidate *cands,
bool strict_p,
bool *any_viable_p)
{
for (; cands; cands = cands->next)
if (pedantic ? cands->viable == 1 : cands->viable)
return true;
return false;
struct z_candidate *viable;
struct z_candidate **last_viable;
struct z_candidate **cand;
viable = NULL;
last_viable = &viable;
*any_viable_p = false;
cand = &cands;
while (*cand)
{
struct z_candidate *c = *cand;
if (strict_p ? c->viable == 1 : c->viable)
{
*last_viable = c;
*cand = c->next;
c->next = NULL;
last_viable = &c->next;
*any_viable_p = true;
}
else
cand = &c->next;
}
return viable ? viable : cands;
}
static bool
@ -2392,22 +2420,6 @@ any_strictly_viable (struct z_candidate *cands)
return false;
}
static struct z_candidate *
splice_viable (struct z_candidate *cands)
{
struct z_candidate **p = &cands;
for (; *p; )
{
if (pedantic ? (*p)->viable == 1 : (*p)->viable)
p = &((*p)->next);
else
*p = (*p)->next;
}
return cands;
}
static tree
build_this (tree obj)
{
@ -2415,10 +2427,49 @@ build_this (tree obj)
return build_unary_op (ADDR_EXPR, obj, 0);
}
/* Returns true iff functions are equivalent. Equivalent functions are
not '==' only if one is a function-local extern function or if
both are extern "C". */
static inline int
equal_functions (tree fn1, tree fn2)
{
if (DECL_LOCAL_FUNCTION_P (fn1) || DECL_LOCAL_FUNCTION_P (fn2)
|| DECL_EXTERN_C_FUNCTION_P (fn1))
return decls_match (fn1, fn2);
return fn1 == fn2;
}
static void
print_z_candidates (struct z_candidate *candidates)
{
const char *str = "candidates are:";
const char *str;
struct z_candidate *cand1;
struct z_candidate **cand2;
/* There may be duplicates in the set of candidates. We put off
checking this condition as long as possible, since we have no way
to eliminate duplicates from a set of functions in less than n^2
time. Now we are about to emit an error message, so it is more
permissible to go slowly. */
for (cand1 = candidates; cand1; cand1 = cand1->next)
{
tree fn = cand1->fn;
/* Skip builtin candidates and conversion functions. */
if (TREE_CODE (fn) != FUNCTION_DECL)
continue;
cand2 = &cand1->next;
while (*cand2)
{
if (TREE_CODE ((*cand2)->fn) == FUNCTION_DECL
&& equal_functions (fn, (*cand2)->fn))
*cand2 = (*cand2)->next;
else
cand2 = &(*cand2)->next;
}
}
str = "candidates are:";
for (; candidates; candidates = candidates->next)
{
if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE)
@ -2487,6 +2538,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
tree fromtype = TREE_TYPE (expr);
tree ctors = NULL_TREE, convs = NULL_TREE;
tree args = NULL_TREE;
bool any_viable_p;
/* We represent conversion within a hierarchy using RVALUE_CONV and
BASE_CONV, as specified by [over.best.ics]; these become plain
@ -2602,12 +2654,11 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
}
}
if (! any_viable (candidates))
candidates = splice_viable (candidates, pedantic, &any_viable_p);
if (!any_viable_p)
return 0;
candidates = splice_viable (candidates);
cand = tourney (candidates);
if (cand == 0)
{
if (flags & LOOKUP_COMPLAIN)
@ -2802,15 +2853,11 @@ perform_overload_resolution (tree fn,
LOOKUP_NORMAL,
candidates);
if (! any_viable (*candidates))
{
*any_viable_p = false;
return NULL;
}
*candidates = splice_viable (*candidates, pedantic, any_viable_p);
if (!*any_viable_p)
return NULL;
*candidates = splice_viable (*candidates);
cand = tourney (*candidates);
return cand;
}
@ -2840,7 +2887,7 @@ build_new_function_call (tree fn, tree args)
DECL_NAME (OVL_CURRENT (fn)), args);
else
error ("call of overloaded `%D(%A)' is ambiguous",
DECL_NAME (OVL_FUNCTION (fn)), args);
DECL_NAME (OVL_CURRENT (fn)), args);
if (candidates)
print_z_candidates (candidates);
return error_mark_node;
@ -2884,7 +2931,7 @@ build_operator_new_call (tree fnname, tree args, tree *size, tree *cookie_size)
DECL_NAME (OVL_CURRENT (fns)), args);
else
error ("call of overlopaded `%D(%A)' is ambiguous",
DECL_NAME (OVL_FUNCTION (fns)), args);
DECL_NAME (OVL_CURRENT (fns)), args);
if (candidates)
print_z_candidates (candidates);
return error_mark_node;
@ -2943,6 +2990,7 @@ build_object_call (tree obj, tree args)
struct z_candidate *candidates = 0, *cand;
tree fns, convs, mem_args = NULL_TREE;
tree type = TREE_TYPE (obj);
bool any_viable_p;
if (TYPE_PTRMEMFUNC_P (type))
{
@ -3011,16 +3059,15 @@ build_object_call (tree obj, tree args)
}
}
if (! any_viable (candidates))
candidates = splice_viable (candidates, pedantic, &any_viable_p);
if (!any_viable_p)
{
error ("no match for call to `(%T) (%A)'", TREE_TYPE (obj), args);
print_z_candidates (candidates);
return error_mark_node;
}
candidates = splice_viable (candidates);
cand = tourney (candidates);
if (cand == 0)
{
error ("call of `(%T) (%A)' is ambiguous", TREE_TYPE (obj), args);
@ -3302,6 +3349,7 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
{
tree args[3];
tree conv;
bool any_viable_p;
/* Rearrange the arguments so that add_builtin_candidate only has
to know about two args. In build_builtin_candidates, the
@ -3320,13 +3368,13 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
If the overload resolution fails, the program is
ill-formed. */
if (!any_viable (candidates))
candidates = splice_viable (candidates, pedantic, &any_viable_p);
if (!any_viable_p)
{
op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match");
print_z_candidates (candidates);
return error_mark_node;
}
candidates = splice_viable (candidates);
cand = tourney (candidates);
if (!cand)
{
@ -3565,7 +3613,8 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
tree args[3];
enum tree_code code2 = NOP_EXPR;
tree conv;
bool viable_candidates;
bool strict_p;
bool any_viable_p;
if (error_operand_p (arg1)
|| error_operand_p (arg2)
@ -3675,15 +3724,16 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
operators. The built-in candidate set for COMPONENT_REF
would be empty too, but since there are no such built-in
operators, we accept non-strict matches for them. */
viable_candidates = any_strictly_viable (candidates);
strict_p = true;
break;
default:
viable_candidates = any_viable (candidates);
strict_p = pedantic;
break;
}
if (! viable_candidates)
candidates = splice_viable (candidates, strict_p, &any_viable_p);
if (!any_viable_p)
{
switch (code)
{
@ -3717,9 +3767,8 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
}
return error_mark_node;
}
candidates = splice_viable (candidates);
cand = tourney (candidates);
cand = tourney (candidates);
if (cand == 0)
{
if (flags & LOOKUP_COMPLAIN)
@ -4885,6 +4934,7 @@ build_new_method_call (tree instance, tree fns, tree args,
tree fn;
tree class_type;
int template_only = 0;
bool any_viable_p;
my_friendly_assert (instance != NULL_TREE, 20020729);
@ -5001,7 +5051,8 @@ build_new_method_call (tree instance, tree fns, tree args,
flags);
}
if (! any_viable (candidates))
candidates = splice_viable (candidates, pedantic, &any_viable_p);
if (!any_viable_p)
{
/* XXX will LOOKUP_SPECULATIVELY be needed when this is done? */
if (flags & LOOKUP_SPECULATIVELY)
@ -5023,9 +5074,8 @@ build_new_method_call (tree instance, tree fns, tree args,
print_z_candidates (candidates);
return error_mark_node;
}
candidates = splice_viable (candidates);
cand = tourney (candidates);
cand = tourney (candidates);
if (cand == 0)
{
char *pretty_name;
@ -5555,19 +5605,6 @@ add_warning (struct z_candidate *winner, struct z_candidate *loser)
winner->warnings);
}
/* Returns true iff functions are equivalent. Equivalent functions are
not '==' only if one is a function-local extern function or if
both are extern "C". */
static inline int
equal_functions (tree fn1, tree fn2)
{
if (DECL_LOCAL_FUNCTION_P (fn1) || DECL_LOCAL_FUNCTION_P (fn2)
|| DECL_EXTERN_C_FUNCTION_P (fn1))
return decls_match (fn1, fn2);
return fn1 == fn2;
}
/* Compare two candidates for overloading as described in
[over.match.best]. Return values:
@ -5748,7 +5785,6 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn)
TREE_VEC_LENGTH (cand1->convs)
- (DECL_NONSTATIC_MEMBER_FUNCTION_P (cand1->fn)
- DECL_CONSTRUCTOR_P (cand1->fn)));
/* HERE */
if (winner)
return winner;
}
@ -5805,7 +5841,7 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn)
if (DECL_P (cand1->fn) && DECL_P (cand2->fn)
&& equal_functions (cand1->fn, cand2->fn))
return 1;
tweak:
/* Extension: If the worst conversion for one candidate is worse than the

View File

@ -2657,14 +2657,8 @@ struct lang_decl GTY(())
/* The format of each node in the DECL_FRIENDLIST is as follows:
The TREE_PURPOSE will be the name of a function, i.e., an
IDENTIFIER_NODE. The TREE_VALUE will be itself a TREE_LIST, the
list of functions with that name which are friends. The
TREE_PURPOSE of each node in this sublist will be error_mark_node,
if the function was declared a friend individually, in which case
the TREE_VALUE will be the function_decl. If, however, all
functions with a given name in a class were declared to be friends,
the TREE_PUROSE will be the class type, and the TREE_VALUE will be
NULL_TREE. */
IDENTIFIER_NODE. The TREE_VALUE will be itself a TREE_LIST, whose
TREE_VALUEs are friends with the given name. */
#define DECL_FRIENDLIST(NODE) (DECL_INITIAL (NODE))
#define FRIEND_NAME(LIST) (TREE_PURPOSE (LIST))
#define FRIEND_DECLS(LIST) (TREE_VALUE (LIST))

View File

@ -3936,13 +3936,12 @@ arg_assoc_class (struct arg_lookup *k, tree type)
/* Process friends. */
for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
list = TREE_CHAIN (list))
if (k->name == TREE_PURPOSE (list))
for (friends = TREE_VALUE (list); friends;
if (k->name == FRIEND_NAME (list))
for (friends = FRIEND_DECLS (list); friends;
friends = TREE_CHAIN (friends))
/* Only interested in global functions with potentially hidden
(i.e. unqualified) declarations. */
if (TREE_PURPOSE (friends) == error_mark_node && TREE_VALUE (friends)
&& decl_namespace (TREE_VALUE (friends)) == context)
if (decl_namespace (TREE_VALUE (friends)) == context)
if (add_function (k, TREE_VALUE (friends)))
return true;

View File

@ -165,7 +165,7 @@ add_friend (type, decl)
maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
TREE_VALUE (list) = tree_cons (error_mark_node, decl,
TREE_VALUE (list) = tree_cons (NULL_TREE, decl,
TREE_VALUE (list));
return;
}
@ -175,7 +175,7 @@ add_friend (type, decl)
maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
DECL_FRIENDLIST (typedecl)
= tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl),
= tree_cons (DECL_NAME (decl), build_tree_list (NULL_TREE, decl),
DECL_FRIENDLIST (typedecl));
if (!uses_template_parms (type))
DECL_BEFRIENDING_CLASSES (decl)