config-lang.in: Add semantics.c to gtfiles.

* config-lang.in: Add semantics.c to gtfiles.
	* cp-tree.h (flagged_type_tree_s): Remove lookups field.
	(saved_scope): Likewise.
	(type_lookups): Remove.
	(deferred_access): New structure.
	(type_access_control): Remove.
	(save_type_access_control): Likewise.
	(reset_type_access_control): Likewise.
	(decl_type_access_control): Likewise.
	(push_deferring_access_checks): Declare.
	(resume_deferring_access_checks): Likewise.
	(stop_deferring_access_checks): Likewise.
	(pop_deferring_access_checks): Likewise.
	(get_deferred_access_checks): Likewise.
	(pop_to_parent_deferring_access_checks): Likewise.
	(perform_deferred_access_checks): Likewise.
	(perform_or_defer_access_check): Likewise.
	* decl.c (make_typename_type): Use perform_or_defer_access_check.
	(make_unbound_class_template): Likewise.
	(grokdeclarator): Don't call decl_type_access_control.
	* parser.c (cp_parser_context): Remove deferred_access_checks
	and deferring_access_checks_p fields.
	(cp_parser_context_new): Adjust.
	(cp_parser): Remove access_checks_lists.
	(cp_parser_defer_access_check): Remove.
	(cp_parser_start_deferring_access_checks): Remove.
	(cp_parser_stop_deferring_access_checks): Remove.
	(cp_parser_perform_deferred_access_checks): Remove.
	(cp_parser_nested_name_specifier_opt): Use new deferred access
	functions.
	(cp_parser_simple_declaration): Likewise.
	(cp_parser_template_id): Likewise.
	(cp_parser_function_definition): Likewise.
	(cp_parser_class_specifier): Likewise.
	(cp_parser_lookup_name): Likewise.
	(cp_parser_single_declaration): Likewise.
	(cp_parser_pre_parsed_nested_name_specifier): Likewise.
	(cp_parser_parse_tentatively): Likewise.
	(cp_parser_parse_definitely): Likewise.
	(yyparse): Likewise.
	(cp_parser_init_declarator): Remove access_checks parameter.
	Use new deferred access functions.
	(cp_parser_function_definition_from_specifiers_and_declarator):
	Likewise.
	(cp_parser_class_head): Remove deferring_access_checks_p and
	saved_access_checks parameters.  Use new deferred access functions.
	(cp_parser_member_specification_opt): Don't call
	reset_type_access_control.
	* search.c (type_access_control): Remove.
	* semantics.c: Include "gt-cp-semantics.h".
	(deferred_type_access_control): Remove.
	(deferred_access_stack): New variable.
	(deferred_access_free_list): Likewise.
	(push_deferring_access_checks): New function.
	(resume_deferring_access_checks): Likewise.
	(stop_deferring_access_checks): Likewise.
	(pop_deferring_access_checks): Likewise.
	(get_deferred_access_checks): Likewise.
	(pop_to_parent_deferring_access_checks): Likewise.
	(perform_deferred_access_checks): New function, adapted from
	cp_parser_perform_deferred_access_checks.
	(perform_or_defer_access_check): New function, adapted from
	cp_parser_defer_access_check.
	(current_type_lookups): Remove.
	(deferred_type_access_control): Likewise.
	(decl_type_access_control): Likewise.
	(save_type_access_control): Likewise.
	(reset_type_access_control): Likewise.
	(begin_function_definition): Adjust.
	(begin_class_definiton): Likewise.

From-SVN: r61283
This commit is contained in:
Kriang Lerdsuwanakij 2003-01-14 13:40:53 +00:00 committed by Kriang Lerdsuwanakij
parent a686ea5ba7
commit cf22909cee
7 changed files with 343 additions and 415 deletions

View File

@ -1,3 +1,76 @@
2003-01-14 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
* config-lang.in: Add semantics.c to gtfiles.
* cp-tree.h (flagged_type_tree_s): Remove lookups field.
(saved_scope): Likewise.
(type_lookups): Remove.
(deferred_access): New structure.
(type_access_control): Remove.
(save_type_access_control): Likewise.
(reset_type_access_control): Likewise.
(decl_type_access_control): Likewise.
(push_deferring_access_checks): Declare.
(resume_deferring_access_checks): Likewise.
(stop_deferring_access_checks): Likewise.
(pop_deferring_access_checks): Likewise.
(get_deferred_access_checks): Likewise.
(pop_to_parent_deferring_access_checks): Likewise.
(perform_deferred_access_checks): Likewise.
(perform_or_defer_access_check): Likewise.
* decl.c (make_typename_type): Use perform_or_defer_access_check.
(make_unbound_class_template): Likewise.
(grokdeclarator): Don't call decl_type_access_control.
* parser.c (cp_parser_context): Remove deferred_access_checks
and deferring_access_checks_p fields.
(cp_parser_context_new): Adjust.
(cp_parser): Remove access_checks_lists.
(cp_parser_defer_access_check): Remove.
(cp_parser_start_deferring_access_checks): Remove.
(cp_parser_stop_deferring_access_checks): Remove.
(cp_parser_perform_deferred_access_checks): Remove.
(cp_parser_nested_name_specifier_opt): Use new deferred access
functions.
(cp_parser_simple_declaration): Likewise.
(cp_parser_template_id): Likewise.
(cp_parser_function_definition): Likewise.
(cp_parser_class_specifier): Likewise.
(cp_parser_lookup_name): Likewise.
(cp_parser_single_declaration): Likewise.
(cp_parser_pre_parsed_nested_name_specifier): Likewise.
(cp_parser_parse_tentatively): Likewise.
(cp_parser_parse_definitely): Likewise.
(yyparse): Likewise.
(cp_parser_init_declarator): Remove access_checks parameter.
Use new deferred access functions.
(cp_parser_function_definition_from_specifiers_and_declarator):
Likewise.
(cp_parser_class_head): Remove deferring_access_checks_p and
saved_access_checks parameters. Use new deferred access functions.
(cp_parser_member_specification_opt): Don't call
reset_type_access_control.
* search.c (type_access_control): Remove.
* semantics.c: Include "gt-cp-semantics.h".
(deferred_type_access_control): Remove.
(deferred_access_stack): New variable.
(deferred_access_free_list): Likewise.
(push_deferring_access_checks): New function.
(resume_deferring_access_checks): Likewise.
(stop_deferring_access_checks): Likewise.
(pop_deferring_access_checks): Likewise.
(get_deferred_access_checks): Likewise.
(pop_to_parent_deferring_access_checks): Likewise.
(perform_deferred_access_checks): New function, adapted from
cp_parser_perform_deferred_access_checks.
(perform_or_defer_access_check): New function, adapted from
cp_parser_defer_access_check.
(current_type_lookups): Remove.
(deferred_type_access_control): Likewise.
(decl_type_access_control): Likewise.
(save_type_access_control): Likewise.
(reset_type_access_control): Likewise.
(begin_function_definition): Adjust.
(begin_class_definiton): Likewise.
2003-01-13 Jason Merrill <jason@redhat.com>
PR c++/8748

View File

@ -34,4 +34,4 @@ stagestuff="g++\$(exeext) g++-cross\$(exeext) cc1plus\$(exeext)"
target_libs="${libstdcxx_version} target-gperf"
gtfiles="\$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/lex.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.c"
gtfiles="\$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/lex.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.c"

View File

@ -257,7 +257,6 @@ typedef struct flagged_type_tree_s GTY(())
{
tree t;
int new_type_flag;
tree lookups;
} flagged_type_tree;
typedef struct template_parm_index_s GTY(())
@ -784,7 +783,6 @@ struct saved_scope GTY(())
tree x_previous_class_type;
tree x_previous_class_values;
tree x_saved_tree;
tree lookups;
tree last_parms;
HOST_WIDE_INT x_processing_template_decl;
@ -851,8 +849,6 @@ struct saved_scope GTY(())
/* A list of private types mentioned, for deferred access checking. */
#define type_lookups scope_chain->lookups
extern GTY(()) struct saved_scope *scope_chain;
/* Global state pertinent to the current function. */
@ -3197,6 +3193,32 @@ extern GTY(()) tree anonymous_namespace_name;
function, two inside the body of a function in a local class, etc.) */
extern int function_depth;
typedef struct deferred_access GTY(())
{
/* A TREE_LIST representing name-lookups for which we have deferred
checking access controls. We cannot check the accessibility of
names used in a decl-specifier-seq until we know what is being
declared because code like:
class A {
class B {};
B* f();
}
A::B* A::f() { return 0; }
is valid, even though `A::B' is not generally accessible.
The TREE_PURPOSE of each node is the scope used to qualify the
name being looked up; the TREE_VALUE is the DECL to which the
name was resolved. */
tree deferred_access_checks;
/* TRUE iff we are deferring access checks. */
bool deferring_access_checks_p;
/* The next deferred access data in stack or linked-list. */
struct deferred_access *next;
} deferred_access;
/* in pt.c */
/* These values are used for the `STRICT' parameter to type_unification and
@ -4097,7 +4119,6 @@ extern tree lookup_base (tree, tree, base_access, base_kind *);
extern int types_overlap_p (tree, tree);
extern tree get_vbase (tree, tree);
extern tree get_dynamic_cast_base_type (tree, tree);
extern void type_access_control (tree, tree);
extern int accessible_p (tree, tree);
extern tree lookup_field (tree, tree, int, int);
extern int lookup_fnfields_1 (tree, tree);
@ -4147,6 +4168,14 @@ extern tree build_baselink (tree, tree, tree, tree);
extern tree adjust_result_of_qualified_name_lookup
(tree, tree, tree);
/* in semantics.c */
extern void push_deferring_access_checks (bool defer_p);
extern void resume_deferring_access_checks (void);
extern void stop_deferring_access_checks (void);
extern void pop_deferring_access_checks (void);
extern tree get_deferred_access_checks (void);
extern void pop_to_parent_deferring_access_checks (void);
extern void perform_deferred_access_checks (void);
extern void perform_or_defer_access_check (tree, tree);
extern void init_cp_semantics (void);
extern tree finish_expr_stmt (tree);
extern tree begin_if_stmt (void);
@ -4207,9 +4236,6 @@ extern tree finish_pseudo_destructor_expr (tree, tree, tree);
extern tree finish_unary_op_expr (enum tree_code, tree);
extern tree finish_compound_literal (tree, tree);
extern tree finish_fname (tree);
extern void save_type_access_control (tree);
extern void reset_type_access_control (void);
extern void decl_type_access_control (tree);
extern int begin_function_definition (tree, tree, tree);
extern tree begin_constructor_declarator (tree, tree);
extern tree finish_declarator (tree, tree, tree, tree, int);

View File

@ -5544,7 +5544,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
if (complain & tf_error)
{
if (complain & tf_parsing)
type_access_control (context, tmpl);
perform_or_defer_access_check (context, tmpl);
else
enforce_access (context, tmpl);
}
@ -5579,7 +5579,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
if (complain & tf_error)
{
if (complain & tf_parsing)
type_access_control (context, t);
perform_or_defer_access_check (context, t);
else
enforce_access (context, t);
}
@ -5651,7 +5651,7 @@ make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
if (complain & tf_error)
{
if (complain & tf_parsing)
type_access_control (context, tmpl);
perform_or_defer_access_check (context, tmpl);
else
enforce_access (context, tmpl);
}
@ -9854,7 +9854,6 @@ grokdeclarator (tree declarator,
decl = start_decl (declarator, declspecs, 1,
attributes, NULL_TREE);
decl_type_access_control (decl);
if (decl)
{
/* Look for __unused__ attribute */
@ -11407,8 +11406,6 @@ grokdeclarator (tree declarator,
/* Only try to do this stuff if we didn't already give up. */
if (type != integer_type_node)
{
decl_type_access_control (TYPE_NAME (type));
/* A friendly class? */
if (current_class_type)
make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type));

View File

@ -1194,26 +1194,6 @@ typedef struct cp_parser_context GTY (())
scope given by OBJECT_TYPE (the type of `x' or `*x') and also in
the context of the containing expression. */
tree object_type;
/* A TREE_LIST representing name-lookups for which we have deferred
checking access controls. We cannot check the accessibility of
names used in a decl-specifier-seq until we know what is being
declared because code like:
class A {
class B {};
B* f();
}
A::B* A::f() { return 0; }
is valid, even though `A::B' is not generally accessible.
The TREE_PURPOSE of each node is the scope used to qualify the
name being looked up; the TREE_VALUE is the DECL to which the
name was resolved. */
tree deferred_access_checks;
/* TRUE iff we are deferring access checks. */
bool deferring_access_checks_p;
/* The next parsing context in the stack. */
struct cp_parser_context *next;
} cp_parser_context;
@ -1260,10 +1240,6 @@ cp_parser_context_new (next)
/* If, in the NEXT context, we are parsing an `x->' or `x.'
expression, then we are parsing one in this context, too. */
context->object_type = next->object_type;
/* We are deferring access checks here if we were in the NEXT
context. */
context->deferring_access_checks_p
= next->deferring_access_checks_p;
/* Thread the stack. */
context->next = next;
}
@ -1367,10 +1343,6 @@ typedef struct cp_parser GTY(())
/* The number of template parameter lists that apply directly to the
current declaration. */
unsigned num_template_parameter_lists;
/* List of access checks lists, used to prevent GC collection while
they are in use. */
tree access_checks_lists;
} cp_parser;
/* The type of a function that parses some kind of expression */
@ -1562,7 +1534,7 @@ static void cp_parser_linkage_specification
/* Declarators [gram.dcl.decl] */
static tree cp_parser_init_declarator
PARAMS ((cp_parser *, tree, tree, tree, bool, bool, bool *));
PARAMS ((cp_parser *, tree, tree, bool, bool, bool *));
static tree cp_parser_declarator
PARAMS ((cp_parser *, cp_parser_declarator_kind, bool *));
static tree cp_parser_direct_declarator
@ -1606,7 +1578,7 @@ static tree cp_parser_class_name
static tree cp_parser_class_specifier
PARAMS ((cp_parser *));
static tree cp_parser_class_head
PARAMS ((cp_parser *, bool *, bool *, tree *));
PARAMS ((cp_parser *, bool *));
static enum tag_types cp_parser_class_key
PARAMS ((cp_parser *));
static void cp_parser_member_specification_opt
@ -1731,7 +1703,7 @@ static tree cp_parser_global_scope_opt
static bool cp_parser_constructor_declarator_p
(cp_parser *, bool);
static tree cp_parser_function_definition_from_specifiers_and_declarator
PARAMS ((cp_parser *, tree, tree, tree, tree));
PARAMS ((cp_parser *, tree, tree, tree));
static tree cp_parser_function_definition_after_declarator
PARAMS ((cp_parser *, bool));
static void cp_parser_template_declaration_after_export
@ -1818,14 +1790,6 @@ static bool cp_parser_dependent_template_id_p
(tree, tree);
static bool cp_parser_dependent_template_p
(tree);
static void cp_parser_defer_access_check
(cp_parser *, tree, tree);
static void cp_parser_start_deferring_access_checks
(cp_parser *);
static tree cp_parser_stop_deferring_access_checks
PARAMS ((cp_parser *));
static void cp_parser_perform_deferred_access_checks
PARAMS ((tree));
static tree cp_parser_scope_through_which_access_occurs
(tree, tree, tree);
@ -2134,79 +2098,6 @@ cp_parser_dependent_template_p (tree tmpl)
return false;
}
/* Defer checking the accessibility of DECL, when looked up in
CLASS_TYPE. */
static void
cp_parser_defer_access_check (cp_parser *parser,
tree class_type,
tree decl)
{
tree check;
/* If we are not supposed to defer access checks, just check now. */
if (!parser->context->deferring_access_checks_p)
{
enforce_access (class_type, decl);
return;
}
/* See if we are already going to perform this check. */
for (check = parser->context->deferred_access_checks;
check;
check = TREE_CHAIN (check))
if (TREE_VALUE (check) == decl
&& same_type_p (TREE_PURPOSE (check), class_type))
return;
/* If not, record the check. */
parser->context->deferred_access_checks
= tree_cons (class_type, decl, parser->context->deferred_access_checks);
}
/* Start deferring access control checks. */
static void
cp_parser_start_deferring_access_checks (cp_parser *parser)
{
parser->context->deferring_access_checks_p = true;
}
/* Stop deferring access control checks. Returns a TREE_LIST
representing the deferred checks. The TREE_PURPOSE of each node is
the type through which the access occurred; the TREE_VALUE is the
declaration named. */
static tree
cp_parser_stop_deferring_access_checks (parser)
cp_parser *parser;
{
tree access_checks;
parser->context->deferring_access_checks_p = false;
access_checks = parser->context->deferred_access_checks;
parser->context->deferred_access_checks = NULL_TREE;
return access_checks;
}
/* Perform the deferred ACCESS_CHECKS, whose representation is as
documented with cp_parser_stop_deferrring_access_checks. */
static void
cp_parser_perform_deferred_access_checks (access_checks)
tree access_checks;
{
tree deferred_check;
/* Look through all the deferred checks. */
for (deferred_check = access_checks;
deferred_check;
deferred_check = TREE_CHAIN (deferred_check))
/* Check access. */
enforce_access (TREE_PURPOSE (deferred_check),
TREE_VALUE (deferred_check));
}
/* Returns the scope through which DECL is being accessed, or
NULL_TREE if DECL is not a member. If OBJECT_TYPE is non-NULL, we
have just seen `x->' or `x.' and OBJECT_TYPE is the type of `*x',
@ -3487,11 +3378,12 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
start = cp_lexer_token_difference (parser->lexer,
parser->lexer->first_token,
token);
access_check = parser->context->deferred_access_checks;
}
else
start = -1;
push_deferring_access_checks (true);
while (true)
{
tree new_scope;
@ -3633,6 +3525,10 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
complete_type (parser->scope);
}
/* Retrieve any deferred checks. Do not pop this access checks yet
so the memory will not be reclaimed during token replacing below. */
access_check = get_deferred_access_checks ();
/* If parsing tentatively, replace the sequence of tokens that makes
up the nested-name-specifier with a CPP_NESTED_NAME_SPECIFIER
token. That way, should we re-parse the token stream, we will
@ -3640,28 +3536,12 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
we issue duplicate error messages. */
if (success && start >= 0)
{
tree c;
/* Find the token that corresponds to the start of the
template-id. */
token = cp_lexer_advance_token (parser->lexer,
parser->lexer->first_token,
start);
/* Remember the access checks associated with this
nested-name-specifier. */
c = parser->context->deferred_access_checks;
if (c == access_check)
access_check = NULL_TREE;
else
{
while (TREE_CHAIN (c) != access_check)
c = TREE_CHAIN (c);
access_check = parser->context->deferred_access_checks;
parser->context->deferred_access_checks = TREE_CHAIN (c);
TREE_CHAIN (c) = NULL_TREE;
}
/* Reset the contents of the START token. */
token->type = CPP_NESTED_NAME_SPECIFIER;
token->value = build_tree_list (access_check, parser->scope);
@ -3671,6 +3551,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
cp_lexer_purge_tokens_after (parser->lexer, token);
}
pop_deferring_access_checks ();
return success ? parser->scope : NULL_TREE;
}
@ -6748,14 +6629,14 @@ cp_parser_simple_declaration (parser, function_definition_allowed_p)
{
tree decl_specifiers;
tree attributes;
tree access_checks;
bool declares_class_or_enum;
bool saw_declarator;
/* Defer access checks until we know what is being declared; the
checks for names appearing in the decl-specifier-seq should be
done as if we were in the scope of the thing being declared. */
cp_parser_start_deferring_access_checks (parser);
push_deferring_access_checks (true);
/* Parse the decl-specifier-seq. We have to keep track of whether
or not the decl-specifier-seq declares a named class or
enumeration type, since that is the only case in which the
@ -6773,11 +6654,7 @@ cp_parser_simple_declaration (parser, function_definition_allowed_p)
&attributes,
&declares_class_or_enum);
/* We no longer need to defer access checks. */
access_checks = cp_parser_stop_deferring_access_checks (parser);
/* Prevent access checks from being reclaimed by GC. */
parser->access_checks_lists = tree_cons (NULL_TREE, access_checks,
parser->access_checks_lists);
stop_deferring_access_checks ();
/* Keep going until we hit the `;' at the end of the simple
declaration. */
@ -6791,7 +6668,6 @@ cp_parser_simple_declaration (parser, function_definition_allowed_p)
saw_declarator = true;
/* Parse the init-declarator. */
cp_parser_init_declarator (parser, decl_specifiers, attributes,
access_checks,
function_definition_allowed_p,
/*member_p=*/false,
&function_definition_p);
@ -6809,9 +6685,7 @@ cp_parser_simple_declaration (parser, function_definition_allowed_p)
/* Otherwise, we're done with the list of declarators. */
else
{
/* Discard access checks no longer in use. */
parser->access_checks_lists
= TREE_CHAIN (parser->access_checks_lists);
pop_deferring_access_checks ();
return;
}
}
@ -6829,9 +6703,7 @@ cp_parser_simple_declaration (parser, function_definition_allowed_p)
cp_parser_error (parser, "expected `,' or `;'");
/* Skip tokens until we reach the end of the statement. */
cp_parser_skip_to_end_of_statement (parser);
/* Discard access checks no longer in use. */
parser->access_checks_lists
= TREE_CHAIN (parser->access_checks_lists);
pop_deferring_access_checks ();
return;
}
/* After the first time around, a function-definition is not
@ -6851,18 +6723,17 @@ cp_parser_simple_declaration (parser, function_definition_allowed_p)
if (cp_parser_declares_only_class_p (parser))
shadow_tag (decl_specifiers);
/* Perform any deferred access checks. */
cp_parser_perform_deferred_access_checks (access_checks);
perform_deferred_access_checks ();
}
pop_deferring_access_checks ();
/* Consume the `;'. */
cp_parser_require (parser, CPP_SEMICOLON, "`;'");
/* Mark all the classes that appeared in the decl-specifier-seq as
having received a `;'. */
note_list_got_semicolon (decl_specifiers);
/* Discard access checks no longer in use. */
parser->access_checks_lists = TREE_CHAIN (parser->access_checks_lists);
}
/* Parse a decl-specifier-seq.
@ -8127,9 +7998,8 @@ cp_parser_template_id (cp_parser *parser,
value = cp_lexer_consume_token (parser->lexer)->value;
/* Perform any access checks that were deferred. */
for (check = TREE_PURPOSE (value); check; check = TREE_CHAIN (check))
cp_parser_defer_access_check (parser,
TREE_PURPOSE (check),
TREE_VALUE (check));
perform_or_defer_access_check (TREE_PURPOSE (check),
TREE_VALUE (check));
/* Return the stored value. */
return TREE_VALUE (value);
}
@ -8152,20 +8022,27 @@ cp_parser_template_id (cp_parser *parser,
start_of_id = cp_lexer_token_difference (parser->lexer,
parser->lexer->first_token,
next_token);
access_check = parser->context->deferred_access_checks;
}
else
start_of_id = -1;
push_deferring_access_checks (true);
/* Parse the template-name. */
template = cp_parser_template_name (parser, template_keyword_p,
check_dependency_p);
if (template == error_mark_node)
return error_mark_node;
{
pop_deferring_access_checks ();
return error_mark_node;
}
/* Look for the `<' that starts the template-argument-list. */
if (!cp_parser_require (parser, CPP_LESS, "`<'"))
return error_mark_node;
{
pop_deferring_access_checks ();
return error_mark_node;
}
/* [temp.names]
@ -8216,6 +8093,10 @@ cp_parser_template_id (cp_parser *parser,
template_id = lookup_template_function (template, arguments);
}
/* Retrieve any deferred checks. Do not pop this access checks yet
so the memory will not be reclaimed during token replacing below. */
access_check = get_deferred_access_checks ();
/* If parsing tentatively, replace the sequence of tokens that makes
up the template-id with a CPP_TEMPLATE_ID token. That way,
should we re-parse the token stream, we will not have to repeat
@ -8225,7 +8106,6 @@ cp_parser_template_id (cp_parser *parser,
if (start_of_id >= 0)
{
cp_token *token;
tree c;
/* Find the token that corresponds to the start of the
template-id. */
@ -8233,20 +8113,6 @@ cp_parser_template_id (cp_parser *parser,
parser->lexer->first_token,
start_of_id);
/* Remember the access checks associated with this
nested-name-specifier. */
c = parser->context->deferred_access_checks;
if (c == access_check)
access_check = NULL_TREE;
else
{
while (TREE_CHAIN (c) != access_check)
c = TREE_CHAIN (c);
access_check = parser->context->deferred_access_checks;
parser->context->deferred_access_checks = TREE_CHAIN (c);
TREE_CHAIN (c) = NULL_TREE;
}
/* Reset the contents of the START_OF_ID token. */
token->type = CPP_TEMPLATE_ID;
token->value = build_tree_list (access_check, template_id);
@ -8255,6 +8121,7 @@ cp_parser_template_id (cp_parser *parser,
cp_lexer_purge_tokens_after (parser->lexer, token);
}
pop_deferring_access_checks ();
return template_id;
}
@ -9724,10 +9591,9 @@ cp_parser_asm_definition (parser)
declarator asm-specification [opt] attributes [opt] initializer [opt]
The DECL_SPECIFIERS and PREFIX_ATTRIBUTES apply to this declarator.
Returns a reprsentation of the entity declared. The ACCESS_CHECKS
represent deferred access checks from the decl-specifier-seq. If
MEMBER_P is TRUE, then this declarator appears in a class scope.
The new DECL created by this declarator is returned.
Returns a reprsentation of the entity declared. If MEMBER_P is TRUE,
then this declarator appears in a class scope. The new DECL created
by this declarator is returned.
If FUNCTION_DEFINITION_ALLOWED_P then we handle the declarator and
for a function-definition here as well. If the declarator is a
@ -9742,14 +9608,12 @@ static tree
cp_parser_init_declarator (parser,
decl_specifiers,
prefix_attributes,
access_checks,
function_definition_allowed_p,
member_p,
function_definition_p)
cp_parser *parser;
tree decl_specifiers;
tree prefix_attributes;
tree access_checks;
bool function_definition_allowed_p;
bool member_p;
bool *function_definition_p;
@ -9761,7 +9625,6 @@ cp_parser_init_declarator (parser,
tree initializer;
tree decl = NULL_TREE;
tree scope;
tree declarator_access_checks;
bool is_initialized;
bool is_parenthesized_init;
bool ctor_dtor_or_conv_p;
@ -9775,29 +9638,19 @@ cp_parser_init_declarator (parser,
/* Defer access checks while parsing the declarator; we cannot know
what names are accessible until we know what is being
declared. */
cp_parser_start_deferring_access_checks (parser);
resume_deferring_access_checks ();
/* Parse the declarator. */
declarator
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
&ctor_dtor_or_conv_p);
/* Gather up the deferred checks. */
declarator_access_checks
= cp_parser_stop_deferring_access_checks (parser);
/* Prevent the access checks from being reclaimed by GC. */
parser->access_checks_lists
= tree_cons (NULL_TREE, declarator_access_checks,
parser->access_checks_lists);
stop_deferring_access_checks ();
/* If the DECLARATOR was erroneous, there's no need to go
further. */
if (declarator == error_mark_node)
{
/* Discard access checks no longer in use. */
parser->access_checks_lists
= TREE_CHAIN (parser->access_checks_lists);
return error_mark_node;
}
return error_mark_node;
/* Figure out what scope the entity declared by the DECLARATOR is
located in. `grokdeclarator' sometimes changes the scope, so
@ -9831,15 +9684,10 @@ cp_parser_init_declarator (parser,
error message. */
cp_parser_error (parser,
"a function-definition is not allowed here");
/* Discard access checks no longer in use. */
parser->access_checks_lists
= TREE_CHAIN (parser->access_checks_lists);
return error_mark_node;
}
else
{
tree *ac;
/* Neither attributes nor an asm-specification are allowed
on a function-definition. */
if (asm_specification)
@ -9849,23 +9697,9 @@ cp_parser_init_declarator (parser,
/* This is a function-definition. */
*function_definition_p = true;
/* Thread the access checks together. */
ac = &access_checks;
while (*ac)
ac = &TREE_CHAIN (*ac);
*ac = declarator_access_checks;
/* Parse the function definition. */
decl = (cp_parser_function_definition_from_specifiers_and_declarator
(parser, decl_specifiers, prefix_attributes, declarator,
access_checks));
/* Pull the access-checks apart again. */
*ac = NULL_TREE;
/* Discard access checks no longer in use. */
parser->access_checks_lists
= TREE_CHAIN (parser->access_checks_lists);
(parser, decl_specifiers, prefix_attributes, declarator));
return decl;
}
@ -9883,9 +9717,6 @@ cp_parser_init_declarator (parser,
{
cp_parser_error (parser,
"expected constructor, destructor, or type conversion");
/* Discard access checks no longer in use. */
parser->access_checks_lists
= TREE_CHAIN (parser->access_checks_lists);
return error_mark_node;
}
@ -9899,9 +9730,6 @@ cp_parser_init_declarator (parser,
&& token->type != CPP_SEMICOLON)
{
cp_parser_error (parser, "expected init-declarator");
/* Discard access checks no longer in use. */
parser->access_checks_lists
= TREE_CHAIN (parser->access_checks_lists);
return error_mark_node;
}
@ -9916,12 +9744,7 @@ cp_parser_init_declarator (parser,
/* Check that the number of template-parameter-lists is OK. */
if (!cp_parser_check_declarator_template_parameters (parser,
declarator))
{
/* Discard access checks no longer in use. */
parser->access_checks_lists
= TREE_CHAIN (parser->access_checks_lists);
return error_mark_node;
}
return error_mark_node;
/* Enter the newly declared entry in the symbol table. If we're
processing a declaration in a class-specifier, we wait until
@ -9962,10 +9785,9 @@ cp_parser_init_declarator (parser,
current_function_decl = decl;
}
/* Perform the access control checks for the decl-specifiers. */
cp_parser_perform_deferred_access_checks (access_checks);
/* And for the declarator. */
cp_parser_perform_deferred_access_checks (declarator_access_checks);
/* Perform the access control checks for the declarator and the
the decl-specifiers. */
perform_deferred_access_checks ();
/* Restore the saved value. */
if (TREE_CODE (decl) == FUNCTION_DECL)
@ -10017,10 +9839,6 @@ cp_parser_init_declarator (parser,
((is_parenthesized_init || !is_initialized)
? 0 : LOOKUP_ONLYCONVERTING));
/* Discard access checks no longer in use. */
parser->access_checks_lists
= TREE_CHAIN (parser->access_checks_lists);
return decl;
}
@ -11167,7 +10985,6 @@ cp_parser_function_definition (parser, friend_p)
tree attributes;
tree declarator;
tree fn;
tree access_checks;
cp_token *token;
bool declares_class_or_enum;
bool member_p;
@ -11198,8 +11015,8 @@ cp_parser_function_definition (parser, friend_p)
function is being defined. There is no need to do this for the
definition of member functions; we cannot be defining a member
from another class. */
if (!member_p)
cp_parser_start_deferring_access_checks (parser);
push_deferring_access_checks (!member_p);
/* Parse the decl-specifier-seq. */
decl_specifiers
= cp_parser_decl_specifier_seq (parser,
@ -11215,10 +11032,7 @@ cp_parser_function_definition (parser, friend_p)
/*ctor_dtor_or_conv_p=*/NULL);
/* Gather up any access checks that occurred. */
if (!member_p)
access_checks = cp_parser_stop_deferring_access_checks (parser);
else
access_checks = NULL_TREE;
stop_deferring_access_checks ();
/* If something has already gone wrong, we may as well stop now. */
if (declarator == error_mark_node)
@ -11227,6 +11041,7 @@ cp_parser_function_definition (parser, friend_p)
like a function-definition, to a `;' in the hopes of finding
a sensible place from which to continue parsing. */
cp_parser_skip_to_end_of_block_or_statement (parser);
pop_deferring_access_checks ();
return error_mark_node;
}
@ -11241,6 +11056,7 @@ cp_parser_function_definition (parser, friend_p)
/* Skip to the next `;'. */
cp_parser_skip_to_end_of_block_or_statement (parser);
pop_deferring_access_checks ();
return error_mark_node;
}
@ -11269,6 +11085,7 @@ cp_parser_function_definition (parser, friend_p)
if (cp_parser_token_starts_function_definition_p
(cp_lexer_peek_token (parser->lexer)))
cp_parser_skip_to_end_of_block_or_statement (parser);
pop_deferring_access_checks ();
return error_mark_node;
}
@ -11294,6 +11111,7 @@ cp_parser_function_definition (parser, friend_p)
= tree_cons (NULL_TREE, fn,
TREE_VALUE (parser->unparsed_functions_queues));
pop_deferring_access_checks ();
return fn;
}
@ -11302,11 +11120,14 @@ cp_parser_function_definition (parser, friend_p)
declarator))
{
cp_parser_skip_to_end_of_block_or_statement (parser);
pop_deferring_access_checks ();
return error_mark_node;
}
return (cp_parser_function_definition_from_specifiers_and_declarator
(parser, decl_specifiers, attributes, declarator, access_checks));
fn = cp_parser_function_definition_from_specifiers_and_declarator
(parser, decl_specifiers, attributes, declarator);
pop_deferring_access_checks ();
return fn;
}
/* Parse a function-body.
@ -11670,25 +11491,29 @@ cp_parser_class_specifier (parser)
tree attributes = NULL_TREE;
int has_trailing_semicolon;
bool nested_name_specifier_p;
bool deferring_access_checks_p;
tree saved_access_checks;
unsigned saved_num_template_parameter_lists;
push_deferring_access_checks (false);
/* Parse the class-head. */
type = cp_parser_class_head (parser,
&nested_name_specifier_p,
&deferring_access_checks_p,
&saved_access_checks);
&nested_name_specifier_p);
/* If the class-head was a semantic disaster, skip the entire body
of the class. */
if (!type)
{
cp_parser_skip_to_end_of_block_or_statement (parser);
pop_deferring_access_checks ();
return error_mark_node;
}
/* Look for the `{'. */
if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
return error_mark_node;
{
pop_deferring_access_checks ();
return error_mark_node;
}
/* Issue an error message if type-definitions are forbidden here. */
cp_parser_check_type_definition (parser);
/* Remember that we are defining one more class. */
@ -11797,11 +11622,7 @@ cp_parser_class_specifier (parser)
}
/* Put back any saved access checks. */
if (deferring_access_checks_p)
{
cp_parser_start_deferring_access_checks (parser);
parser->context->deferred_access_checks = saved_access_checks;
}
pop_deferring_access_checks ();
/* Restore the count of active template-parameter-lists. */
parser->num_template_parameter_lists
@ -11827,10 +11648,6 @@ cp_parser_class_specifier (parser)
Returns the TYPE of the indicated class. Sets
*NESTED_NAME_SPECIFIER_P to TRUE iff one of the productions
involving a nested-name-specifier was used, and FALSE otherwise.
Sets *DEFERRING_ACCESS_CHECKS_P to TRUE iff we were deferring
access checks before this class-head. In that case,
*SAVED_ACCESS_CHECKS is set to the current list of deferred access
checks.
Returns NULL_TREE if the class-head is syntactically valid, but
semantically invalid in a way that means we should skip the entire
@ -11838,13 +11655,9 @@ cp_parser_class_specifier (parser)
static tree
cp_parser_class_head (parser,
nested_name_specifier_p,
deferring_access_checks_p,
saved_access_checks)
nested_name_specifier_p)
cp_parser *parser;
bool *nested_name_specifier_p;
bool *deferring_access_checks_p;
tree *saved_access_checks;
{
cp_token *token;
tree nested_name_specifier;
@ -12004,14 +11817,6 @@ cp_parser_class_head (parser,
process the class-definition. */
return NULL_TREE;
/* We do not need to defer access checks for entities declared
within the class. But, we do need to save any access checks that
are currently deferred and restore them later, in case we are in
the middle of something else. */
*deferring_access_checks_p = parser->context->deferring_access_checks_p;
if (*deferring_access_checks_p)
*saved_access_checks = cp_parser_stop_deferring_access_checks (parser);
/* Look up the type. */
if (template_id_p)
{
@ -12165,7 +11970,6 @@ cp_parser_member_specification_opt (parser)
/* Otherwise, the next construction must be a
member-declaration. */
cp_parser_member_declaration (parser);
reset_type_access_control ();
}
}
}
@ -13659,15 +13463,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name, bool check_access,
object_type,
parser->scope);
if (qualifying_type)
{
/* If we are supposed to defer access checks, just record
the information for later. */
if (parser->context->deferring_access_checks_p)
cp_parser_defer_access_check (parser, qualifying_type, decl);
/* Otherwise, check accessibility now. */
else
enforce_access (qualifying_type, decl);
}
perform_or_defer_access_check (qualifying_type, decl);
}
return decl;
@ -14129,19 +13925,18 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
}
/* Parse the definition of the function given by the DECL_SPECIFIERS,
ATTRIBUTES, and DECLARATOR. The ACCESS_CHECKS have been deferred;
ATTRIBUTES, and DECLARATOR. The access checks have been deferred;
they must be performed once we are in the scope of the function.
Returns the function defined. */
static tree
cp_parser_function_definition_from_specifiers_and_declarator
(parser, decl_specifiers, attributes, declarator, access_checks)
(parser, decl_specifiers, attributes, declarator)
cp_parser *parser;
tree decl_specifiers;
tree attributes;
tree declarator;
tree access_checks;
{
tree fn;
bool success_p;
@ -14155,7 +13950,7 @@ cp_parser_function_definition_from_specifiers_and_declarator
did not check, check them now. We must wait until we are in the
scope of the function to perform the checks, since the function
might be a friend. */
cp_parser_perform_deferred_access_checks (access_checks);
perform_deferred_access_checks ();
if (!success_p)
{
@ -14335,13 +14130,13 @@ cp_parser_single_declaration (parser,
tree decl = NULL_TREE;
tree decl_specifiers;
tree attributes;
tree access_checks;
/* Parse the dependent declaration. We don't know yet
whether it will be a function-definition. */
cp_parser_parse_tentatively (parser);
/* Defer access checks until we know what is being declared. */
cp_parser_start_deferring_access_checks (parser);
push_deferring_access_checks (true);
/* Try the `decl-specifier-seq [opt] init-declarator [opt]'
alternative. */
decl_specifiers
@ -14351,7 +14146,8 @@ cp_parser_single_declaration (parser,
&declares_class_or_enum);
/* Gather up the access checks that occurred the
decl-specifier-seq. */
access_checks = cp_parser_stop_deferring_access_checks (parser);
stop_deferring_access_checks ();
/* Check for the declaration of a template class. */
if (declares_class_or_enum)
{
@ -14377,10 +14173,12 @@ cp_parser_single_declaration (parser,
decl = cp_parser_init_declarator (parser,
decl_specifiers,
attributes,
access_checks,
/*function_definition_allowed_p=*/false,
member_p,
/*function_definition_p=*/NULL);
pop_deferring_access_checks ();
/* Clear any current qualification; whatever comes next is the start
of something new. */
parser->scope = NULL_TREE;
@ -14881,9 +14679,7 @@ cp_parser_pre_parsed_nested_name_specifier (cp_parser *parser)
value = cp_lexer_consume_token (parser->lexer)->value;
/* Perform any access checks that were deferred. */
for (check = TREE_PURPOSE (value); check; check = TREE_CHAIN (check))
cp_parser_defer_access_check (parser,
TREE_PURPOSE (check),
TREE_VALUE (check));
perform_or_defer_access_check (TREE_PURPOSE (check), TREE_VALUE (check));
/* Set the scope from the stored value. */
parser->scope = TREE_VALUE (value);
parser->qualifying_scope = TREE_TYPE (value);
@ -14942,7 +14738,7 @@ cp_parser_parse_tentatively (parser)
/* In order to avoid repetitive access control error messages,
access checks are queued up until we are no longer parsing
tentatively. */
cp_parser_start_deferring_access_checks (parser);
push_deferring_access_checks (true);
}
/* Commit to the currently active tentative parse. */
@ -15004,22 +14800,16 @@ cp_parser_parse_definitely (parser)
already done. */
if (context->status != CP_PARSER_STATUS_KIND_COMMITTED)
cp_lexer_commit_tokens (parser->lexer);
if (!parser->context->deferring_access_checks_p)
/* If in the parent context we are not deferring checks, then
these perform these checks now. */
(cp_parser_perform_deferred_access_checks
(context->deferred_access_checks));
else
/* Any lookups that were deferred during the tentative parse are
still deferred. */
parser->context->deferred_access_checks
= chainon (parser->context->deferred_access_checks,
context->deferred_access_checks);
pop_to_parent_deferring_access_checks ();
}
/* Otherwise, if errors occurred, roll back our state so that things
are just as they were before we began the tentative parse. */
else
cp_lexer_rollback_tokens (parser->lexer);
{
cp_lexer_rollback_tokens (parser->lexer);
pop_deferring_access_checks ();
}
/* Add the context to the front of the free list. */
context->next = cp_parser_context_free_list;
cp_parser_context_free_list = context;
@ -15074,6 +14864,7 @@ yyparse ()
bool error_occurred;
the_parser = cp_parser_new ();
push_deferring_access_checks (false);
error_occurred = cp_parser_translation_unit (the_parser);
the_parser = NULL;

View File

@ -979,41 +979,6 @@ friend_accessible_p (scope, decl, binfo)
return 0;
}
/* Perform access control on TYPE_DECL or TEMPLATE_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 save_type_access_control,
which stores the lookups from the decl-specifier-seq in
current_type_lookups.
As we finish with each declarator, we process everything in type_lookups
via decl_type_access_control, which resets type_lookups to the value of
current_type_lookups for subsequent declarators.
When we enter a function, we set type_lookups to 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) != TEMPLATE_DECL && 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 nonzero if, in the current
context, DECL is accessible. If TYPE is actually a BINFO node,

View File

@ -52,7 +52,6 @@
static tree maybe_convert_cond PARAMS ((tree));
static tree simplify_aggr_init_exprs_r PARAMS ((tree *, int *, void *));
static void deferred_type_access_control PARAMS ((void));
static void emit_associated_thunks PARAMS ((tree));
static void genrtl_try_block PARAMS ((tree));
static void genrtl_eh_spec_block PARAMS ((tree));
@ -79,6 +78,145 @@ static tree clear_decl_rtl PARAMS ((tree *, int *, void *));
(SUBSTMT) = (COND); \
} while (0)
/* Data for deferred access checking. */
static GTY(()) deferred_access *deferred_access_stack;
static GTY(()) deferred_access *deferred_access_free_list;
/* Save the current deferred access states and start deferred
access checking iff DEFER_P is true. */
void push_deferring_access_checks (bool deferring_p)
{
deferred_access *d;
/* Recycle previously used free store if available. */
if (deferred_access_free_list)
{
d = deferred_access_free_list;
deferred_access_free_list = d->next;
}
else
d = (deferred_access *) ggc_alloc (sizeof (deferred_access));
d->next = deferred_access_stack;
d->deferred_access_checks = NULL_TREE;
d->deferring_access_checks_p = deferring_p;
deferred_access_stack = d;
}
/* Resume deferring access checks again after we stopped doing
this previously. */
void resume_deferring_access_checks (void)
{
deferred_access_stack->deferring_access_checks_p = true;
}
/* Stop deferring access checks. */
void stop_deferring_access_checks (void)
{
deferred_access_stack->deferring_access_checks_p = false;
}
/* Discard the current deferred access checks and restore the
previous states. */
void pop_deferring_access_checks (void)
{
deferred_access *d = deferred_access_stack;
deferred_access_stack = d->next;
/* Remove references to access checks TREE_LIST. */
d->deferred_access_checks = NULL_TREE;
/* Store in free list for later use. */
d->next = deferred_access_free_list;
deferred_access_free_list = d;
}
/* Returns a TREE_LIST representing the deferred checks.
The TREE_PURPOSE of each node is the type through which the
access occurred; the TREE_VALUE is the declaration named.
*/
tree get_deferred_access_checks (void)
{
return deferred_access_stack->deferred_access_checks;
}
/* Take current deferred checks and combine with the
previous states if we also defer checks previously.
Otherwise perform checks now. */
void pop_to_parent_deferring_access_checks (void)
{
tree deferred_check = get_deferred_access_checks ();
deferred_access *d1 = deferred_access_stack;
deferred_access *d2 = deferred_access_stack->next;
deferred_access *d3 = deferred_access_stack->next->next;
/* Temporary swap the order of the top two states, just to make
sure the garbage collector will not reclaim the memory during
processing below. */
deferred_access_stack = d2;
d2->next = d1;
d1->next = d3;
for ( ; deferred_check; deferred_check = TREE_CHAIN (deferred_check))
/* Perform deferred check if required. */
perform_or_defer_access_check (TREE_PURPOSE (deferred_check),
TREE_VALUE (deferred_check));
deferred_access_stack = d1;
d1->next = d2;
d2->next = d3;
pop_deferring_access_checks ();
}
/* Perform the deferred access checks. */
void perform_deferred_access_checks (void)
{
tree deferred_check;
for (deferred_check = deferred_access_stack->deferred_access_checks;
deferred_check;
deferred_check = TREE_CHAIN (deferred_check))
/* Check access. */
enforce_access (TREE_PURPOSE (deferred_check),
TREE_VALUE (deferred_check));
/* No more deferred checks. */
deferred_access_stack->deferred_access_checks = NULL_TREE;
}
/* Defer checking the accessibility of DECL, when looked up in
CLASS_TYPE. */
void perform_or_defer_access_check (tree class_type, tree decl)
{
tree check;
/* If we are not supposed to defer access checks, just check now. */
if (!deferred_access_stack->deferring_access_checks_p)
{
enforce_access (class_type, decl);
return;
}
/* See if we are already going to perform this check. */
for (check = deferred_access_stack->deferred_access_checks;
check;
check = TREE_CHAIN (check))
if (TREE_VALUE (check) == decl
&& same_type_p (TREE_PURPOSE (check), class_type))
return;
/* If not, record the check. */
deferred_access_stack->deferred_access_checks
= tree_cons (class_type, decl,
deferred_access_stack->deferred_access_checks);
}
/* Returns nonzero if the current statement is a full expression,
i.e. temporaries created during that statement should be destroyed
at the end of the statement. */
@ -1506,63 +1644,6 @@ finish_fname (tree id)
return decl;
}
static tree current_type_lookups;
/* Perform deferred access control for types used in the type of a
declaration. */
static void
deferred_type_access_control ()
{
tree lookup = type_lookups;
if (lookup == error_mark_node)
return;
for (; lookup; lookup = TREE_CHAIN (lookup))
enforce_access (TREE_PURPOSE (lookup), TREE_VALUE (lookup));
}
void
decl_type_access_control (decl)
tree decl;
{
tree save_fn;
if (type_lookups == error_mark_node)
return;
save_fn = current_function_decl;
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
current_function_decl = decl;
deferred_type_access_control ();
current_function_decl = save_fn;
/* Now strip away the checks for the current declarator; they were
added to type_lookups after typed_declspecs saved the copy that
ended up in current_type_lookups. */
type_lookups = current_type_lookups;
}
void
save_type_access_control (lookups)
tree lookups;
{
current_type_lookups = lookups;
}
/* Reset the deferred access control. */
void
reset_type_access_control ()
{
type_lookups = NULL_TREE;
current_type_lookups = NULL_TREE;
}
/* Begin a function definition declared with DECL_SPECS, ATTRIBUTES,
and DECLARATOR. Returns nonzero if the function-declaration is
valid. */
@ -1576,9 +1657,6 @@ begin_function_definition (decl_specs, attributes, declarator)
if (!start_function (decl_specs, declarator, attributes, SF_DEFAULT))
return 0;
deferred_type_access_control ();
type_lookups = error_mark_node;
/* The things we're about to see are not directly qualified by any
template headers we've seen thus far. */
reset_specialization ();
@ -1714,10 +1792,6 @@ begin_class_definition (t)
if (t == error_mark_node)
return error_mark_node;
/* Check the bases are accessible. */
decl_type_access_control (TYPE_NAME (t));
reset_type_access_control ();
if (processing_template_parmlist)
{
error ("definition of `%#T' inside template parameter list", t);
@ -2690,3 +2764,5 @@ init_cp_semantics ()
{
lang_expand_stmt = cp_expand_stmt;
}
#include "gt-cp-semantics.h"