Commit 70adf8a9 by Jason Merrill

cp-tree.h (struct saved_scope): Add incomplete field.

        * cp-tree.h (struct saved_scope): Add incomplete field.
        (namespace_scope_incomplete): New macro.
        * decl.c (pushdecl): Use it.
        (hack_incomplete_structures): Use it.  See through artificial
        binding levels.
        (mark_saved_scope): Mark it.

        Implement access control for nested types.
        * search.c (type_access_control): New fn.
        (accessible_p): Now we do perform access control for types.
        * semantics.c (deferred_type_access_control): New fn.
        (initial_deferred_type_access_control): New fn.
        (begin_function_definition): Call it.  Add lookups parm.
        * decl.c (struct binding_level): Add this_class field.
        (pushlevel_class): Set it.
        (mark_binding_level): Mark it.
        (lookup_name_real): Use it.  Call type_access_control.
        (mark_saved_scope): Mark lookups field.
        * cp-tree.h (flagged_type_tree): Add lookups field.
        (struct saved_scope): Add lookups field.
        (type_lookups): New macro.
        * parse.y (declmods): Now <ftype>.
        (parse_decl): Add lookups parm.  Call
        initial_deferred_type_access_control.
        (lang_extdef): Clear type_lookups.
        (typed_declspecs, declmods, typespec): Set lookups field.
        (initdcl): Call deferred_type_access_control.
        (fn.def1, fn.def2, typed_declspecs1, initdcl0_innards, nomods_initdcl0,
        component_decl_1, named_parm): Adjust.
        * friend.c (is_friend): Nested classes are friends of their
        enclosing classes.

        * class.c (currently_open_derived_class): New fn.
        * method.c (hack_identifier): Use it.

        * lex.c (do_identifier): Remove obsolete code.

        * parse.y (typed_typespecs): Propagate new_type_flag properly.

From-SVN: r31837
parent dd8216e1
2000-02-07 Jason Merrill <jason@casey.cygnus.com>
* cp-tree.h (struct saved_scope): Add incomplete field.
(namespace_scope_incomplete): New macro.
* decl.c (pushdecl): Use it.
(hack_incomplete_structures): Use it. See through artificial
binding levels.
(mark_saved_scope): Mark it.
Implement access control for nested types.
* search.c (type_access_control): New fn.
(accessible_p): Now we do perform access control for types.
* semantics.c (deferred_type_access_control): New fn.
(initial_deferred_type_access_control): New fn.
(begin_function_definition): Call it. Add lookups parm.
* decl.c (struct binding_level): Add this_class field.
(pushlevel_class): Set it.
(mark_binding_level): Mark it.
(lookup_name_real): Use it. Call type_access_control.
(mark_saved_scope): Mark lookups field.
* cp-tree.h (flagged_type_tree): Add lookups field.
(struct saved_scope): Add lookups field.
(type_lookups): New macro.
* parse.y (declmods): Now <ftype>.
(parse_decl): Add lookups parm. Call
initial_deferred_type_access_control.
(lang_extdef): Clear type_lookups.
(typed_declspecs, declmods, typespec): Set lookups field.
(initdcl): Call deferred_type_access_control.
(fn.def1, fn.def2, typed_declspecs1, initdcl0_innards, nomods_initdcl0,
component_decl_1, named_parm): Adjust.
* friend.c (is_friend): Nested classes are friends of their
enclosing classes.
* class.c (currently_open_derived_class): New fn.
* method.c (hack_identifier): Use it.
* lex.c (do_identifier): Remove obsolete code.
* parse.y (typed_typespecs): Propagate new_type_flag properly.
2000-02-05 Zack Weinberg <zack@wolery.cumb.org> 2000-02-05 Zack Weinberg <zack@wolery.cumb.org>
* tinfo.h: Remove apostrophes from C++ comment (xgettext * tinfo.h: Remove apostrophes from C++ comment (xgettext
...@@ -5481,7 +5522,7 @@ Wed Jul 7 01:26:47 1999 Alexandre Oliva <oliva@dcc.unicamp.br> ...@@ -5481,7 +5522,7 @@ Wed Jul 7 01:26:47 1999 Alexandre Oliva <oliva@dcc.unicamp.br>
1999-06-19 Mark Mitchell <mark@codesourcery.com> 1999-06-19 Mark Mitchell <mark@codesourcery.com>
* semantics.c (finish_asm_statement): Apply decay conversions to * semantics.c (finish_asm_stmt): Apply decay conversions to
input operands. input operands.
* decl.c (expand_static_init): When building an anonymous function * decl.c (expand_static_init): When building an anonymous function
......
...@@ -5487,7 +5487,9 @@ popclass () ...@@ -5487,7 +5487,9 @@ popclass ()
splay_tree_delete (current_class_stack[current_class_depth].names_used); splay_tree_delete (current_class_stack[current_class_depth].names_used);
} }
/* Returns 1 if current_class_type is either T or a nested type of T. */ /* Returns 1 if current_class_type is either T or a nested type of T.
We start looking from 1 because entry 0 is from global scope, and has
no type. */
int int
currently_open_class (t) currently_open_class (t)
...@@ -5496,12 +5498,32 @@ currently_open_class (t) ...@@ -5496,12 +5498,32 @@ currently_open_class (t)
int i; int i;
if (t == current_class_type) if (t == current_class_type)
return 1; return 1;
for (i = 0; i < current_class_depth; ++i) for (i = 1; i < current_class_depth; ++i)
if (current_class_stack [i].type == t) if (current_class_stack [i].type == t)
return 1; return 1;
return 0; return 0;
} }
/* If either current_class_type or one of its enclosing classes are derived
from T, return the appropriate type. Used to determine how we found
something via unqualified lookup. */
tree
currently_open_derived_class (t)
tree t;
{
int i;
if (DERIVED_FROM_P (t, current_class_type))
return current_class_type;
for (i = current_class_depth - 1; i > 0; --i)
if (DERIVED_FROM_P (t, current_class_stack[i].type))
return current_class_stack[i].type;
return NULL_TREE;
}
/* When entering a class scope, all enclosing class scopes' names with /* When entering a class scope, all enclosing class scopes' names with
static meaning (static variables, static functions, types and enumerators) static meaning (static variables, static functions, types and enumerators)
have to be visible. This recursive function calls pushclass for all have to be visible. This recursive function calls pushclass for all
......
...@@ -276,6 +276,7 @@ typedef struct ...@@ -276,6 +276,7 @@ typedef struct
{ {
tree t; tree t;
int new_type_flag; int new_type_flag;
tree lookups;
} flagged_type_tree; } flagged_type_tree;
typedef struct typedef struct
...@@ -714,6 +715,8 @@ struct saved_scope { ...@@ -714,6 +715,8 @@ struct saved_scope {
tree x_previous_class_type; tree x_previous_class_type;
tree x_previous_class_values; tree x_previous_class_values;
tree x_saved_tree; tree x_saved_tree;
tree incomplete;
tree lookups;
HOST_WIDE_INT x_processing_template_decl; HOST_WIDE_INT x_processing_template_decl;
int x_processing_specialization; int x_processing_specialization;
...@@ -774,6 +777,14 @@ struct saved_scope { ...@@ -774,6 +777,14 @@ struct saved_scope {
#define previous_class_values scope_chain->x_previous_class_values #define previous_class_values scope_chain->x_previous_class_values
/* A list of the declarations with incomplete type at namespace scope. */
#define namespace_scope_incomplete scope_chain->incomplete
/* A list of private types mentioned, for deferred access checking. */
#define type_lookups scope_chain->lookups
extern struct saved_scope *scope_chain; extern struct saved_scope *scope_chain;
/* Global state pertinent to the current function. */ /* Global state pertinent to the current function. */
...@@ -3550,6 +3561,7 @@ extern tree build_vfn_ref PARAMS ((tree *, tree, tree)); ...@@ -3550,6 +3561,7 @@ extern tree build_vfn_ref PARAMS ((tree *, tree, tree));
extern tree get_vtable_decl PARAMS ((tree, int)); extern tree get_vtable_decl PARAMS ((tree, int));
extern void add_method PARAMS ((tree, tree *, tree)); extern void add_method PARAMS ((tree, tree *, tree));
extern int currently_open_class PARAMS ((tree)); extern int currently_open_class PARAMS ((tree));
extern tree currently_open_derived_class PARAMS ((tree));
extern tree get_vfield_offset PARAMS ((tree)); extern tree get_vfield_offset PARAMS ((tree));
extern void duplicate_tag_error PARAMS ((tree)); extern void duplicate_tag_error PARAMS ((tree));
extern tree finish_struct PARAMS ((tree, tree)); extern tree finish_struct PARAMS ((tree, tree));
...@@ -4043,6 +4055,7 @@ extern tree get_vbase PARAMS ((tree, tree)); ...@@ -4043,6 +4055,7 @@ extern tree get_vbase PARAMS ((tree, tree));
extern tree get_binfo PARAMS ((tree, tree, int)); extern tree get_binfo PARAMS ((tree, tree, int));
extern int get_base_distance PARAMS ((tree, tree, int, tree *)); extern int get_base_distance PARAMS ((tree, tree, int, tree *));
extern tree get_dynamic_cast_base_type PARAMS ((tree, tree)); extern tree get_dynamic_cast_base_type PARAMS ((tree, tree));
extern void type_access_control PARAMS ((tree, tree));
extern int accessible_p PARAMS ((tree, tree)); extern int accessible_p PARAMS ((tree, tree));
extern tree lookup_field PARAMS ((tree, tree, int, int)); extern tree lookup_field PARAMS ((tree, tree, int, int));
extern int lookup_fnfields_1 PARAMS ((tree, tree)); extern int lookup_fnfields_1 PARAMS ((tree, tree));
...@@ -4153,7 +4166,9 @@ extern tree finish_qualified_call_expr PARAMS ((tree, tree)); ...@@ -4153,7 +4166,9 @@ extern tree finish_qualified_call_expr PARAMS ((tree, tree));
extern tree finish_label_address_expr PARAMS ((tree)); extern tree finish_label_address_expr PARAMS ((tree));
extern tree finish_unary_op_expr PARAMS ((enum tree_code, tree)); extern tree finish_unary_op_expr PARAMS ((enum tree_code, tree));
extern tree finish_id_expr PARAMS ((tree)); extern tree finish_id_expr PARAMS ((tree));
extern int begin_function_definition PARAMS ((tree, tree)); extern void deferred_type_access_control PARAMS ((void));
extern void initial_deferred_type_access_control PARAMS ((tree));
extern int begin_function_definition PARAMS ((tree, tree, tree));
extern tree begin_constructor_declarator PARAMS ((tree, tree)); extern tree begin_constructor_declarator PARAMS ((tree, tree));
extern tree finish_declarator PARAMS ((tree, tree, tree, tree, int)); extern tree finish_declarator PARAMS ((tree, tree, tree, tree, int));
extern void finish_translation_unit PARAMS ((void)); extern void finish_translation_unit PARAMS ((void));
......
...@@ -442,6 +442,9 @@ struct binding_level ...@@ -442,6 +442,9 @@ struct binding_level
If 0, the BLOCK is allocated (if needed) when the level is popped. */ If 0, the BLOCK is allocated (if needed) when the level is popped. */
tree this_block; tree this_block;
/* The _TYPE node for this level, if parm_flag == 2. */
tree this_class;
/* The binding level which this one is contained in (inherits from). */ /* The binding level which this one is contained in (inherits from). */
struct binding_level *level_chain; struct binding_level *level_chain;
...@@ -1524,6 +1527,7 @@ pushlevel_class () ...@@ -1524,6 +1527,7 @@ pushlevel_class ()
class_binding_level = current_binding_level; class_binding_level = current_binding_level;
class_binding_level->parm_flag = 2; class_binding_level->parm_flag = 2;
class_binding_level->this_class = current_class_type;
} }
/* ...and a poplevel for class declarations. */ /* ...and a poplevel for class declarations. */
...@@ -1837,6 +1841,7 @@ mark_binding_level (arg) ...@@ -1837,6 +1841,7 @@ mark_binding_level (arg)
ggc_mark_tree (lvl->shadowed_labels); ggc_mark_tree (lvl->shadowed_labels);
ggc_mark_tree (lvl->blocks); ggc_mark_tree (lvl->blocks);
ggc_mark_tree (lvl->this_block); ggc_mark_tree (lvl->this_block);
ggc_mark_tree (lvl->this_class);
ggc_mark_tree (lvl->incomplete); ggc_mark_tree (lvl->incomplete);
ggc_mark_tree (lvl->dead_vars_from_for); ggc_mark_tree (lvl->dead_vars_from_for);
...@@ -2278,6 +2283,8 @@ mark_saved_scope (arg) ...@@ -2278,6 +2283,8 @@ mark_saved_scope (arg)
ggc_mark_tree (t->x_previous_class_type); ggc_mark_tree (t->x_previous_class_type);
ggc_mark_tree (t->x_previous_class_values); ggc_mark_tree (t->x_previous_class_values);
ggc_mark_tree (t->x_saved_tree); ggc_mark_tree (t->x_saved_tree);
ggc_mark_tree (t->incomplete);
ggc_mark_tree (t->lookups);
mark_stmt_tree (&t->x_stmt_tree); mark_stmt_tree (&t->x_stmt_tree);
mark_binding_level (&t->bindings); mark_binding_level (&t->bindings);
...@@ -4033,8 +4040,14 @@ pushdecl (x) ...@@ -4033,8 +4040,14 @@ pushdecl (x)
/* RTTI TD entries are created while defining the type_info. */ /* RTTI TD entries are created while defining the type_info. */
|| (TYPE_LANG_SPECIFIC (TREE_TYPE (x)) || (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
&& TYPE_BEING_DEFINED (TREE_TYPE (x))))) && TYPE_BEING_DEFINED (TREE_TYPE (x)))))
current_binding_level->incomplete {
= tree_cons (NULL_TREE, x, current_binding_level->incomplete); if (namespace_bindings_p ())
namespace_scope_incomplete
= tree_cons (NULL_TREE, x, namespace_scope_incomplete);
else
current_binding_level->incomplete
= tree_cons (NULL_TREE, x, current_binding_level->incomplete);
}
} }
if (need_new_binding) if (need_new_binding)
...@@ -5602,7 +5615,10 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only) ...@@ -5602,7 +5615,10 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
else if (type == current_class_type) else if (type == current_class_type)
val = IDENTIFIER_CLASS_VALUE (name); val = IDENTIFIER_CLASS_VALUE (name);
else else
val = lookup_member (type, name, 0, prefer_type); {
val = lookup_member (type, name, 0, prefer_type);
type_access_control (type, val);
}
} }
else else
val = NULL_TREE; val = NULL_TREE;
...@@ -5641,6 +5657,11 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only) ...@@ -5641,6 +5657,11 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
else else
binding = NULL_TREE; binding = NULL_TREE;
/* Handle access control on types from enclosing or base classes. */
if (binding && ! yylex
&& BINDING_LEVEL (t) && BINDING_LEVEL (t)->parm_flag == 2)
type_access_control (BINDING_LEVEL (t)->this_class, binding);
if (binding if (binding
&& (!val || !IMPLICIT_TYPENAME_TYPE_DECL_P (binding))) && (!val || !IMPLICIT_TYPENAME_TYPE_DECL_P (binding)))
{ {
...@@ -9118,7 +9139,7 @@ create_array_type_for_decl (name, type, size) ...@@ -9118,7 +9139,7 @@ create_array_type_for_decl (name, type, size)
ATTRLIST is a TREE_LIST node with prefix attributes in TREE_VALUE and ATTRLIST is a TREE_LIST node with prefix attributes in TREE_VALUE and
normal attributes in TREE_PURPOSE, or NULL_TREE. normal attributes in TREE_PURPOSE, or NULL_TREE.
In the TYPENAME case, DECLARATOR is really an absolute declarator. In the TYPENAME case, DECLARATOR is really an abstract declarator.
It may also be so in the PARM case, for a prototype where the It may also be so in the PARM case, for a prototype where the
argument type is specified but not the name. argument type is specified but not the name.
...@@ -14222,41 +14243,63 @@ hack_incomplete_structures (type) ...@@ -14222,41 +14243,63 @@ hack_incomplete_structures (type)
tree type; tree type;
{ {
tree *list; tree *list;
struct binding_level *level;
if (current_binding_level->incomplete == NULL_TREE)
return;
if (!type) /* Don't do this for class templates. */ if (!type) /* Don't do this for class templates. */
return; return;
for (list = &current_binding_level->incomplete; *list; ) if (namespace_bindings_p ())
{ {
tree decl = TREE_VALUE (*list); level = 0;
if ((decl && TREE_TYPE (decl) == type) list = &namespace_scope_incomplete;
|| (TREE_TYPE (decl) }
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE else
&& TREE_TYPE (TREE_TYPE (decl)) == type)) {
{ level = innermost_nonclass_level ();
int toplevel = toplevel_bindings_p (); list = &level->incomplete;
if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE }
&& TREE_TYPE (TREE_TYPE (decl)) == type)
layout_type (TREE_TYPE (decl)); while (1)
layout_decl (decl, 0); {
rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0); while (*list)
if (! toplevel) {
tree decl = TREE_VALUE (*list);
if ((decl && TREE_TYPE (decl) == type)
|| (TREE_TYPE (decl)
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
&& TREE_TYPE (TREE_TYPE (decl)) == type))
{ {
tree cleanup; int toplevel = toplevel_bindings_p ();
expand_decl (decl); if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
cleanup = maybe_build_cleanup (decl); && TREE_TYPE (TREE_TYPE (decl)) == type)
expand_decl_init (decl); layout_type (TREE_TYPE (decl));
if (! expand_decl_cleanup (decl, cleanup)) layout_decl (decl, 0);
cp_error ("parser lost in parsing declaration of `%D'", rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0);
decl); if (! toplevel)
{
tree cleanup;
expand_decl (decl);
cleanup = maybe_build_cleanup (decl);
expand_decl_init (decl);
if (! expand_decl_cleanup (decl, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
decl);
}
*list = TREE_CHAIN (*list);
} }
*list = TREE_CHAIN (*list); else
list = &TREE_CHAIN (*list);
}
/* Keep looking through artificial binding levels generated
for local variables. */
if (level && level->keep == 2)
{
level = level->level_chain;
list = &level->incomplete;
} }
else else
list = &TREE_CHAIN (*list); break;
} }
} }
......
...@@ -101,8 +101,13 @@ is_friend (type, supplicant) ...@@ -101,8 +101,13 @@ is_friend (type, supplicant)
else else
/* It's a type. */ /* It's a type. */
{ {
if (type == supplicant) /* The type and its nested classes are implicitly friends, as
return 1; per core issue 45 (this is a change from the standard). */
for (context = supplicant;
context && TYPE_P (context);
context = TYPE_CONTEXT (context))
if (type == context)
return 1;
list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_MAIN_DECL (type))); list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_MAIN_DECL (type)));
for (; list ; list = TREE_CHAIN (list)) for (; list ; list = TREE_CHAIN (list))
......
...@@ -3077,12 +3077,7 @@ do_identifier (token, parsing, args) ...@@ -3077,12 +3077,7 @@ do_identifier (token, parsing, args)
/* Remember that this name has been used in the class definition, as per /* Remember that this name has been used in the class definition, as per
[class.scope0] */ [class.scope0] */
if (id && parsing if (id && parsing)
/* Avoid breaking if we get called for a default argument that
refers to an overloaded method. Eventually this will not be
necessary, since default arguments shouldn't be parsed until
after the class is complete. (jason 3/12/97) */
&& TREE_CODE (id) != OVERLOAD)
maybe_note_name_used_in_class (token, id); maybe_note_name_used_in_class (token, id);
if (id == error_mark_node) if (id == error_mark_node)
......
...@@ -1978,7 +1978,7 @@ hack_identifier (value, name) ...@@ -1978,7 +1978,7 @@ hack_identifier (value, name)
if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value)) if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value))
{ {
if (DECL_LANG_SPECIFIC (value) if (DECL_CLASS_SCOPE_P (value)
&& DECL_CLASS_CONTEXT (value) != current_class_type) && DECL_CLASS_CONTEXT (value) != current_class_type)
{ {
tree path; tree path;
...@@ -1987,9 +1987,8 @@ hack_identifier (value, name) ...@@ -1987,9 +1987,8 @@ hack_identifier (value, name)
? DECL_CLASS_CONTEXT (value) ? DECL_CLASS_CONTEXT (value)
: DECL_CONTEXT (value); : DECL_CONTEXT (value);
get_base_distance (context, current_class_type, 0, &path); path = currently_open_derived_class (context);
if (path && !enforce_access (current_class_type, value)) enforce_access (path, value);
return error_mark_node;
} }
} }
else if (TREE_CODE (value) == TREE_LIST else if (TREE_CODE (value) == TREE_LIST
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -1072,9 +1072,44 @@ friend_accessible_p (scope, type, decl, binfo) ...@@ -1072,9 +1072,44 @@ friend_accessible_p (scope, type, decl, binfo)
return 0; return 0;
} }
/* Perform access control on TYPE_DECL VAL, which was looked up in TYPE.
This is fairly complex, so here's the design:
The lang_extdef nonterminal sets type_lookups to NULL_TREE before we
start to process a top-level declaration.
As we process the decl-specifier-seq for the declaration, any types we
see that might need access control are passed to type_access_control,
which defers checking by adding them to type_lookups.
When we are done with the decl-specifier-seq, we record the lookups we've
seen in the lookups field of the typed_declspecs nonterminal.
When we process the first declarator, either in parse_decl or
begin_function_definition, we call initial_deferred_type_access_control,
which processes any lookups from within that declarator, stores the
lookups from the decl-specifier-seq in current_type_lookups, and sets
type_lookups to error_mark_node.
Subsequent declarators process current_type_lookups again to make sure
that the types are accessible to all of the declarators. Any lookups
within subsequent declarators are processed immediately.
Within a function, type_lookups is error_mark_node, so all lookups are
processed immediately. */
void
type_access_control (type, val)
tree type, val;
{
if (val == NULL_TREE || TREE_CODE (val) != TYPE_DECL
|| ! DECL_CLASS_SCOPE_P (val))
return;
if (type_lookups == error_mark_node)
enforce_access (type, val);
else if (! accessible_p (type, val))
type_lookups = tree_cons (type, val, type_lookups);
}
/* 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 class 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,
then we can tell in what context the access is occurring by looking then we can tell in what context the access is occurring by looking
at the most derived class along the path indicated by BINFO. */ at the most derived class along the path indicated by BINFO. */
...@@ -1101,10 +1136,6 @@ accessible_p (type, decl) ...@@ -1101,10 +1136,6 @@ accessible_p (type, decl)
if (!TYPE_P (context_for_name_lookup (decl))) if (!TYPE_P (context_for_name_lookup (decl)))
return 1; return 1;
/* We don't do access control for types yet. */
if (TREE_CODE (decl) == TYPE_DECL)
return 1;
if (!TYPE_P (type)) if (!TYPE_P (type))
{ {
binfo = type; binfo = type;
...@@ -1145,8 +1176,8 @@ accessible_p (type, decl) ...@@ -1145,8 +1176,8 @@ accessible_p (type, decl)
protected_ok = friend_accessible_p (current_scope (), protected_ok = friend_accessible_p (current_scope (),
type, decl, binfo); type, decl, binfo);
/* Standardize on the same that will access_in_type will use. We /* Standardize the binfo that access_in_type will use. We don't
don't need to know what path was chosen from this point onwards. */ need to know what path was chosen from this point onwards. */
binfo = TYPE_BINFO (type); binfo = TYPE_BINFO (type);
/* Compute the accessibility of DECL in the class hierarchy /* Compute the accessibility of DECL in the class hierarchy
...@@ -1457,7 +1488,7 @@ lookup_field_r (binfo, data) ...@@ -1457,7 +1488,7 @@ lookup_field_r (binfo, data)
1, we enforce accessibility. If PROTECT is zero, then, for an 1, we enforce accessibility. If PROTECT is zero, then, for an
ambiguous lookup, we return NULL. If PROTECT is 1, we issue an ambiguous lookup, we return NULL. If PROTECT is 1, we issue an
error message. If PROTECT is 2, we return a TREE_LIST whose error message. If PROTECT is 2, we return a TREE_LIST whose
TREEE_TYPE is error_mark_node and whose TREE_VALUEs are the list of TREE_TYPE is error_mark_node and whose TREE_VALUEs are the list of
ambiguous candidates. ambiguous candidates.
WANT_TYPE is 1 when we should only return TYPE_DECLs, if no WANT_TYPE is 1 when we should only return TYPE_DECLs, if no
......
...@@ -1690,17 +1690,59 @@ finish_id_expr (expr) ...@@ -1690,17 +1690,59 @@ finish_id_expr (expr)
return expr; return expr;
} }
/* Begin a function defniition declared with DECL_SPECS and static tree current_type_lookups;
/* Perform deferred access control for types used in the type of a
declaration. */
void
deferred_type_access_control ()
{
tree lookup = current_type_lookups;
if (lookup == error_mark_node)
return;
for (; lookup; lookup = TREE_CHAIN (lookup))
enforce_access (TREE_PURPOSE (lookup), TREE_VALUE (lookup));
}
/* Perform deferred access control for types used in the type of a
declaration. Called for the first declarator in a declaration. */
void
initial_deferred_type_access_control (lookups)
tree lookups;
{
tree lookup = type_lookups;
/* First perform the checks for the current declarator; they will have
been added to type_lookups since typed_declspecs saved the copy that
we have been passed. */
if (lookup != error_mark_node)
for (; lookup != lookups; lookup = TREE_CHAIN (lookup))
enforce_access (TREE_PURPOSE (lookup), TREE_VALUE (lookup));
current_type_lookups = lookups;
type_lookups = error_mark_node;
deferred_type_access_control ();
}
/* Begin a function definition declared with DECL_SPECS and
DECLARATOR. Returns non-zero if the function-declaration is DECLARATOR. Returns non-zero if the function-declaration is
legal. */ legal. */
int int
begin_function_definition (decl_specs, declarator) begin_function_definition (decl_specs, lookups, declarator)
tree decl_specs; tree decl_specs;
tree lookups;
tree declarator; tree declarator;
{ {
tree specs; tree specs;
tree attrs; tree attrs;
initial_deferred_type_access_control (lookups);
split_specs_attrs (decl_specs, &specs, &attrs); split_specs_attrs (decl_specs, &specs, &attrs);
if (!start_function (specs, declarator, attrs, SF_DEFAULT)) if (!start_function (specs, declarator, attrs, SF_DEFAULT))
return 0; return 0;
......
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