Commit 6a629cac by Mark Mitchell Committed by Mark Mitchell

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
parent 7ad3a049
1999-03-24 Mark Mitchell <mark@codesourcery.com>
* 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 <mark@codesourcery.com> 1999-03-23 Mark Mitchell <mark@codesourcery.com>
* pt.c (convert_nontype_argument): Don't create things that aren't * pt.c (convert_nontype_argument): Don't create things that aren't
......
...@@ -3808,7 +3808,6 @@ finish_struct_1 (t, warn_anon) ...@@ -3808,7 +3808,6 @@ finish_struct_1 (t, warn_anon)
if (! IS_SIGNATURE (t)) if (! IS_SIGNATURE (t))
CLASSTYPE_NON_AGGREGATE (t) CLASSTYPE_NON_AGGREGATE (t)
= ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (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_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t);
TYPE_HAS_COMPLEX_ASSIGN_REF (t) TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t); |= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t);
......
...@@ -683,12 +683,12 @@ struct lang_type ...@@ -683,12 +683,12 @@ struct lang_type
{ {
unsigned has_type_conversion : 1; unsigned has_type_conversion : 1;
unsigned has_init_ref : 1; unsigned has_init_ref : 1;
unsigned has_assignment : 1;
unsigned has_default_ctor : 1; unsigned has_default_ctor : 1;
unsigned uses_multiple_inheritance : 1; unsigned uses_multiple_inheritance : 1;
unsigned const_needs_init : 1; unsigned const_needs_init : 1;
unsigned ref_needs_init : 1; unsigned ref_needs_init : 1;
unsigned has_const_assign_ref : 1; unsigned has_const_assign_ref : 1;
unsigned anon_union : 1;
unsigned has_nonpublic_ctor : 2; unsigned has_nonpublic_ctor : 2;
unsigned has_nonpublic_assign_ref : 2; unsigned has_nonpublic_assign_ref : 2;
...@@ -721,22 +721,20 @@ struct lang_type ...@@ -721,22 +721,20 @@ struct lang_type
unsigned has_opaque_typedecls : 1; unsigned has_opaque_typedecls : 1;
unsigned sigtable_has_been_generated : 1; unsigned sigtable_has_been_generated : 1;
unsigned was_anonymous : 1; unsigned was_anonymous : 1;
unsigned has_real_assignment : 1;
unsigned has_real_assign_ref : 1; unsigned has_real_assign_ref : 1;
unsigned has_const_init_ref : 1; unsigned has_const_init_ref : 1;
unsigned has_complex_init_ref : 1; unsigned has_complex_init_ref : 1;
unsigned has_complex_assign_ref : 1; unsigned has_complex_assign_ref : 1;
unsigned has_abstract_assign_ref : 1; unsigned has_abstract_assign_ref : 1;
unsigned non_aggregate : 1; unsigned non_aggregate : 1;
unsigned is_partial_instantiation : 1; unsigned is_partial_instantiation : 1;
unsigned has_mutable : 1; unsigned has_mutable : 1;
unsigned anon_union : 1;
/* The MIPS compiler gets it wrong if this struct also /* The MIPS compiler gets it wrong if this struct also
does not fill out to a multiple of 4 bytes. Add a does not fill out to a multiple of 4 bytes. Add a
member `dummy' with new bits if you go over the edge. */ member `dummy' with new bits if you go over the edge. */
unsigned dummy : 9; unsigned dummy : 11;
} type_flags; } type_flags;
int n_ancestors; int n_ancestors;
...@@ -772,8 +770,8 @@ struct lang_type ...@@ -772,8 +770,8 @@ struct lang_type
union tree_node *signature; union tree_node *signature;
union tree_node *signature_pointer_to; union tree_node *signature_pointer_to;
union tree_node *signature_reference_to; union tree_node *signature_reference_to;
union tree_node *template_info; union tree_node *template_info;
tree befriending_classes;
}; };
/* Indicates whether or not (and how) a template was expanded for this class. /* Indicates whether or not (and how) a template was expanded for this class.
...@@ -789,13 +787,6 @@ struct lang_type ...@@ -789,13 +787,6 @@ struct lang_type
/* List of friends which were defined inline in this class definition. */ /* List of friends which were defined inline in this class definition. */
#define CLASSTYPE_INLINE_FRIENDS(NODE) (TYPE_NONCOPIED_PARTS (NODE)) #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, /* Nonzero for _CLASSTYPE means that operator new and delete are defined,
respectively. */ respectively. */
#define TYPE_GETS_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_new) #define TYPE_GETS_NEW(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.gets_new)
...@@ -1057,11 +1048,15 @@ struct lang_type ...@@ -1057,11 +1048,15 @@ struct lang_type
/* Same, but cache a list whose value is the binfo of this 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) #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 TREE_VALUE is normally a TYPE, but will be a TEMPLATE_DECL in the
case of a template friend. */ case of a template friend. */
#define CLASSTYPE_FRIEND_CLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->friend_classes) #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". */ /* 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) #define CLASSTYPE_DECLARED_CLASS(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.declared_class)
...@@ -1169,6 +1164,15 @@ struct lang_type ...@@ -1169,6 +1164,15 @@ struct lang_type
/* The binding level associated with the namespace. */ /* The binding level associated with the namespace. */
#define NAMESPACE_LEVEL(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.level) #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 struct lang_decl_flags
{ {
#ifdef ONLY_INT_FIELDS #ifdef ONLY_INT_FIELDS
...@@ -1215,6 +1219,7 @@ struct lang_decl ...@@ -1215,6 +1219,7 @@ struct lang_decl
struct lang_decl_flags decl_flags; struct lang_decl_flags decl_flags;
tree main_decl_variant; tree main_decl_variant;
tree befriending_classes;
struct pending_inline *pending_inline_info; struct pending_inline *pending_inline_info;
}; };
...@@ -1281,6 +1286,10 @@ struct lang_decl ...@@ -1281,6 +1286,10 @@ struct lang_decl
member functions for this class. */ member functions for this class. */
#define DECL_FRIEND_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.friend_attr) #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 /* Nonzero for FUNCTION_DECL means that this decl is a static
member function. */ member function. */
#define DECL_STATIC_FUNCTION_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.static_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; ...@@ -1822,6 +1831,8 @@ extern int flag_new_for_scope;
the TREE_PUROSE will be the class type, and the TREE_VALUE will be the TREE_PUROSE will be the class type, and the TREE_VALUE will be
NULL_TREE. */ NULL_TREE. */
#define DECL_FRIENDLIST(NODE) (DECL_INITIAL (NODE)) #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 /* 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 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 */ ...@@ -2677,9 +2688,6 @@ extern tree current_class_name; /* IDENTIFIER_NODE: name of current class */
#define same_or_base_type_p(type1, type2) \ #define same_or_base_type_p(type1, type2) \
comptypes ((type1), (type2), COMPARE_BASE) 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. */ /* These macros are used to access a TEMPLATE_PARM_INDEX. */
#define TEMPLATE_PARM_IDX(NODE) (((template_parm_index*) NODE)->index) #define TEMPLATE_PARM_IDX(NODE) (((template_parm_index*) NODE)->index)
#define TEMPLATE_PARM_LEVEL(NODE) (((template_parm_index*) NODE)->level) #define TEMPLATE_PARM_LEVEL(NODE) (((template_parm_index*) NODE)->level)
......
...@@ -3326,6 +3326,13 @@ duplicate_decls (newdecl, olddecl) ...@@ -3326,6 +3326,13 @@ duplicate_decls (newdecl, olddecl)
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl); DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl); DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
olddecl_friend = DECL_FRIEND_P (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) if (TREE_CODE (newdecl) == FUNCTION_DECL)
...@@ -6668,7 +6675,6 @@ fixup_anonymous_union (t) ...@@ -6668,7 +6675,6 @@ fixup_anonymous_union (t)
TYPE_HAS_INIT_REF (t) = 0; TYPE_HAS_INIT_REF (t) = 0;
TYPE_HAS_CONST_INIT_REF (t) = 0; TYPE_HAS_CONST_INIT_REF (t) = 0;
TYPE_HAS_ASSIGN_REF (t) = 0; TYPE_HAS_ASSIGN_REF (t) = 0;
TYPE_HAS_ASSIGNMENT (t) = 0;
TYPE_HAS_CONST_ASSIGN_REF (t) = 0; TYPE_HAS_CONST_ASSIGN_REF (t) = 0;
/* Splice the implicitly generated functions out of the TYPE_METHODS /* Splice the implicitly generated functions out of the TYPE_METHODS
...@@ -11804,7 +11810,7 @@ grok_op_properties (decl, virtualp, friendp) ...@@ -11804,7 +11810,7 @@ grok_op_properties (decl, virtualp, friendp)
if (name == ansi_opname[(int) MODIFY_EXPR] if (name == ansi_opname[(int) MODIFY_EXPR]
&& !(DECL_TEMPLATE_INSTANTIATION (decl) && !(DECL_TEMPLATE_INSTANTIATION (decl)
&& is_member_template (DECL_TI_TEMPLATE (decl)))) && is_member_template (DECL_TI_TEMPLATE (decl))))
TYPE_HAS_ASSIGNMENT (current_class_type) = 1; ;
else if (name == ansi_opname[(int) CALL_EXPR]) else if (name == ansi_opname[(int) CALL_EXPR])
TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1; TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
else if (name == ansi_opname[(int) ARRAY_REF]) else if (name == ansi_opname[(int) ARRAY_REF])
......
...@@ -61,9 +61,9 @@ is_friend (type, supplicant) ...@@ -61,9 +61,9 @@ is_friend (type, supplicant)
for (; list ; list = TREE_CHAIN (list)) 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)) for (; friends ; friends = TREE_CHAIN (friends))
{ {
if (same_type_p (ctype, TREE_PURPOSE (friends))) if (same_type_p (ctype, TREE_PURPOSE (friends)))
...@@ -148,11 +148,13 @@ add_friend (type, decl) ...@@ -148,11 +148,13 @@ add_friend (type, decl)
tree list = DECL_FRIENDLIST (typedecl); tree list = DECL_FRIENDLIST (typedecl);
tree name = DECL_NAME (decl); tree name = DECL_NAME (decl);
type = TREE_TYPE (typedecl);
while (list) 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)) for (; friends ; friends = TREE_CHAIN (friends))
{ {
if (decl == TREE_VALUE (friends)) if (decl == TREE_VALUE (friends))
...@@ -170,21 +172,13 @@ add_friend (type, decl) ...@@ -170,21 +172,13 @@ add_friend (type, decl)
} }
list = TREE_CHAIN (list); list = TREE_CHAIN (list);
} }
DECL_FRIENDLIST (typedecl) DECL_FRIENDLIST (typedecl)
= tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl), = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl),
DECL_FRIENDLIST (typedecl)); DECL_FRIENDLIST (typedecl));
if (DECL_NAME (decl) == ansi_opname[(int) MODIFY_EXPR]) DECL_BEFRIENDING_CLASSES (decl)
{ = tree_cons (NULL_TREE, type,
tree parmtypes = TYPE_ARG_TYPES (TREE_TYPE (decl)); DECL_BEFRIENDING_CLASSES (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;
}
}
} }
/* Declare that every member function NAME in FRIEND_TYPE /* Declare that every member function NAME in FRIEND_TYPE
...@@ -199,9 +193,9 @@ add_friends (type, name, friend_type) ...@@ -199,9 +193,9 @@ add_friends (type, name, friend_type)
while (list) 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) while (friends && TREE_PURPOSE (friends) != friend_type)
friends = TREE_CHAIN (friends); friends = TREE_CHAIN (friends);
if (friends) if (friends)
...@@ -226,13 +220,6 @@ add_friends (type, name, friend_type) ...@@ -226,13 +220,6 @@ add_friends (type, name, friend_type)
= tree_cons (name, = tree_cons (name,
build_tree_list (friend_type, NULL_TREE), build_tree_list (friend_type, NULL_TREE),
DECL_FRIENDLIST (typedecl)); 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 /* Make FRIEND_TYPE a friend class to TYPE. If FRIEND_TYPE has already
...@@ -309,6 +296,11 @@ make_friend_class (type, friend_type) ...@@ -309,6 +296,11 @@ make_friend_class (type, friend_type)
{ {
CLASSTYPE_FRIEND_CLASSES (type) CLASSTYPE_FRIEND_CLASSES (type)
= tree_cons (NULL_TREE, 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));
} }
} }
......
...@@ -4783,7 +4783,6 @@ instantiate_class_template (type) ...@@ -4783,7 +4783,6 @@ instantiate_class_template (type)
TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern); TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern);
TYPE_HAS_DESTRUCTOR (type) = TYPE_HAS_DESTRUCTOR (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_CALL_EXPR (type) = TYPE_OVERLOADS_CALL_EXPR (pattern);
TYPE_OVERLOADS_ARRAY_REF (type) = TYPE_OVERLOADS_ARRAY_REF (pattern); TYPE_OVERLOADS_ARRAY_REF (type) = TYPE_OVERLOADS_ARRAY_REF (pattern);
TYPE_OVERLOADS_ARROW (type) = TYPE_OVERLOADS_ARROW (pattern); TYPE_OVERLOADS_ARROW (type) = TYPE_OVERLOADS_ARROW (pattern);
...@@ -6682,7 +6681,7 @@ tsubst_copy (t, args, complain, in_decl) ...@@ -6682,7 +6681,7 @@ tsubst_copy (t, args, complain, in_decl)
case THROW_EXPR: case THROW_EXPR:
case TYPEID_EXPR: case TYPEID_EXPR:
return build1 return build1
(code, NULL_TREE, (code, tsubst (TREE_TYPE (t), args, complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl)); tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl));
case PLUS_EXPR: case PLUS_EXPR:
......
...@@ -113,8 +113,6 @@ print_lang_type (file, node, indent) ...@@ -113,8 +113,6 @@ print_lang_type (file, node, indent)
fputs (" delete", file); fputs (" delete", file);
if (TYPE_GETS_DELETE (node) & 2) if (TYPE_GETS_DELETE (node) & 2)
fputs (" delete[]", file); fputs (" delete[]", file);
if (TYPE_HAS_ASSIGNMENT (node))
fputs (" has=", file);
if (TYPE_HAS_ASSIGN_REF (node)) if (TYPE_HAS_ASSIGN_REF (node))
fputs (" this=(X&)", file); fputs (" this=(X&)", file);
if (TYPE_OVERLOADS_CALL_EXPR (node)) if (TYPE_OVERLOADS_CALL_EXPR (node))
......
...@@ -147,6 +147,8 @@ static tree access_in_type PROTO ((tree, tree)); ...@@ -147,6 +147,8 @@ static tree access_in_type PROTO ((tree, tree));
static tree dfs_canonical_queue PROTO ((tree, void *)); static tree dfs_canonical_queue PROTO ((tree, void *));
static tree dfs_assert_unmarked_p PROTO ((tree, void *)); static tree dfs_assert_unmarked_p PROTO ((tree, void *));
static void assert_canonical_unmarked PROTO ((tree)); 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. */ /* Allocate a level of searching. */
...@@ -846,6 +848,116 @@ dfs_accessible_p (binfo, data) ...@@ -846,6 +848,116 @@ dfs_accessible_p (binfo, data)
return NULL_TREE; 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 /* 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 classs used to name DECL. Return non-zero if, in the current
context, DECL is accessible. If TYPE is actually a BINFO node, context, DECL is accessible. If TYPE is actually a BINFO node,
...@@ -858,7 +970,6 @@ accessible_p (type, decl) ...@@ -858,7 +970,6 @@ accessible_p (type, decl)
tree decl; tree decl;
{ {
tree scope;
tree binfo; tree binfo;
tree t; tree t;
...@@ -909,48 +1020,16 @@ accessible_p (type, decl) ...@@ -909,48 +1020,16 @@ accessible_p (type, decl)
/* Figure out where the reference is occurring. Check to see if /* Figure out where the reference is occurring. Check to see if
DECL is private or protected in this scope, since that will DECL is private or protected in this scope, since that will
determine whether protected access in TYPE allowed. */ determine whether protected access in TYPE allowed. */
if (current_class_type if (current_class_type)
&& DERIVED_FROM_P (type, current_class_type)) protected_ok
{ = protected_accessible_p (type, decl, current_class_type,
tree access = access_in_type (current_class_type, decl); binfo);
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;
}
/* Now, loop through the classes of which SCOPE is a friend. */ /* Now, loop through the classes of which we are a friend. */
if (!protected_ok && scope) if (!protected_ok)
{ protected_ok = friend_accessible_p (current_scope (),
/* FIXME: Implement this. Right now, we have no way of knowing type, decl, binfo);
which classes befriend a particular function or class. */
}
/* [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 (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 /* 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. */ don't need to know what path was chosen from this point onwards. */
binfo = TYPE_BINFO (type); binfo = TYPE_BINFO (type);
......
...@@ -9,21 +9,77 @@ ...@@ -9,21 +9,77 @@
// From: Alexandre Oliva <oliva@dcc.unicamp.br> // From: Alexandre Oliva <oliva@dcc.unicamp.br>
// Date: 06 Mar 1998 01:43:18 -0300 // Date: 06 Mar 1998 01:43:18 -0300
template <int*>
class X {};
template <typename T>
void g();
struct S;
template <typename T>
struct R;
class B { class B {
protected: protected:
int i; // ERROR - in this context int i; // ERROR - in this context
static int j; // gets bogus error - XFAIL *-*-* static int j;
}; };
class D : public B { class D : public B {
friend void f(); friend void f();
template <typename T>
friend void g();
friend struct S;
template <typename T>
friend struct R;
};
struct S {
void h();
X<&B::j> x;
};
template <typename T>
struct R {
void h();
X<&B::j> x;
}; };
void f() void f()
{ {
((B*)0)->i = 3; // ERROR - protected ((B*)0)->i = 3; // ERROR - protected
((D*)0)->i = 4; ((D*)0)->i = 4;
B::j = 5; // gets bogus error - XFAIL *-*-* B::j = 5;
D::j = 6; D::j = 6;
} }
template <typename T>
void g()
{
((B*)0)->i = 3; // ERROR - protected
((D*)0)->i = 4;
B::j = 5;
D::j = 6;
}
template void g<int>();
void S::h()
{
((B*)0)->i = 3; // ERROR - protected
((D*)0)->i = 4;
B::j = 5;
D::j = 6;
}
template <typename T>
void R<T>::h()
{
((B*)0)->i = 3; // ERROR - protected
((D*)0)->i = 4;
B::j = 5;
D::j = 6;
}
template struct R<double>;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment