From: Mark Mitchell Date: Wed, 24 Mar 1999 01:10:13 +0000 (+0000) Subject: cp-tree.h (lang_type): Remove has_assignment and has_real_assignment. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6a629cac2b8bc32566f6990f649ced12cbba5ff4;p=gcc.git cp-tree.h (lang_type): Remove has_assignment and has_real_assignment. * cp-tree.h (lang_type): Remove has_assignment and has_real_assignment. Add befriending_classes. (TYPE_HAS_ASSIGNMENT): Remove. (TYPE_HAS_REAL_ASSIGNMENT): Likewise. (CLASSTYPE_BEFRIENDING_CLASSES): New macro. (lang_decl): Document. (DECL_BEFRIENDING_CLASSES): New macro. (FRIEND_NAME): Move declaration to more obvious location. (FRIEND_DECLS): Likewise. * class.c (finish_struct_1): Don't use TYPE_HAS_REAL_ASSIGNMENT. * decl.c (duplicate_decls): Copy DECL_BEFRIENDING_CLASSES. (fixup_anonymous_union): Don't use TYPE_HAS_ASSIGNMENT. (grok_op_properties): Likewise. * friend.c (is_friend): Use FRIEND_NAME and FRIEND_DECLS. (add_friend): Likewise. Don't do weird things with assignment operators. Update DECL_BEFRIENDING_CLASSES. (add_friends): Don't do weird things with assignment operators. (make_friend_class): Likewise. Update CLASSTYPE_BEFRIENDING_CLASSES. * pt.c (instantiate_class_template): Don't set TYPE_HAS_ASSIGNMENT. (tsubst_copy): Substitute the TREE_TYPE for more unary expressions. * ptree.c (print_lang_type): Don't look at TYPE_HAS_ASSIGNMENT. * search.c (protected_accessible_p): New function. (friend_accessible_p): Likewise. (accessible_p): Use them. From-SVN: r25940 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3bac892ca8e..d0f66bce36e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,33 @@ +1999-03-24 Mark Mitchell + + * cp-tree.h (lang_type): Remove has_assignment and + has_real_assignment. Add befriending_classes. + (TYPE_HAS_ASSIGNMENT): Remove. + (TYPE_HAS_REAL_ASSIGNMENT): Likewise. + (CLASSTYPE_BEFRIENDING_CLASSES): New macro. + (lang_decl): Document. + (DECL_BEFRIENDING_CLASSES): New macro. + (FRIEND_NAME): Move declaration to more obvious location. + (FRIEND_DECLS): Likewise. + * class.c (finish_struct_1): Don't use TYPE_HAS_REAL_ASSIGNMENT. + * decl.c (duplicate_decls): Copy DECL_BEFRIENDING_CLASSES. + (fixup_anonymous_union): Don't use TYPE_HAS_ASSIGNMENT. + (grok_op_properties): Likewise. + * friend.c (is_friend): Use FRIEND_NAME and FRIEND_DECLS. + (add_friend): Likewise. Don't do weird things with assignment + operators. Update DECL_BEFRIENDING_CLASSES. + (add_friends): Don't do weird things with assignment operators. + (make_friend_class): Likewise. Update + CLASSTYPE_BEFRIENDING_CLASSES. + * pt.c (instantiate_class_template): Don't set + TYPE_HAS_ASSIGNMENT. + (tsubst_copy): Substitute the TREE_TYPE for more unary + expressions. + * ptree.c (print_lang_type): Don't look at TYPE_HAS_ASSIGNMENT. + * search.c (protected_accessible_p): New function. + (friend_accessible_p): Likewise. + (accessible_p): Use them. + 1999-03-23 Mark Mitchell * pt.c (convert_nontype_argument): Don't create things that aren't diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 6d8a4d61e50..07f8f9737e1 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -3808,7 +3808,6 @@ finish_struct_1 (t, warn_anon) if (! IS_SIGNATURE (t)) CLASSTYPE_NON_AGGREGATE (t) = ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (t); - TYPE_HAS_REAL_ASSIGNMENT (t) |= TYPE_HAS_ASSIGNMENT (t); TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t); TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 59f3e30a3bb..307df1dd989 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -683,12 +683,12 @@ struct lang_type { unsigned has_type_conversion : 1; unsigned has_init_ref : 1; - unsigned has_assignment : 1; unsigned has_default_ctor : 1; unsigned uses_multiple_inheritance : 1; unsigned const_needs_init : 1; unsigned ref_needs_init : 1; unsigned has_const_assign_ref : 1; + unsigned anon_union : 1; unsigned has_nonpublic_ctor : 2; unsigned has_nonpublic_assign_ref : 2; @@ -721,22 +721,20 @@ struct lang_type unsigned has_opaque_typedecls : 1; unsigned sigtable_has_been_generated : 1; unsigned was_anonymous : 1; - unsigned has_real_assignment : 1; unsigned has_real_assign_ref : 1; unsigned has_const_init_ref : 1; - unsigned has_complex_init_ref : 1; + unsigned has_complex_assign_ref : 1; unsigned has_abstract_assign_ref : 1; unsigned non_aggregate : 1; unsigned is_partial_instantiation : 1; unsigned has_mutable : 1; - unsigned anon_union : 1; /* The MIPS compiler gets it wrong if this struct also does not fill out to a multiple of 4 bytes. Add a member `dummy' with new bits if you go over the edge. */ - unsigned dummy : 9; + unsigned dummy : 11; } type_flags; int n_ancestors; @@ -772,8 +770,8 @@ struct lang_type union tree_node *signature; union tree_node *signature_pointer_to; union tree_node *signature_reference_to; - union tree_node *template_info; + tree befriending_classes; }; /* Indicates whether or not (and how) a template was expanded for this class. @@ -789,13 +787,6 @@ struct lang_type /* List of friends which were defined inline in this class definition. */ #define CLASSTYPE_INLINE_FRIENDS(NODE) (TYPE_NONCOPIED_PARTS (NODE)) -/* Nonzero for _CLASSTYPE means that the _CLASSTYPE either has - a special meaning for the assignment operator ("operator="), - or one of its fields (or base members) has a special meaning - defined. */ -#define TYPE_HAS_ASSIGNMENT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_assignment) -#define TYPE_HAS_REAL_ASSIGNMENT(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_real_assignment) - /* Nonzero for _CLASSTYPE means that operator new and delete are defined, respectively. */ #define TYPE_GETS_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_new) @@ -1057,11 +1048,15 @@ struct lang_type /* Same, but cache a list whose value is the binfo of this type. */ #define CLASSTYPE_BINFO_AS_LIST(NODE) (TYPE_LANG_SPECIFIC(NODE)->binfo_as_list) -/* A list of class types with which this type is a friend. The +/* A list of class types of which this type is a friend. The TREE_VALUE is normally a TYPE, but will be a TEMPLATE_DECL in the case of a template friend. */ #define CLASSTYPE_FRIEND_CLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->friend_classes) +/* A list of the classes which grant friendship to this class. */ +#define CLASSTYPE_BEFRIENDING_CLASSES(NODE) \ + (TYPE_LANG_SPECIFIC (NODE)->befriending_classes) + /* Say whether this node was declared as a "class" or a "struct". */ #define CLASSTYPE_DECLARED_CLASS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.declared_class) @@ -1169,6 +1164,15 @@ struct lang_type /* The binding level associated with the namespace. */ #define NAMESPACE_LEVEL(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.level) + +/* If a DECL has DECL_LANG_SPECIFIC, it is either a lang_decl_flags or + a lang_decl (which has lang_decl_flags as its initial prefix). A + FUNCTION_DECL, NAMESPACE_DECL, TYPE_DECL, or USING_DECL may have a + full lang_decl. A FIELD_DECL, or a static data member VAR_DECL, + will have only lang_decl_flags. Thus, one should only access the + members of lang_decl that are not in lang_decl_flags for DECLs that + are not FIELD_DECLs or VAR_DECLs. */ + struct lang_decl_flags { #ifdef ONLY_INT_FIELDS @@ -1215,6 +1219,7 @@ struct lang_decl struct lang_decl_flags decl_flags; tree main_decl_variant; + tree befriending_classes; struct pending_inline *pending_inline_info; }; @@ -1281,6 +1286,10 @@ struct lang_decl member functions for this class. */ #define DECL_FRIEND_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.friend_attr) +/* A TREE_LIST of the types which have befriended this FUNCTION_DECL. */ +#define DECL_BEFRIENDING_CLASSES(NODE) \ + (DECL_LANG_SPECIFIC(NODE)->befriending_classes) + /* Nonzero for FUNCTION_DECL means that this decl is a static member function. */ #define DECL_STATIC_FUNCTION_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.static_function) @@ -1822,6 +1831,8 @@ extern int flag_new_for_scope; 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 each node is a type; the TREE_VALUE is the access granted for this @@ -2677,9 +2688,6 @@ extern tree current_class_name; /* IDENTIFIER_NODE: name of current class */ #define same_or_base_type_p(type1, type2) \ comptypes ((type1), (type2), COMPARE_BASE) -#define FRIEND_NAME(LIST) (TREE_PURPOSE (LIST)) -#define FRIEND_DECLS(LIST) (TREE_VALUE (LIST)) - /* These macros are used to access a TEMPLATE_PARM_INDEX. */ #define TEMPLATE_PARM_IDX(NODE) (((template_parm_index*) NODE)->index) #define TEMPLATE_PARM_LEVEL(NODE) (((template_parm_index*) NODE)->level) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index e7272ff0b4a..64c8a6595f5 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3326,6 +3326,13 @@ duplicate_decls (newdecl, olddecl) DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl); DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl); olddecl_friend = DECL_FRIEND_P (olddecl); + + /* Only functions have DECL_BEFRIENDING_CLASSES. */ + if (TREE_CODE (newdecl) == FUNCTION_DECL + || DECL_FUNCTION_TEMPLATE_P (newdecl)) + DECL_BEFRIENDING_CLASSES (newdecl) + = chainon (DECL_BEFRIENDING_CLASSES (newdecl), + DECL_BEFRIENDING_CLASSES (olddecl)); } if (TREE_CODE (newdecl) == FUNCTION_DECL) @@ -6668,7 +6675,6 @@ fixup_anonymous_union (t) TYPE_HAS_INIT_REF (t) = 0; TYPE_HAS_CONST_INIT_REF (t) = 0; TYPE_HAS_ASSIGN_REF (t) = 0; - TYPE_HAS_ASSIGNMENT (t) = 0; TYPE_HAS_CONST_ASSIGN_REF (t) = 0; /* Splice the implicitly generated functions out of the TYPE_METHODS @@ -11804,7 +11810,7 @@ grok_op_properties (decl, virtualp, friendp) if (name == ansi_opname[(int) MODIFY_EXPR] && !(DECL_TEMPLATE_INSTANTIATION (decl) && is_member_template (DECL_TI_TEMPLATE (decl)))) - TYPE_HAS_ASSIGNMENT (current_class_type) = 1; + ; else if (name == ansi_opname[(int) CALL_EXPR]) TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1; else if (name == ansi_opname[(int) ARRAY_REF]) diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index 30b3c510972..2a69acd8d84 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -61,9 +61,9 @@ is_friend (type, supplicant) for (; list ; list = TREE_CHAIN (list)) { - if (name == TREE_PURPOSE (list)) + if (name == FRIEND_NAME (list)) { - tree friends = TREE_VALUE (list); + tree friends = FRIEND_DECLS (list); for (; friends ; friends = TREE_CHAIN (friends)) { if (same_type_p (ctype, TREE_PURPOSE (friends))) @@ -148,11 +148,13 @@ add_friend (type, decl) tree list = DECL_FRIENDLIST (typedecl); tree name = DECL_NAME (decl); + type = TREE_TYPE (typedecl); + while (list) { - if (name == TREE_PURPOSE (list)) + if (name == FRIEND_NAME (list)) { - tree friends = TREE_VALUE (list); + tree friends = FRIEND_DECLS (list); for (; friends ; friends = TREE_CHAIN (friends)) { if (decl == TREE_VALUE (friends)) @@ -170,21 +172,13 @@ add_friend (type, decl) } list = TREE_CHAIN (list); } + DECL_FRIENDLIST (typedecl) = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl), DECL_FRIENDLIST (typedecl)); - if (DECL_NAME (decl) == ansi_opname[(int) MODIFY_EXPR]) - { - tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (decl)); - TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1; - if (parmtypes && TREE_CHAIN (parmtypes)) - { - tree parmtype = TREE_VALUE (TREE_CHAIN (parmtypes)); - if (TREE_CODE (parmtype) == REFERENCE_TYPE - && TREE_TYPE (parmtypes) == TREE_TYPE (typedecl)) - TYPE_HAS_ASSIGN_REF (TREE_TYPE (typedecl)) = 1; - } - } + DECL_BEFRIENDING_CLASSES (decl) + = tree_cons (NULL_TREE, type, + DECL_BEFRIENDING_CLASSES (decl)); } /* Declare that every member function NAME in FRIEND_TYPE @@ -199,9 +193,9 @@ add_friends (type, name, friend_type) while (list) { - if (name == TREE_PURPOSE (list)) + if (name == FRIEND_NAME (list)) { - tree friends = TREE_VALUE (list); + tree friends = FRIEND_DECLS (list); while (friends && TREE_PURPOSE (friends) != friend_type) friends = TREE_CHAIN (friends); if (friends) @@ -226,13 +220,6 @@ add_friends (type, name, friend_type) = tree_cons (name, build_tree_list (friend_type, NULL_TREE), DECL_FRIENDLIST (typedecl)); - if (! strncmp (IDENTIFIER_POINTER (name), - IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR]), - strlen (IDENTIFIER_POINTER (ansi_opname[(int) MODIFY_EXPR])))) - { - TYPE_HAS_ASSIGNMENT (TREE_TYPE (typedecl)) = 1; - sorry ("declaring \"friend operator =\" will not find \"operator = (X&)\" if it exists"); - } } /* Make FRIEND_TYPE a friend class to TYPE. If FRIEND_TYPE has already @@ -309,6 +296,11 @@ make_friend_class (type, friend_type) { CLASSTYPE_FRIEND_CLASSES (type) = tree_cons (NULL_TREE, friend_type, CLASSTYPE_FRIEND_CLASSES (type)); + if (is_template_friend) + friend_type = TREE_TYPE (friend_type); + CLASSTYPE_BEFRIENDING_CLASSES (friend_type) + = tree_cons (NULL_TREE, type, + CLASSTYPE_BEFRIENDING_CLASSES (friend_type)); } } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index aa8c9e99c10..f7372dd42e1 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -4783,7 +4783,6 @@ instantiate_class_template (type) TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern); TYPE_HAS_DESTRUCTOR (type) = TYPE_HAS_DESTRUCTOR (pattern); - TYPE_HAS_ASSIGNMENT (type) = TYPE_HAS_ASSIGNMENT (pattern); TYPE_OVERLOADS_CALL_EXPR (type) = TYPE_OVERLOADS_CALL_EXPR (pattern); TYPE_OVERLOADS_ARRAY_REF (type) = TYPE_OVERLOADS_ARRAY_REF (pattern); TYPE_OVERLOADS_ARROW (type) = TYPE_OVERLOADS_ARROW (pattern); @@ -6682,7 +6681,7 @@ tsubst_copy (t, args, complain, in_decl) case THROW_EXPR: case TYPEID_EXPR: return build1 - (code, NULL_TREE, + (code, tsubst (TREE_TYPE (t), args, complain, in_decl), tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl)); case PLUS_EXPR: diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c index 4fb0413b9c0..2cff6552ed9 100644 --- a/gcc/cp/ptree.c +++ b/gcc/cp/ptree.c @@ -113,8 +113,6 @@ print_lang_type (file, node, indent) fputs (" delete", file); if (TYPE_GETS_DELETE (node) & 2) fputs (" delete[]", file); - if (TYPE_HAS_ASSIGNMENT (node)) - fputs (" has=", file); if (TYPE_HAS_ASSIGN_REF (node)) fputs (" this=(X&)", file); if (TYPE_OVERLOADS_CALL_EXPR (node)) diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 0218b56827d..a5301beb8b0 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -147,6 +147,8 @@ static tree access_in_type PROTO ((tree, tree)); static tree dfs_canonical_queue PROTO ((tree, void *)); static tree dfs_assert_unmarked_p PROTO ((tree, void *)); static void assert_canonical_unmarked PROTO ((tree)); +static int protected_accessible_p PROTO ((tree, tree, tree, tree)); +static int friend_accessible_p PROTO ((tree, tree, tree, tree)); /* Allocate a level of searching. */ @@ -846,6 +848,116 @@ dfs_accessible_p (binfo, data) return NULL_TREE; } +/* Returns non-zero if it is OK to access DECL when named in TYPE + through an object indiated by BINFO in the context of DERIVED. */ + +static int +protected_accessible_p (type, decl, derived, binfo) + tree type; + tree decl; + tree derived; + tree binfo; +{ + tree access; + + /* We're checking this clause from [class.access.base] + + m as a member of N is protected, and the reference occurs in a + member or friend of class N, or in a member or friend of a + class P derived from N, where m as a member of P is private or + protected. + + If DERIVED isn't derived from TYPE, then it certainly does not + apply. */ + if (!DERIVED_FROM_P (type, derived)) + return 0; + + access = access_in_type (derived, decl); + if (same_type_p (derived, type)) + { + if (access != access_private_node) + return 0; + } + else if (access != access_private_node + && access != access_protected_node) + return 0; + + /* [class.protected] + + When a friend or a member function of a derived class references + a protected nonstatic member of a base class, an access check + applies in addition to those described earlier in clause + _class.access_.4) Except when forming a pointer to member + (_expr.unary.op_), the access must be through a pointer to, + reference to, or object of the derived class itself (or any class + derived from that class) (_expr.ref_). If the access is to form + a pointer to member, the nested-name-specifier shall name the + derived class (or any class derived from that class). */ + if (DECL_NONSTATIC_MEMBER_P (decl)) + { + /* We can tell through what the reference is occurring by + chasing BINFO up to the root. */ + tree t = binfo; + while (BINFO_INHERITANCE_CHAIN (t)) + t = BINFO_INHERITANCE_CHAIN (t); + + if (!DERIVED_FROM_P (derived, BINFO_TYPE (t))) + return 0; + } + + return 1; +} + +/* Returns non-zero if SCOPE is a friend of a type which would be able + to acces DECL, named in TYPE, through the object indicated by + BINFO. */ + +static int +friend_accessible_p (scope, type, decl, binfo) + tree scope; + tree type; + tree decl; + tree binfo; +{ + tree befriending_classes; + tree t; + + if (!scope) + return 0; + + if (TREE_CODE (scope) == FUNCTION_DECL + || DECL_FUNCTION_TEMPLATE_P (scope)) + befriending_classes = DECL_BEFRIENDING_CLASSES (scope); + else if (TYPE_P (scope)) + befriending_classes = CLASSTYPE_BEFRIENDING_CLASSES (scope); + else + return 0; + + for (t = befriending_classes; t; t = TREE_CHAIN (t)) + if (protected_accessible_p (type, decl, TREE_VALUE (t), binfo)) + return 1; + + if (TREE_CODE (scope) == FUNCTION_DECL + || DECL_FUNCTION_TEMPLATE_P (scope)) + { + /* Perhaps this SCOPE is a member of a class which is a + friend. */ + if (friend_accessible_p (DECL_CLASS_CONTEXT (scope), type, + decl, binfo)) + return 1; + + /* Or an instantiation of something which is a friend. */ + if (DECL_TEMPLATE_INFO (scope)) + return friend_accessible_p (DECL_TI_TEMPLATE (scope), + type, decl, binfo); + } + else if (CLASSTYPE_TEMPLATE_INFO (scope)) + return friend_accessible_p (CLASSTYPE_TI_TEMPLATE (scope), + type, decl, binfo); + + return 0; +} + /* DECL is a declaration from a base class of TYPE, which was the classs used to name DECL. Return non-zero if, in the current context, DECL is accessible. If TYPE is actually a BINFO node, @@ -858,7 +970,6 @@ accessible_p (type, decl) tree decl; { - tree scope; tree binfo; tree t; @@ -909,48 +1020,16 @@ accessible_p (type, decl) /* Figure out where the reference is occurring. Check to see if DECL is private or protected in this scope, since that will determine whether protected access in TYPE allowed. */ - if (current_class_type - && DERIVED_FROM_P (type, current_class_type)) - { - tree access = access_in_type (current_class_type, decl); - if (same_type_p (current_class_type, type) - && access == access_private_node) - protected_ok = 1; - else if (access && (access == access_private_node - || access == access_protected_node)) - protected_ok = 1; - } + if (current_class_type) + protected_ok + = protected_accessible_p (type, decl, current_class_type, + binfo); - /* Now, loop through the classes of which SCOPE is a friend. */ - if (!protected_ok && scope) - { - /* FIXME: Implement this. Right now, we have no way of knowing - which classes befriend a particular function or class. */ - } - - /* [class.protected] + /* Now, loop through the classes of which we are a friend. */ + if (!protected_ok) + protected_ok = friend_accessible_p (current_scope (), + type, decl, binfo); - When a friend or a member function of a derived class references - a protected nonstatic member of a base class, an access check - applies in addition to those described earlier in clause - _class.access_.4) Except when forming a pointer to member - (_expr.unary.op_), the access must be through a pointer to, - reference to, or object of the derived class itself (or any class - derived from that class) (_expr.ref_). If the access is to form - a pointer to member, the nested-name-specifier shall name the - derived class (or any class derived from that class). */ - if (protected_ok && DECL_NONSTATIC_MEMBER_P (decl)) - { - /* We can tell through what the reference is occurring by - chasing BINFO up to the root. */ - t = binfo; - while (BINFO_INHERITANCE_CHAIN (t)) - t = BINFO_INHERITANCE_CHAIN (t); - - if (!DERIVED_FROM_P (current_class_type, BINFO_TYPE (t))) - protected_ok = 0; - } - /* Standardize on the same that will access_in_type will use. We don't need to know what path was chosen from this point onwards. */ binfo = TYPE_BINFO (type); diff --git a/gcc/testsuite/g++.old-deja/g++.other/friend1.C b/gcc/testsuite/g++.old-deja/g++.other/friend1.C index ef90607eaeb..76fcebe1fae 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/friend1.C +++ b/gcc/testsuite/g++.old-deja/g++.other/friend1.C @@ -9,21 +9,77 @@ // From: Alexandre Oliva // Date: 06 Mar 1998 01:43:18 -0300 +template +class X {}; + +template +void g(); + +struct S; + +template +struct R; class B { protected: int i; // ERROR - in this context - static int j; // gets bogus error - XFAIL *-*-* + static int j; }; class D : public B { - friend void f(); + friend void f(); + template + friend void g(); + friend struct S; + template + friend struct R; +}; + +struct S { + void h(); + X<&B::j> x; +}; + +template +struct R { + void h(); + X<&B::j> x; }; void f() { ((B*)0)->i = 3; // ERROR - protected ((D*)0)->i = 4; - B::j = 5; // gets bogus error - XFAIL *-*-* + B::j = 5; D::j = 6; } + +template +void g() +{ + ((B*)0)->i = 3; // ERROR - protected + ((D*)0)->i = 4; + B::j = 5; + D::j = 6; +} + +template void g(); + +void S::h() +{ + ((B*)0)->i = 3; // ERROR - protected + ((D*)0)->i = 4; + B::j = 5; + D::j = 6; +} + +template +void R::h() +{ + ((B*)0)->i = 3; // ERROR - protected + ((D*)0)->i = 4; + B::j = 5; + D::j = 6; +} + +template struct R;