diff options
author | Mark Mitchell <mark@codesourcery.com> | 2003-03-11 15:43:14 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2003-03-11 15:43:14 +0000 |
commit | 436f8a4ce077dc372f70d1b57ab693c4aa0c6c6d (patch) | |
tree | 06a7a25a0f012883df97a7adf593d48822400080 /gcc/cp | |
parent | 1be4def3c6aa88e74c2a74a445405191706e323e (diff) | |
download | gcc-436f8a4ce077dc372f70d1b57ab693c4aa0c6c6d.zip gcc-436f8a4ce077dc372f70d1b57ab693c4aa0c6c6d.tar.gz gcc-436f8a4ce077dc372f70d1b57ab693c4aa0c6c6d.tar.bz2 |
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
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 20 | ||||
-rw-r--r-- | gcc/cp/call.c | 174 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 10 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 7 | ||||
-rw-r--r-- | gcc/cp/friend.c | 4 |
5 files changed, 132 insertions, 83 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f0421f1..121c2ae 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index ed9227f..c8baf74 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a45e546..db603ba 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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)) diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 6a4250e..c2f1f6c 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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; diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index 56b6452..3ecd317 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -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) |