(C++) patch to implement access control for types
Jason Merrill
jason@cygnus.com
Mon Feb 7 12:33:00 GMT 2000
I finally got tired of the periodic reports that this doesn't work and
decided to make it work. See the comment before type_access_control
for a description of the design; it's a bit cheesy, but it works. I
also fixed access control for static data members of enclosing classes
while I was at it.
2000-02-07 Jason Merrill <jason@casey.cygnus.com>
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.
* parse.y (typed_typespecs): Propagate new_type_flag properly.
Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.253
diff -c -p -r1.253 class.c
*** class.c 2000/02/06 04:27:53 1.253
--- class.c 2000/02/07 20:21:40
*************** popclass ()
*** 5487,5493 ****
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. */
int
currently_open_class (t)
--- 5487,5495 ----
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.
! We start looking from 1 because entry 0 is from global scope, and has
! no type. */
int
currently_open_class (t)
*************** currently_open_class (t)
*** 5496,5505 ****
int i;
if (t == current_class_type)
return 1;
! for (i = 0; i < current_class_depth; ++i)
if (current_class_stack [i].type == t)
return 1;
return 0;
}
/* When entering a class scope, all enclosing class scopes' names with
--- 5498,5527 ----
int i;
if (t == current_class_type)
return 1;
! for (i = 1; i < current_class_depth; ++i)
if (current_class_stack [i].type == t)
return 1;
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
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.400
diff -c -p -r1.400 cp-tree.h
*** cp-tree.h 2000/01/31 21:00:01 1.400
--- cp-tree.h 2000/02/07 20:21:43
*************** typedef struct
*** 276,281 ****
--- 276,282 ----
{
tree t;
int new_type_flag;
+ tree lookups;
} flagged_type_tree;
typedef struct
*************** struct saved_scope {
*** 714,719 ****
--- 715,722 ----
tree x_previous_class_type;
tree x_previous_class_values;
tree x_saved_tree;
+ tree lookups;
HOST_WIDE_INT x_processing_template_decl;
int x_processing_specialization;
*************** struct saved_scope {
*** 774,779 ****
--- 777,790 ----
#define previous_class_values scope_chain->x_previous_class_values
+ /* A list of private types mentioned, for deferred access checking. */
+
+ #define type_lookups scope_chain->lookups
+
extern struct saved_scope *scope_chain;
/* Global state pertinent to the current function. */
*************** extern tree build_vfn_ref PARAMS ((tre
*** 3550,3555 ****
--- 3561,3567 ----
extern tree get_vtable_decl PARAMS ((tree, int));
extern void add_method PARAMS ((tree, tree *, tree));
extern int currently_open_class PARAMS ((tree));
+ extern tree currently_open_derived_class PARAMS ((tree));
extern tree get_vfield_offset PARAMS ((tree));
extern void duplicate_tag_error PARAMS ((tree));
extern tree finish_struct PARAMS ((tree, tree));
*************** extern tree get_vbase PARAMS ((tree,
*** 4043,4048 ****
--- 4055,4061 ----
extern tree get_binfo PARAMS ((tree, tree, int));
extern int get_base_distance PARAMS ((tree, tree, int, 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 tree lookup_field PARAMS ((tree, tree, int, int));
extern int lookup_fnfields_1 PARAMS ((tree, tree));
*************** extern tree finish_qualified_call_expr
*** 4153,4159 ****
extern tree finish_label_address_expr PARAMS ((tree));
extern tree finish_unary_op_expr PARAMS ((enum tree_code, tree));
extern tree finish_id_expr PARAMS ((tree));
! extern int begin_function_definition PARAMS ((tree, tree));
extern tree begin_constructor_declarator PARAMS ((tree, tree));
extern tree finish_declarator PARAMS ((tree, tree, tree, tree, int));
extern void finish_translation_unit PARAMS ((void));
--- 4166,4174 ----
extern tree finish_label_address_expr PARAMS ((tree));
extern tree finish_unary_op_expr PARAMS ((enum tree_code, tree));
extern tree finish_id_expr PARAMS ((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 finish_declarator PARAMS ((tree, tree, tree, tree, int));
extern void finish_translation_unit PARAMS ((void));
Index: decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.541
diff -c -p -r1.541 decl.c
*** decl.c 2000/01/29 19:10:00 1.541
--- decl.c 2000/02/07 20:21:52
*************** struct binding_level
*** 442,447 ****
--- 442,450 ----
If 0, the BLOCK is allocated (if needed) when the level is popped. */
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). */
struct binding_level *level_chain;
*************** pushlevel_class ()
*** 1524,1529 ****
--- 1527,1533 ----
class_binding_level = current_binding_level;
class_binding_level->parm_flag = 2;
+ class_binding_level->this_class = current_class_type;
}
/* ...and a poplevel for class declarations. */
*************** mark_binding_level (arg)
*** 1837,1842 ****
--- 1841,1847 ----
ggc_mark_tree (lvl->shadowed_labels);
ggc_mark_tree (lvl->blocks);
ggc_mark_tree (lvl->this_block);
+ ggc_mark_tree (lvl->this_class);
ggc_mark_tree (lvl->incomplete);
ggc_mark_tree (lvl->dead_vars_from_for);
*************** mark_saved_scope (arg)
*** 2278,2283 ****
--- 2283,2290 ----
ggc_mark_tree (t->x_previous_class_type);
ggc_mark_tree (t->x_previous_class_values);
ggc_mark_tree (t->x_saved_tree);
+ ggc_mark_tree (t->lookups);
mark_stmt_tree (&t->x_stmt_tree);
mark_binding_level (&t->bindings);
*************** lookup_name_real (name, prefer_type, non
*** 5602,5608 ****
else if (type == current_class_type)
val = IDENTIFIER_CLASS_VALUE (name);
else
! val = lookup_member (type, name, 0, prefer_type);
}
else
val = NULL_TREE;
--- 5615,5624 ----
else if (type == current_class_type)
val = IDENTIFIER_CLASS_VALUE (name);
else
! {
! val = lookup_member (type, name, 0, prefer_type);
! type_access_control (type, val);
! }
}
else
val = NULL_TREE;
*************** lookup_name_real (name, prefer_type, non
*** 5641,5646 ****
--- 5657,5667 ----
else
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
&& (!val || !IMPLICIT_TYPENAME_TYPE_DECL_P (binding)))
{
Index: friend.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/friend.c,v
retrieving revision 1.50
diff -c -p -r1.50 friend.c
*** friend.c 2000/01/11 08:54:28 1.50
--- friend.c 2000/02/07 20:21:53
*************** is_friend (type, supplicant)
*** 101,108 ****
else
/* It's a type. */
{
! if (type == supplicant)
! return 1;
list = CLASSTYPE_FRIEND_CLASSES (TREE_TYPE (TYPE_MAIN_DECL (type)));
for (; list ; list = TREE_CHAIN (list))
--- 101,113 ----
else
/* It's a type. */
{
! /* The type and its nested classes are implicitly friends, as
! 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)));
for (; list ; list = TREE_CHAIN (list))
Index: method.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/method.c,v
retrieving revision 1.134
diff -c -p -r1.134 method.c
*** method.c 2000/01/29 03:59:09 1.134
--- method.c 2000/02/07 20:21:56
*************** hack_identifier (value, name)
*** 1978,1984 ****
if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value))
{
! if (DECL_LANG_SPECIFIC (value)
&& DECL_CLASS_CONTEXT (value) != current_class_type)
{
tree path;
--- 1978,1984 ----
if (TREE_CODE_CLASS (TREE_CODE (value)) == 'd' && DECL_NONLOCAL (value))
{
! if (DECL_CLASS_SCOPE_P (value)
&& DECL_CLASS_CONTEXT (value) != current_class_type)
{
tree path;
*************** hack_identifier (value, name)
*** 1987,1995 ****
? DECL_CLASS_CONTEXT (value)
: DECL_CONTEXT (value);
! get_base_distance (context, current_class_type, 0, &path);
! if (path && !enforce_access (current_class_type, value))
! return error_mark_node;
}
}
else if (TREE_CODE (value) == TREE_LIST
--- 1987,1994 ----
? DECL_CLASS_CONTEXT (value)
: DECL_CONTEXT (value);
! path = currently_open_derived_class (context);
! enforce_access (path, value);
}
}
else if (TREE_CODE (value) == TREE_LIST
Index: parse.y
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/parse.y,v
retrieving revision 1.161
diff -c -p -r1.161 parse.y
*** parse.y 2000/02/02 06:30:44 1.161
--- parse.y 2000/02/07 20:22:03
*************** extern int end_of_file;
*** 63,69 ****
static const char *cond_stmt_keyword;
static tree empty_parms PARAMS ((void));
! static void parse_decl PARAMS ((tree, tree, tree, int, tree *));
/* Nonzero if we have an `extern "C"' acting as an extern specifier. */
int have_extern_spec;
--- 63,69 ----
static const char *cond_stmt_keyword;
static tree empty_parms PARAMS ((void));
! static void parse_decl PARAMS ((tree, tree, tree, tree, int, tree *));
/* Nonzero if we have an `extern "C"' acting as an extern specifier. */
int have_extern_spec;
*************** empty_parms ()
*** 197,203 ****
%type <ttype> expr_no_commas cast_expr unary_expr primary string STRING
%type <ttype> reserved_declspecs boolean.literal
%type <ttype> reserved_typespecquals
- %type <ttype> declmods
%type <ttype> SCSPEC TYPESPEC CV_QUALIFIER maybe_cv_qualifier
%type <ttype> init initlist maybeasm maybe_init defarg defarg1
%type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
--- 197,202 ----
*************** empty_parms ()
*** 233,238 ****
--- 232,238 ----
%type <ftype> type_id new_type_id typed_typespecs typespec typed_declspecs
%type <ftype> typed_declspecs1 type_specifier_seq nonempty_cv_qualifiers
%type <ftype> structsp typespecqual_reserved parm named_parm full_parm
+ %type <ftype> declmods
%type <itype> extension
*************** extern void yyprint PARAMS ((FILE *, i
*** 315,327 ****
extern tree combine_strings PARAMS ((tree));
static void
! parse_decl (declarator, specs_attrs, attributes, initialized, decl)
tree declarator;
tree specs_attrs;
tree attributes;
int initialized;
tree* decl;
{
split_specs_attrs (specs_attrs, ¤t_declspecs, &prefix_attributes);
if (current_declspecs
&& TREE_CODE (current_declspecs) != TREE_LIST)
--- 315,330 ----
extern tree combine_strings PARAMS ((tree));
static void
! parse_decl (declarator, specs_attrs, lookups, attributes, initialized, decl)
tree declarator;
tree specs_attrs;
+ tree lookups;
tree attributes;
int initialized;
tree* decl;
{
+ initial_deferred_type_access_control (lookups);
+
split_specs_attrs (specs_attrs, ¤t_declspecs, &prefix_attributes);
if (current_declspecs
&& TREE_CODE (current_declspecs) != TREE_LIST)
*************** asm_keyword:
*** 391,397 ****
;
lang_extdef:
! { if (pending_lang_change) do_pending_lang_change(); }
extdef
{ if (! toplevel_bindings_p ())
pop_everything (); }
--- 394,401 ----
;
lang_extdef:
! { if (pending_lang_change) do_pending_lang_change();
! type_lookups = NULL_TREE; }
extdef
{ if (! toplevel_bindings_p ())
pop_everything (); }
*************** constructor_declarator:
*** 695,713 ****
fn.def1:
typed_declspecs declarator
! { if (!begin_function_definition ($1.t, $2))
YYERROR1; }
| declmods notype_declarator
! { if (!begin_function_definition ($1, $2))
YYERROR1; }
| notype_declarator
! { if (!begin_function_definition (NULL_TREE, $1))
YYERROR1; }
| declmods constructor_declarator
! { if (!begin_function_definition ($1, $2))
YYERROR1; }
| constructor_declarator
! { if (!begin_function_definition (NULL_TREE, $1))
YYERROR1; }
;
--- 699,717 ----
fn.def1:
typed_declspecs declarator
! { if (!begin_function_definition ($1.t, $1.lookups, $2))
YYERROR1; }
| declmods notype_declarator
! { if (!begin_function_definition ($1.t, NULL_TREE, $2))
YYERROR1; }
| notype_declarator
! { if (!begin_function_definition (NULL_TREE, NULL_TREE, $1))
YYERROR1; }
| declmods constructor_declarator
! { if (!begin_function_definition ($1.t, NULL_TREE, $2))
YYERROR1; }
| constructor_declarator
! { if (!begin_function_definition (NULL_TREE, NULL_TREE, $1))
YYERROR1; }
;
*************** component_constructor_declarator:
*** 727,733 ****
fn.def2:
declmods component_constructor_declarator
{ tree specs, attrs;
! split_specs_attrs ($1, &specs, &attrs);
attrs = build_tree_list (attrs, NULL_TREE);
$$ = start_method (specs, $2, attrs);
rest_of_mdef:
--- 731,737 ----
fn.def2:
declmods component_constructor_declarator
{ tree specs, attrs;
! split_specs_attrs ($1.t, &specs, &attrs);
attrs = build_tree_list (attrs, NULL_TREE);
$$ = start_method (specs, $2, attrs);
rest_of_mdef:
*************** fn.def2:
*** 746,752 ****
$$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
| declmods notype_declarator
{ tree specs, attrs;
! split_specs_attrs ($1, &specs, &attrs);
attrs = build_tree_list (attrs, NULL_TREE);
$$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
| notype_declarator
--- 750,756 ----
$$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
| declmods notype_declarator
{ tree specs, attrs;
! split_specs_attrs ($1.t, &specs, &attrs);
attrs = build_tree_list (attrs, NULL_TREE);
$$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
| notype_declarator
*************** fn.def2:
*** 754,760 ****
goto rest_of_mdef; }
| declmods constructor_declarator
{ tree specs, attrs;
! split_specs_attrs ($1, &specs, &attrs);
attrs = build_tree_list (attrs, NULL_TREE);
$$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
| constructor_declarator
--- 758,764 ----
goto rest_of_mdef; }
| declmods constructor_declarator
{ tree specs, attrs;
! split_specs_attrs ($1.t, &specs, &attrs);
attrs = build_tree_list (attrs, NULL_TREE);
$$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
| constructor_declarator
*************** type_id:
*** 1667,1678 ****
typed_declspecs:
typed_typespecs %prec EMPTY
| typed_declspecs1
;
typed_declspecs1:
declmods typespec
! { $$.t = decl_tree_cons (NULL_TREE, $2.t, $1);
$$.new_type_flag = $2.new_type_flag; }
| typespec reserved_declspecs %prec HYPERUNARY
{ $$.t = decl_tree_cons (NULL_TREE, $1.t, $2);
--- 1671,1684 ----
typed_declspecs:
typed_typespecs %prec EMPTY
+ { $$.lookups = type_lookups; }
| typed_declspecs1
+ { $$.lookups = type_lookups; }
;
typed_declspecs1:
declmods typespec
! { $$.t = decl_tree_cons (NULL_TREE, $2.t, $1.t);
$$.new_type_flag = $2.new_type_flag; }
| typespec reserved_declspecs %prec HYPERUNARY
{ $$.t = decl_tree_cons (NULL_TREE, $1.t, $2);
*************** typed_declspecs1:
*** 1681,1694 ****
{ $$.t = decl_tree_cons (NULL_TREE, $1.t, chainon ($2, $3));
$$.new_type_flag = $1.new_type_flag; }
| declmods typespec reserved_declspecs
! { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1));
$$.new_type_flag = $2.new_type_flag; }
| declmods typespec reserved_typespecquals
! { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1));
$$.new_type_flag = $2.new_type_flag; }
| declmods typespec reserved_typespecquals reserved_declspecs
{ $$.t = decl_tree_cons (NULL_TREE, $2.t,
! chainon ($3, chainon ($4, $1)));
$$.new_type_flag = $2.new_type_flag; }
;
--- 1687,1700 ----
{ $$.t = decl_tree_cons (NULL_TREE, $1.t, chainon ($2, $3));
$$.new_type_flag = $1.new_type_flag; }
| declmods typespec reserved_declspecs
! { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
$$.new_type_flag = $2.new_type_flag; }
| declmods typespec reserved_typespecquals
! { $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
$$.new_type_flag = $2.new_type_flag; }
| declmods typespec reserved_typespecquals reserved_declspecs
{ $$.t = decl_tree_cons (NULL_TREE, $2.t,
! chainon ($3, chainon ($4, $1.t)));
$$.new_type_flag = $2.new_type_flag; }
;
*************** reserved_declspecs:
*** 1727,1748 ****
declmods:
nonempty_cv_qualifiers %prec EMPTY
! { $$ = $1.t; TREE_STATIC ($$) = 1; }
| SCSPEC
! { $$ = hash_tree_cons (NULL_TREE, $$, NULL_TREE); }
| declmods CV_QUALIFIER
! { $$ = hash_tree_cons (NULL_TREE, $2, $$);
! TREE_STATIC ($$) = 1; }
| declmods SCSPEC
! { if (extra_warnings && TREE_STATIC ($$))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
! $$ = hash_tree_cons (NULL_TREE, $2, $$);
! TREE_STATIC ($$) = TREE_STATIC ($1); }
| declmods attributes
! { $$ = hash_tree_cons ($2, NULL_TREE, $1); }
| attributes %prec EMPTY
! { $$ = hash_tree_cons ($1, NULL_TREE, NULL_TREE); }
;
/* Used instead of declspecs where storage classes are not allowed
--- 1733,1764 ----
declmods:
nonempty_cv_qualifiers %prec EMPTY
! { $$.lookups = NULL_TREE; TREE_STATIC ($$.t) = 1; }
| SCSPEC
! {
! $$.t = hash_tree_cons (NULL_TREE, $1, NULL_TREE);
! $$.new_type_flag = 0; $$.lookups = NULL_TREE;
! }
| declmods CV_QUALIFIER
! {
! $$.t = hash_tree_cons (NULL_TREE, $2, $1.t);
! TREE_STATIC ($$.t) = 1;
! }
| declmods SCSPEC
! {
! if (extra_warnings && TREE_STATIC ($$.t))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
! $$.t = hash_tree_cons (NULL_TREE, $2, $1.t);
! TREE_STATIC ($$.t) = TREE_STATIC ($1.t);
! }
| declmods attributes
! { $$.t = hash_tree_cons ($2, NULL_TREE, $1.t); }
| attributes %prec EMPTY
! {
! $$.t = hash_tree_cons ($1, NULL_TREE, NULL_TREE);
! $$.new_type_flag = 0; $$.lookups = NULL_TREE;
! }
;
/* Used instead of declspecs where storage classes are not allowed
*************** typed_typespecs:
*** 1763,1769 ****
$$.new_type_flag = $1.new_type_flag; }
| nonempty_cv_qualifiers typespec reserved_typespecquals
{ $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
! $$.new_type_flag = $1.new_type_flag; }
;
reserved_typespecquals:
--- 1779,1785 ----
$$.new_type_flag = $1.new_type_flag; }
| nonempty_cv_qualifiers typespec reserved_typespecquals
{ $$.t = decl_tree_cons (NULL_TREE, $2.t, chainon ($3, $1.t));
! $$.new_type_flag = $2.new_type_flag; }
;
reserved_typespecquals:
*************** reserved_typespecquals:
*** 1779,1798 ****
typespec:
structsp
| TYPESPEC %prec EMPTY
! { $$.t = $1; $$.new_type_flag = 0; }
| complete_type_name
! { $$.t = $1; $$.new_type_flag = 0; }
| TYPEOF '(' expr ')'
{ $$.t = finish_typeof ($3);
! $$.new_type_flag = 0; }
| TYPEOF '(' type_id ')'
{ $$.t = groktypename ($3.t);
! $$.new_type_flag = 0; }
| SIGOF '(' expr ')'
{ tree type = TREE_TYPE ($3);
! $$.new_type_flag = 0;
if (IS_AGGR_TYPE (type))
{
sorry ("sigof type specifier");
--- 1795,1815 ----
typespec:
structsp
+ { $$.lookups = NULL_TREE; }
| TYPESPEC %prec EMPTY
! { $$.t = $1; $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
| complete_type_name
! { $$.t = $1; $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
| TYPEOF '(' expr ')'
{ $$.t = finish_typeof ($3);
! $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
| TYPEOF '(' type_id ')'
{ $$.t = groktypename ($3.t);
! $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
| SIGOF '(' expr ')'
{ tree type = TREE_TYPE ($3);
! $$.new_type_flag = 0; $$.lookups = NULL_TREE;
if (IS_AGGR_TYPE (type))
{
sorry ("sigof type specifier");
*************** typespec:
*** 1807,1813 ****
| SIGOF '(' type_id ')'
{ tree type = groktypename ($3.t);
! $$.new_type_flag = 0;
if (IS_AGGR_TYPE (type))
{
sorry ("sigof type specifier");
--- 1824,1830 ----
| SIGOF '(' type_id ')'
{ tree type = groktypename ($3.t);
! $$.new_type_flag = 0; $$.lookups = NULL_TREE;
if (IS_AGGR_TYPE (type))
{
sorry ("sigof type specifier");
*************** maybeasm:
*** 1858,1872 ****
initdcl:
declarator maybeasm maybe_attribute '='
! { $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1,
! $3, prefix_attributes); }
init
/* Note how the declaration of the variable is in effect while its init is parsed! */
{ cp_finish_decl ($<ttype>5, $6, $2, LOOKUP_ONLYCONVERTING); }
| declarator maybeasm maybe_attribute
! { $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 0,
$3, prefix_attributes);
! cp_finish_decl ($<ttype>$, NULL_TREE, $2, 0); }
;
/* This rule assumes a certain configuration of the parser stack.
--- 1875,1895 ----
initdcl:
declarator maybeasm maybe_attribute '='
! {
! deferred_type_access_control ();
! $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1,
! $3, prefix_attributes);
! }
init
/* Note how the declaration of the variable is in effect while its init is parsed! */
{ cp_finish_decl ($<ttype>5, $6, $2, LOOKUP_ONLYCONVERTING); }
| declarator maybeasm maybe_attribute
! {
! deferred_type_access_control ();
! $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 0,
$3, prefix_attributes);
! cp_finish_decl ($<ttype>$, NULL_TREE, $2, 0);
! }
;
/* This rule assumes a certain configuration of the parser stack.
*************** initdcl:
*** 1877,1883 ****
we need that reduce so we prefer fn.def1 when appropriate. */
initdcl0_innards:
maybe_attribute '='
! { parse_decl ($<ttype>-1, $<ttype>-2, $1, 1, &$<ttype>$); }
/* Note how the declaration of the variable is in effect
while its init is parsed! */
init
--- 1900,1907 ----
we need that reduce so we prefer fn.def1 when appropriate. */
initdcl0_innards:
maybe_attribute '='
! { parse_decl ($<ttype>-1, $<ftype>-2.t, $<ftype>-2.lookups,
! $1, 1, &$<ttype>$); }
/* Note how the declaration of the variable is in effect
while its init is parsed! */
init
*************** initdcl0_innards:
*** 1885,1891 ****
LOOKUP_ONLYCONVERTING); }
| maybe_attribute
{ tree d;
! parse_decl ($<ttype>-1, $<ttype>-2, $1, 0, &d);
cp_finish_decl (d, NULL_TREE, $<ttype>0, 0); }
;
--- 1909,1916 ----
LOOKUP_ONLYCONVERTING); }
| maybe_attribute
{ tree d;
! parse_decl ($<ttype>-1, $<ftype>-2.t, $<ftype>-2.lookups,
! $1, 0, &d);
cp_finish_decl (d, NULL_TREE, $<ttype>0, 0); }
;
*************** nomods_initdcl0:
*** 1908,1914 ****
{}
| constructor_declarator maybeasm maybe_attribute
{ tree d;
! parse_decl($1, NULL_TREE, $3, 0, &d);
cp_finish_decl (d, NULL_TREE, $2, 0); }
;
--- 1933,1939 ----
{}
| constructor_declarator maybeasm maybe_attribute
{ tree d;
! parse_decl ($1, NULL_TREE, NULL_TREE, $3, 0, &d);
cp_finish_decl (d, NULL_TREE, $2, 0); }
;
*************** component_decl_1:
*** 2431,2437 ****
| declmods notype_components
{
if (!$2)
! grok_x_components ($1);
$$ = NULL_TREE;
}
| notype_declarator maybeasm maybe_attribute maybe_init
--- 2456,2462 ----
| declmods notype_components
{
if (!$2)
! grok_x_components ($1.t);
$$ = NULL_TREE;
}
| notype_declarator maybeasm maybe_attribute maybe_init
*************** component_decl_1:
*** 2455,2461 ****
parmlist? */
| declmods component_constructor_declarator maybeasm maybe_attribute maybe_init
{ tree specs, attrs;
! split_specs_attrs ($1, &specs, &attrs);
$$ = grokfield ($2, specs, $5, $3,
build_tree_list ($4, attrs)); }
| component_constructor_declarator maybeasm maybe_attribute maybe_init
--- 2480,2486 ----
parmlist? */
| declmods component_constructor_declarator maybeasm maybe_attribute maybe_init
{ tree specs, attrs;
! split_specs_attrs ($1.t, &specs, &attrs);
$$ = grokfield ($2, specs, $5, $3,
build_tree_list ($4, attrs)); }
| component_constructor_declarator maybeasm maybe_attribute maybe_init
*************** functional_cast:
*** 2824,2829 ****
--- 2849,2855 ----
| typespec fcast_or_absdcl %prec EMPTY
{ $$ = reparse_absdcl_as_expr ($1.t, $2); }
;
+
type_name:
TYPENAME
| SELFNAME
*************** named_parm:
*** 3529,3535 ****
$$.t = build_tree_list (specs, NULL_TREE);
$$.new_type_flag = $1.new_type_flag; }
| declmods notype_declarator
! { tree specs = strip_attrs ($1);
$$.t = build_tree_list (specs, $2);
$$.new_type_flag = 0; }
;
--- 3555,3561 ----
$$.t = build_tree_list (specs, NULL_TREE);
$$.new_type_flag = $1.new_type_flag; }
| declmods notype_declarator
! { tree specs = strip_attrs ($1.t);
$$.t = build_tree_list (specs, $2);
$$.new_type_flag = 0; }
;
Index: search.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/search.c,v
retrieving revision 1.151
diff -c -p -r1.151 search.c
*** search.c 2000/02/06 04:27:53 1.151
--- search.c 2000/02/07 20:22:05
*************** friend_accessible_p (scope, type, decl,
*** 1072,1080 ****
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,
then we can tell in what context the access is occurring by looking
at the most derived class along the path indicated by BINFO. */
--- 1072,1115 ----
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
! class used to name DECL. Return non-zero if, in the current
context, DECL is accessible. If TYPE is actually a BINFO node,
then we can tell in what context the access is occurring by looking
at the most derived class along the path indicated by BINFO. */
*************** accessible_p (type, decl)
*** 1101,1110 ****
if (!TYPE_P (context_for_name_lookup (decl)))
return 1;
- /* We don't do access control for types yet. */
- if (TREE_CODE (decl) == TYPE_DECL)
- return 1;
-
if (!TYPE_P (type))
{
binfo = type;
--- 1136,1141 ----
Index: semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/semantics.c,v
retrieving revision 1.122
diff -c -p -r1.122 semantics.c
*** semantics.c 2000/01/26 20:51:37 1.122
--- semantics.c 2000/02/07 20:22:07
*************** finish_id_expr (expr)
*** 1690,1706 ****
return expr;
}
! /* Begin a function defniition declared with DECL_SPECS and
DECLARATOR. Returns non-zero if the function-declaration is
legal. */
int
! begin_function_definition (decl_specs, declarator)
tree decl_specs;
tree declarator;
{
tree specs;
tree attrs;
split_specs_attrs (decl_specs, &specs, &attrs);
if (!start_function (specs, declarator, attrs, SF_DEFAULT))
return 0;
--- 1690,1745 ----
return expr;
}
! 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;
!
! 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
legal. */
int
! begin_function_definition (decl_specs, lookups, declarator)
tree decl_specs;
+ tree lookups;
tree declarator;
{
tree specs;
tree attrs;
+
+ initial_deferred_type_access_control (lookups);
+
split_specs_attrs (decl_specs, &specs, &attrs);
if (!start_function (specs, declarator, attrs, SF_DEFAULT))
return 0;
More information about the Gcc-patches
mailing list