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
This commit is contained in:
Jason Merrill 2000-02-07 15:36:36 -05:00
parent dd8216e19e
commit 70adf8a937
11 changed files with 1243 additions and 990 deletions

View File

@ -1,3 +1,44 @@
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>
* 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>
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.
* decl.c (expand_static_init): When building an anonymous function

View File

@ -5487,7 +5487,9 @@ popclass ()
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
currently_open_class (t)
@ -5496,12 +5498,32 @@ currently_open_class (t)
int i;
if (t == current_class_type)
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)
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
static meaning (static variables, static functions, types and enumerators)
have to be visible. This recursive function calls pushclass for all

View File

@ -276,6 +276,7 @@ typedef struct
{
tree t;
int new_type_flag;
tree lookups;
} flagged_type_tree;
typedef struct
@ -714,6 +715,8 @@ struct saved_scope {
tree x_previous_class_type;
tree x_previous_class_values;
tree x_saved_tree;
tree incomplete;
tree lookups;
HOST_WIDE_INT x_processing_template_decl;
int x_processing_specialization;
@ -774,6 +777,14 @@ struct saved_scope {
#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;
/* Global state pertinent to the current function. */
@ -3550,6 +3561,7 @@ extern tree build_vfn_ref PARAMS ((tree *, tree, tree));
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));
@ -4043,6 +4055,7 @@ extern tree get_vbase PARAMS ((tree, tree));
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));
@ -4153,7 +4166,9 @@ extern tree finish_qualified_call_expr PARAMS ((tree, tree));
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 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));

View File

@ -442,6 +442,9 @@ struct binding_level
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;
@ -1524,6 +1527,7 @@ pushlevel_class ()
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. */
@ -1837,6 +1841,7 @@ mark_binding_level (arg)
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);
@ -2278,6 +2283,8 @@ mark_saved_scope (arg)
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->incomplete);
ggc_mark_tree (t->lookups);
mark_stmt_tree (&t->x_stmt_tree);
mark_binding_level (&t->bindings);
@ -4033,8 +4040,14 @@ pushdecl (x)
/* RTTI TD entries are created while defining the type_info. */
|| (TYPE_LANG_SPECIFIC (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)
@ -5602,7 +5615,10 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
else if (type == current_class_type)
val = IDENTIFIER_CLASS_VALUE (name);
else
val = lookup_member (type, name, 0, prefer_type);
{
val = lookup_member (type, name, 0, prefer_type);
type_access_control (type, val);
}
}
else
val = NULL_TREE;
@ -5641,6 +5657,11 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
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)))
{
@ -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
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
argument type is specified but not the name.
@ -14222,41 +14243,63 @@ hack_incomplete_structures (type)
tree type;
{
tree *list;
if (current_binding_level->incomplete == NULL_TREE)
return;
struct binding_level *level;
if (!type) /* Don't do this for class templates. */
return;
for (list = &current_binding_level->incomplete; *list; )
if (namespace_bindings_p ())
{
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))
level = 0;
list = &namespace_scope_incomplete;
}
else
{
level = innermost_nonclass_level ();
list = &level->incomplete;
}
while (1)
{
while (*list)
{
int toplevel = toplevel_bindings_p ();
if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
&& TREE_TYPE (TREE_TYPE (decl)) == type)
layout_type (TREE_TYPE (decl));
layout_decl (decl, 0);
rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0);
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;
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);
int toplevel = toplevel_bindings_p ();
if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
&& TREE_TYPE (TREE_TYPE (decl)) == type)
layout_type (TREE_TYPE (decl));
layout_decl (decl, 0);
rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0);
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
list = &TREE_CHAIN (*list);
break;
}
}

View File

@ -101,8 +101,13 @@ is_friend (type, supplicant)
else
/* It's a type. */
{
if (type == supplicant)
return 1;
/* 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))

View File

@ -3077,12 +3077,7 @@ do_identifier (token, parsing, args)
/* Remember that this name has been used in the class definition, as per
[class.scope0] */
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)
if (id && parsing)
maybe_note_name_used_in_class (token, id);
if (id == error_mark_node)

View File

@ -1978,7 +1978,7 @@ hack_identifier (value, name)
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)
{
tree path;
@ -1987,9 +1987,8 @@ hack_identifier (value, name)
? 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;
path = currently_open_derived_class (context);
enforce_access (path, value);
}
}
else if (TREE_CODE (value) == TREE_LIST

File diff suppressed because it is too large Load Diff

View File

@ -63,7 +63,7 @@ extern int end_of_file;
static const char *cond_stmt_keyword;
static tree empty_parms PARAMS ((void));
static void parse_decl PARAMS ((tree, tree, tree, int, tree *));
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;
@ -197,7 +197,6 @@ empty_parms ()
%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
@ -233,6 +232,7 @@ empty_parms ()
%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
@ -315,13 +315,16 @@ extern void yyprint PARAMS ((FILE *, int, YYSTYPE));
extern tree combine_strings PARAMS ((tree));
static void
parse_decl (declarator, specs_attrs, attributes, initialized, decl)
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, &current_declspecs, &prefix_attributes);
if (current_declspecs
&& TREE_CODE (current_declspecs) != TREE_LIST)
@ -391,7 +394,8 @@ asm_keyword:
;
lang_extdef:
{ if (pending_lang_change) do_pending_lang_change(); }
{ if (pending_lang_change) do_pending_lang_change();
type_lookups = NULL_TREE; }
extdef
{ if (! toplevel_bindings_p ())
pop_everything (); }
@ -695,19 +699,19 @@ constructor_declarator:
fn.def1:
typed_declspecs declarator
{ if (!begin_function_definition ($1.t, $2))
{ if (!begin_function_definition ($1.t, $1.lookups, $2))
YYERROR1; }
| declmods notype_declarator
{ if (!begin_function_definition ($1, $2))
{ if (!begin_function_definition ($1.t, NULL_TREE, $2))
YYERROR1; }
| notype_declarator
{ if (!begin_function_definition (NULL_TREE, $1))
{ if (!begin_function_definition (NULL_TREE, NULL_TREE, $1))
YYERROR1; }
| declmods constructor_declarator
{ if (!begin_function_definition ($1, $2))
{ if (!begin_function_definition ($1.t, NULL_TREE, $2))
YYERROR1; }
| constructor_declarator
{ if (!begin_function_definition (NULL_TREE, $1))
{ if (!begin_function_definition (NULL_TREE, NULL_TREE, $1))
YYERROR1; }
;
@ -727,7 +731,7 @@ component_constructor_declarator:
fn.def2:
declmods component_constructor_declarator
{ tree specs, attrs;
split_specs_attrs ($1, &specs, &attrs);
split_specs_attrs ($1.t, &specs, &attrs);
attrs = build_tree_list (attrs, NULL_TREE);
$$ = start_method (specs, $2, attrs);
rest_of_mdef:
@ -746,7 +750,7 @@ fn.def2:
$$ = start_method (specs, $2, attrs); goto rest_of_mdef; }
| declmods notype_declarator
{ tree specs, attrs;
split_specs_attrs ($1, &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
@ -754,7 +758,7 @@ fn.def2:
goto rest_of_mdef; }
| declmods constructor_declarator
{ tree specs, attrs;
split_specs_attrs ($1, &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
@ -1667,12 +1671,14 @@ type_id:
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 = 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);
@ -1681,14 +1687,14 @@ typed_declspecs1:
{ $$.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 = 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 = 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)));
chainon ($3, chainon ($4, $1.t)));
$$.new_type_flag = $2.new_type_flag; }
;
@ -1727,22 +1733,32 @@ reserved_declspecs:
declmods:
nonempty_cv_qualifiers %prec EMPTY
{ $$ = $1.t; TREE_STATIC ($$) = 1; }
{ $$.lookups = NULL_TREE; TREE_STATIC ($$.t) = 1; }
| SCSPEC
{ $$ = hash_tree_cons (NULL_TREE, $$, NULL_TREE); }
{
$$.t = hash_tree_cons (NULL_TREE, $1, NULL_TREE);
$$.new_type_flag = 0; $$.lookups = NULL_TREE;
}
| declmods CV_QUALIFIER
{ $$ = hash_tree_cons (NULL_TREE, $2, $$);
TREE_STATIC ($$) = 1; }
{
$$.t = hash_tree_cons (NULL_TREE, $2, $1.t);
TREE_STATIC ($$.t) = 1;
}
| declmods SCSPEC
{ if (extra_warnings && TREE_STATIC ($$))
{
if (extra_warnings && TREE_STATIC ($$.t))
warning ("`%s' is not at beginning of declaration",
IDENTIFIER_POINTER ($2));
$$ = hash_tree_cons (NULL_TREE, $2, $$);
TREE_STATIC ($$) = TREE_STATIC ($1); }
$$.t = hash_tree_cons (NULL_TREE, $2, $1.t);
TREE_STATIC ($$.t) = TREE_STATIC ($1.t);
}
| declmods attributes
{ $$ = hash_tree_cons ($2, NULL_TREE, $1); }
{ $$.t = hash_tree_cons ($2, NULL_TREE, $1.t); }
| attributes %prec EMPTY
{ $$ = hash_tree_cons ($1, NULL_TREE, NULL_TREE); }
{
$$.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
@ -1763,7 +1779,7 @@ typed_typespecs:
$$.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; }
$$.new_type_flag = $2.new_type_flag; }
;
reserved_typespecquals:
@ -1779,20 +1795,21 @@ reserved_typespecquals:
typespec:
structsp
{ $$.lookups = NULL_TREE; }
| TYPESPEC %prec EMPTY
{ $$.t = $1; $$.new_type_flag = 0; }
{ $$.t = $1; $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
| complete_type_name
{ $$.t = $1; $$.new_type_flag = 0; }
{ $$.t = $1; $$.new_type_flag = 0; $$.lookups = NULL_TREE; }
| TYPEOF '(' expr ')'
{ $$.t = finish_typeof ($3);
$$.new_type_flag = 0; }
$$.new_type_flag = 0; $$.lookups = NULL_TREE; }
| TYPEOF '(' type_id ')'
{ $$.t = groktypename ($3.t);
$$.new_type_flag = 0; }
$$.new_type_flag = 0; $$.lookups = NULL_TREE; }
| SIGOF '(' expr ')'
{ tree type = TREE_TYPE ($3);
$$.new_type_flag = 0;
$$.new_type_flag = 0; $$.lookups = NULL_TREE;
if (IS_AGGR_TYPE (type))
{
sorry ("sigof type specifier");
@ -1807,7 +1824,7 @@ typespec:
| SIGOF '(' type_id ')'
{ tree type = groktypename ($3.t);
$$.new_type_flag = 0;
$$.new_type_flag = 0; $$.lookups = NULL_TREE;
if (IS_AGGR_TYPE (type))
{
sorry ("sigof type specifier");
@ -1858,15 +1875,21 @@ maybeasm:
initdcl:
declarator maybeasm maybe_attribute '='
{ $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1,
$3, prefix_attributes); }
{
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
{ $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 0,
{
deferred_type_access_control ();
$<ttype>$ = start_decl ($<ttype>1, current_declspecs, 0,
$3, prefix_attributes);
cp_finish_decl ($<ttype>$, NULL_TREE, $2, 0); }
cp_finish_decl ($<ttype>$, NULL_TREE, $2, 0);
}
;
/* This rule assumes a certain configuration of the parser stack.
@ -1877,7 +1900,8 @@ initdcl:
we need that reduce so we prefer fn.def1 when appropriate. */
initdcl0_innards:
maybe_attribute '='
{ parse_decl ($<ttype>-1, $<ttype>-2, $1, 1, &$<ttype>$); }
{ 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
@ -1885,7 +1909,8 @@ initdcl0_innards:
LOOKUP_ONLYCONVERTING); }
| maybe_attribute
{ tree d;
parse_decl ($<ttype>-1, $<ttype>-2, $1, 0, &d);
parse_decl ($<ttype>-1, $<ftype>-2.t, $<ftype>-2.lookups,
$1, 0, &d);
cp_finish_decl (d, NULL_TREE, $<ttype>0, 0); }
;
@ -1908,7 +1933,7 @@ nomods_initdcl0:
{}
| constructor_declarator maybeasm maybe_attribute
{ tree d;
parse_decl($1, NULL_TREE, $3, 0, &d);
parse_decl ($1, NULL_TREE, NULL_TREE, $3, 0, &d);
cp_finish_decl (d, NULL_TREE, $2, 0); }
;
@ -2431,7 +2456,7 @@ component_decl_1:
| declmods notype_components
{
if (!$2)
grok_x_components ($1);
grok_x_components ($1.t);
$$ = NULL_TREE;
}
| notype_declarator maybeasm maybe_attribute maybe_init
@ -2455,7 +2480,7 @@ component_decl_1:
parmlist? */
| declmods component_constructor_declarator maybeasm maybe_attribute maybe_init
{ tree specs, attrs;
split_specs_attrs ($1, &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
@ -2824,6 +2849,7 @@ functional_cast:
| typespec fcast_or_absdcl %prec EMPTY
{ $$ = reparse_absdcl_as_expr ($1.t, $2); }
;
type_name:
TYPENAME
| SELFNAME
@ -3529,7 +3555,7 @@ named_parm:
$$.t = build_tree_list (specs, NULL_TREE);
$$.new_type_flag = $1.new_type_flag; }
| declmods notype_declarator
{ tree specs = strip_attrs ($1);
{ tree specs = strip_attrs ($1.t);
$$.t = build_tree_list (specs, $2);
$$.new_type_flag = 0; }
;

View File

@ -1072,9 +1072,44 @@ friend_accessible_p (scope, type, decl, binfo)
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
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,
then we can tell in what context the access is occurring by looking
at the most derived class along the path indicated by BINFO. */
@ -1101,10 +1136,6 @@ accessible_p (type, decl)
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;
@ -1145,8 +1176,8 @@ accessible_p (type, decl)
protected_ok = friend_accessible_p (current_scope (),
type, decl, binfo);
/* 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. */
/* Standardize the binfo that access_in_type will use. We don't
need to know what path was chosen from this point onwards. */
binfo = TYPE_BINFO (type);
/* Compute the accessibility of DECL in the class hierarchy
@ -1457,7 +1488,7 @@ lookup_field_r (binfo, data)
1, we enforce accessibility. If PROTECT is zero, then, for 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
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.
WANT_TYPE is 1 when we should only return TYPE_DECLs, if no

View File

@ -1690,17 +1690,59 @@ finish_id_expr (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
legal. */
int
begin_function_definition (decl_specs, declarator)
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;