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:
parent
dd8216e19e
commit
70adf8a937
@ -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
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
101
gcc/cp/decl.c
101
gcc/cp/decl.c
@ -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 = ¤t_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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
1818
gcc/cp/parse.c
1818
gcc/cp/parse.c
File diff suppressed because it is too large
Load Diff
110
gcc/cp/parse.y
110
gcc/cp/parse.y
@ -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, ¤t_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; }
|
||||
;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user