This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PR 8700
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 11 Mar 2003 09:49:53 -0800
- Subject: PR 8700
This patch fixes PR 8700.
Tested on i686-pc-linux-gnu, applied on the mainline and on the
branch.
(It turns out that some of my recent patch mails have been dropped on
the floor by the mailing lists; the Red Hat 8.0 upgrade program
apparently changed my sendmail configuration that makes the mailing
lists drop mail, even without bouncing it back to me. Unfortunately, I
neither have the mails nor the old configuration. Oh, well...)
--
Mark Mitchell mark at codesourcery dot com
CodeSourcery, LLC http://www.codesourcery.com
2003-03-11 Mark Mitchell <mark at codesourcery dot 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.
Index: call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.366
diff -c -5 -p -r1.366 call.c
*** call.c 11 Mar 2003 02:37:13 -0000 1.366
--- call.c 11 Mar 2003 08:26:51 -0000
*************** static void op_error (enum tree_code, en
*** 56,67 ****
static tree build_object_call (tree, tree);
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 bool any_strictly_viable (struct z_candidate *);
static struct z_candidate *add_template_candidate
(struct z_candidate **, tree, tree, tree, tree, tree,
tree, tree, int, unification_kind_t);
static struct z_candidate *add_template_candidate_real
--- 56,66 ----
static tree build_object_call (tree, tree);
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 *, 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,
tree, tree, int, unification_kind_t);
static struct z_candidate *add_template_candidate_real
*************** convert_class_to_reference (tree t, tree
*** 956,965 ****
--- 955,965 ----
tree arglist;
tree conv;
tree reference_type;
struct z_candidate *candidates;
struct z_candidate *cand;
+ bool any_viable_p;
conversions = lookup_conversions (s);
if (!conversions)
return NULL_TREE;
*************** convert_class_to_reference (tree t, tree
*** 1051,1066 ****
NULL_TREE)));
}
conversions = TREE_CHAIN (conversions);
}
/* If none of the conversion functions worked out, let our caller
know. */
! if (!any_viable (candidates))
return NULL_TREE;
!
! candidates = splice_viable (candidates);
cand = tourney (candidates);
if (!cand)
return NULL_TREE;
/* Now that we know that this is the function we're going to use fix
--- 1051,1066 ----
NULL_TREE)));
}
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_p)
return NULL_TREE;
!
cand = tourney (candidates);
if (!cand)
return NULL_TREE;
/* Now that we know that this is the function we're going to use fix
*************** add_template_conv_candidate (struct z_ca
*** 2371,2388 ****
add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
arglist, return_type, access_path,
conversion_path, 0, obj, DEDUCE_CONV);
}
! static bool
! any_viable (struct z_candidate *cands)
! {
! for (; cands; cands = cands->next)
! if (pedantic ? cands->viable == 1 : cands->viable)
! return true;
! return false;
}
static bool
any_strictly_viable (struct z_candidate *cands)
{
--- 2371,2416 ----
add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
arglist, return_type, access_path,
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 struct z_candidate*
! splice_viable (struct z_candidate *cands,
! bool strict_p,
! bool *any_viable_p)
! {
! 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
any_strictly_viable (struct z_candidate *cands)
{
*************** any_strictly_viable (struct z_candidate
*** 2390,2426 ****
if (cands->viable == 1)
return true;
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)
{
/* Fix this to work on non-lvalues. */
return build_unary_op (ADDR_EXPR, obj, 0);
}
static void
print_z_candidates (struct z_candidate *candidates)
{
! const char *str = "candidates are:";
for (; candidates; candidates = candidates->next)
{
if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE)
{
if (TREE_VEC_LENGTH (candidates->convs) == 3)
--- 2418,2477 ----
if (cands->viable == 1)
return true;
return false;
}
static tree
build_this (tree obj)
{
/* Fix this to work on non-lvalues. */
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;
! 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)
{
if (TREE_VEC_LENGTH (candidates->convs) == 3)
*************** build_user_type_conversion_1 (tree totyp
*** 2485,2494 ****
--- 2536,2546 ----
{
struct z_candidate *candidates, *cand;
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
constructor calls, as specified in [dcl.init]. */
my_friendly_assert (!IS_AGGR_TYPE (fromtype) || !IS_AGGR_TYPE (totype)
*************** build_user_type_conversion_1 (tree totyp
*** 2600,2615 ****
cand->viable = -1;
}
}
}
! if (! any_viable (candidates))
return 0;
- candidates = splice_viable (candidates);
cand = tourney (candidates);
-
if (cand == 0)
{
if (flags & LOOKUP_COMPLAIN)
{
error ("conversion from `%T' to `%T' is ambiguous",
--- 2652,2666 ----
cand->viable = -1;
}
}
}
! candidates = splice_viable (candidates, pedantic, &any_viable_p);
! if (!any_viable_p)
return 0;
cand = tourney (candidates);
if (cand == 0)
{
if (flags & LOOKUP_COMPLAIN)
{
error ("conversion from `%T' to `%T' is ambiguous",
*************** perform_overload_resolution (tree fn,
*** 2800,2818 ****
/*conversion_path=*/NULL_TREE,
/*access_path=*/NULL_TREE,
LOOKUP_NORMAL,
candidates);
! if (! any_viable (*candidates))
! {
! *any_viable_p = false;
! return NULL;
! }
- *candidates = splice_viable (*candidates);
cand = tourney (*candidates);
-
return cand;
}
/* Return an expression for a call to FN (a namespace-scope function,
or a static member function) with the ARGS. */
--- 2851,2865 ----
/*conversion_path=*/NULL_TREE,
/*access_path=*/NULL_TREE,
LOOKUP_NORMAL,
candidates);
! *candidates = splice_viable (*candidates, pedantic, any_viable_p);
! if (!*any_viable_p)
! return NULL;
cand = tourney (*candidates);
return cand;
}
/* Return an expression for a call to FN (a namespace-scope function,
or a static member function) with the ARGS. */
*************** build_new_function_call (tree fn, tree a
*** 2838,2848 ****
if (!any_viable_p)
error ("no matching function for call to `%D(%A)'",
DECL_NAME (OVL_CURRENT (fn)), args);
else
error ("call of overloaded `%D(%A)' is ambiguous",
! DECL_NAME (OVL_FUNCTION (fn)), args);
if (candidates)
print_z_candidates (candidates);
return error_mark_node;
}
--- 2885,2895 ----
if (!any_viable_p)
error ("no matching function for call to `%D(%A)'",
DECL_NAME (OVL_CURRENT (fn)), args);
else
error ("call of overloaded `%D(%A)' is ambiguous",
! DECL_NAME (OVL_CURRENT (fn)), args);
if (candidates)
print_z_candidates (candidates);
return error_mark_node;
}
*************** build_operator_new_call (tree fnname, tr
*** 2882,2892 ****
if (!any_viable_p)
error ("no matching function for call to `%D(%A)'",
DECL_NAME (OVL_CURRENT (fns)), args);
else
error ("call of overlopaded `%D(%A)' is ambiguous",
! DECL_NAME (OVL_FUNCTION (fns)), args);
if (candidates)
print_z_candidates (candidates);
return error_mark_node;
}
--- 2929,2939 ----
if (!any_viable_p)
error ("no matching function for call to `%D(%A)'",
DECL_NAME (OVL_CURRENT (fns)), args);
else
error ("call of overlopaded `%D(%A)' is ambiguous",
! DECL_NAME (OVL_CURRENT (fns)), args);
if (candidates)
print_z_candidates (candidates);
return error_mark_node;
}
*************** static tree
*** 2941,2950 ****
--- 2988,2998 ----
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))
{
/* It's no good looking for an overloaded operator() on a
pointer-to-member-function. */
*************** build_object_call (tree obj, tree args)
*** 3009,3028 ****
/*conversion_path=*/NULL_TREE,
/*access_path=*/NULL_TREE);
}
}
! if (! any_viable (candidates))
{
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);
print_z_candidates (candidates);
return error_mark_node;
--- 3057,3075 ----
/*conversion_path=*/NULL_TREE,
/*access_path=*/NULL_TREE);
}
}
! 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;
}
cand = tourney (candidates);
if (cand == 0)
{
error ("call of `(%T) (%A)' is ambiguous", TREE_TYPE (obj), args);
print_z_candidates (candidates);
return error_mark_node;
*************** build_conditional_expr (tree arg1, tree
*** 3300,3309 ****
--- 3347,3357 ----
if (!same_type_p (arg2_type, arg3_type)
&& (CLASS_TYPE_P (arg2_type) || CLASS_TYPE_P (arg3_type)))
{
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
arguments are unscrambled. */
args[0] = arg2;
*************** build_conditional_expr (tree arg1, tree
*** 3318,3334 ****
/* [expr.cond]
If the overload resolution fails, the program is
ill-formed. */
! if (!any_viable (candidates))
{
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)
{
op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match");
print_z_candidates (candidates);
--- 3366,3382 ----
/* [expr.cond]
If the overload resolution fails, the program is
ill-formed. */
! 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;
}
cand = tourney (candidates);
if (!cand)
{
op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match");
print_z_candidates (candidates);
*************** build_new_op (enum tree_code code, int f
*** 3563,3573 ****
struct z_candidate *candidates = 0, *cand;
tree arglist, fnname;
tree args[3];
enum tree_code code2 = NOP_EXPR;
tree conv;
! bool viable_candidates;
if (error_operand_p (arg1)
|| error_operand_p (arg2)
|| error_operand_p (arg3))
return error_mark_node;
--- 3611,3622 ----
struct z_candidate *candidates = 0, *cand;
tree arglist, fnname;
tree args[3];
enum tree_code code2 = NOP_EXPR;
tree conv;
! bool strict_p;
! bool any_viable_p;
if (error_operand_p (arg1)
|| error_operand_p (arg2)
|| error_operand_p (arg3))
return error_mark_node;
*************** build_new_op (enum tree_code code, int f
*** 3673,3691 ****
[over.match.oper]/3. We don't want non-strict matches
because exact matches are always possible with built-in
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);
break;
default:
! viable_candidates = any_viable (candidates);
break;
}
! if (! viable_candidates)
{
switch (code)
{
case POSTINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
--- 3722,3741 ----
[over.match.oper]/3. We don't want non-strict matches
because exact matches are always possible with built-in
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. */
! strict_p = true;
break;
default:
! strict_p = pedantic;
break;
}
! candidates = splice_viable (candidates, strict_p, &any_viable_p);
! if (!any_viable_p)
{
switch (code)
{
case POSTINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
*************** build_new_op (enum tree_code code, int f
*** 3715,3727 ****
op_error (code, code2, arg1, arg2, arg3, "no match");
print_z_candidates (candidates);
}
return error_mark_node;
}
- candidates = splice_viable (candidates);
- cand = tourney (candidates);
if (cand == 0)
{
if (flags & LOOKUP_COMPLAIN)
{
op_error (code, code2, arg1, arg2, arg3, "ambiguous overload");
--- 3765,3776 ----
op_error (code, code2, arg1, arg2, arg3, "no match");
print_z_candidates (candidates);
}
return error_mark_node;
}
+ cand = tourney (candidates);
if (cand == 0)
{
if (flags & LOOKUP_COMPLAIN)
{
op_error (code, code2, arg1, arg2, arg3, "ambiguous overload");
*************** build_new_method_call (tree instance, tr
*** 4883,4892 ****
--- 4932,4942 ----
tree user_args;
tree call;
tree fn;
tree class_type;
int template_only = 0;
+ bool any_viable_p;
my_friendly_assert (instance != NULL_TREE, 20020729);
if (error_operand_p (instance)
|| error_operand_p (fns)
*************** build_new_method_call (tree instance, tr
*** 4999,5009 ****
access_binfo,
conversion_path,
flags);
}
! if (! any_viable (candidates))
{
/* XXX will LOOKUP_SPECULATIVELY be needed when this is done? */
if (flags & LOOKUP_SPECULATIVELY)
return NULL_TREE;
if (!COMPLETE_TYPE_P (basetype))
--- 5049,5060 ----
access_binfo,
conversion_path,
flags);
}
! 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)
return NULL_TREE;
if (!COMPLETE_TYPE_P (basetype))
*************** build_new_method_call (tree instance, tr
*** 5021,5033 ****
free (pretty_name);
}
print_z_candidates (candidates);
return error_mark_node;
}
- candidates = splice_viable (candidates);
- cand = tourney (candidates);
if (cand == 0)
{
char *pretty_name;
bool free_p;
--- 5072,5083 ----
free (pretty_name);
}
print_z_candidates (candidates);
return error_mark_node;
}
+ cand = tourney (candidates);
if (cand == 0)
{
char *pretty_name;
bool free_p;
*************** add_warning (struct z_candidate *winner,
*** 5553,5575 ****
winner->warnings = tree_cons (NULL_TREE,
build_zc_wrapper (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:
1: cand1 is better than cand2
-1: cand2 is better than cand1
--- 5603,5612 ----
*************** joust (struct z_candidate *cand1, struct
*** 5746,5756 ****
arguments has no effect on the partial ordering of function
templates. */
TREE_VEC_LENGTH (cand1->convs)
- (DECL_NONSTATIC_MEMBER_FUNCTION_P (cand1->fn)
- DECL_CONSTRUCTOR_P (cand1->fn)));
- /* HERE */
if (winner)
return winner;
}
/* or, if not that,
--- 5783,5792 ----
*************** joust (struct z_candidate *cand1, struct
*** 5803,5813 ****
/* If the two functions are the same (this can happen with declarations
in multiple scopes and arg-dependent lookup), arbitrarily choose
one. */
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
worst conversion for the other, take the first. */
if (!pedantic)
--- 5839,5849 ----
/* If the two functions are the same (this can happen with declarations
in multiple scopes and arg-dependent lookup), arbitrarily choose
one. */
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
worst conversion for the other, take the first. */
if (!pedantic)
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.823
diff -c -5 -p -r1.823 cp-tree.h
*** cp-tree.h 11 Mar 2003 02:37:13 -0000 1.823
--- cp-tree.h 11 Mar 2003 08:26:52 -0000
*************** struct lang_decl GTY(())
*** 2655,2672 ****
/* C++: all of these are overloaded! These apply only to TYPE_DECLs. */
/* 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. */
#define DECL_FRIENDLIST(NODE) (DECL_INITIAL (NODE))
#define FRIEND_NAME(LIST) (TREE_PURPOSE (LIST))
#define FRIEND_DECLS(LIST) (TREE_VALUE (LIST))
/* The DECL_ACCESS, if non-NULL, is a TREE_LIST. The TREE_PURPOSE of
--- 2655,2666 ----
/* C++: all of these are overloaded! These apply only to TYPE_DECLs. */
/* 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, 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))
/* The DECL_ACCESS, if non-NULL, is a TREE_LIST. The TREE_PURPOSE of
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.602
diff -c -5 -p -r1.602 decl2.c
*** decl2.c 10 Mar 2003 21:10:37 -0000 1.602
--- decl2.c 11 Mar 2003 08:26:53 -0000
*************** arg_assoc_class (struct arg_lookup *k, t
*** 3924,3940 ****
return true;
/* 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;
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 (add_function (k, TREE_VALUE (friends)))
return true;
/* Process template arguments. */
if (CLASSTYPE_TEMPLATE_INFO (type))
--- 3924,3939 ----
return true;
/* Process friends. */
for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
list = TREE_CHAIN (list))
! 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 (decl_namespace (TREE_VALUE (friends)) == context)
if (add_function (k, TREE_VALUE (friends)))
return true;
/* Process template arguments. */
if (CLASSTYPE_TEMPLATE_INFO (type))
Index: friend.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/friend.c,v
retrieving revision 1.81
diff -c -5 -p -r1.81 friend.c
*** friend.c 2 Jan 2003 11:39:46 -0000 1.81
--- friend.c 11 Mar 2003 08:26:53 -0000
*************** add_friend (type, decl)
*** 163,183 ****
}
}
maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
! TREE_VALUE (list) = tree_cons (error_mark_node, decl,
TREE_VALUE (list));
return;
}
list = TREE_CHAIN (list);
}
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),
DECL_FRIENDLIST (typedecl));
if (!uses_template_parms (type))
DECL_BEFRIENDING_CLASSES (decl)
= tree_cons (NULL_TREE, type,
DECL_BEFRIENDING_CLASSES (decl));
--- 163,183 ----
}
}
maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
! TREE_VALUE (list) = tree_cons (NULL_TREE, decl,
TREE_VALUE (list));
return;
}
list = TREE_CHAIN (list);
}
maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
DECL_FRIENDLIST (typedecl)
! = tree_cons (DECL_NAME (decl), build_tree_list (NULL_TREE, decl),
DECL_FRIENDLIST (typedecl));
if (!uses_template_parms (type))
DECL_BEFRIENDING_CLASSES (decl)
= tree_cons (NULL_TREE, type,
DECL_BEFRIENDING_CLASSES (decl));