aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>2003-01-14 13:40:53 +0000
committerKriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org>2003-01-14 13:40:53 +0000
commitcf22909ceee710ab2f61b4d689b02cff8d62ec79 (patch)
tree90148a1690538fe0373d3e426aeda784a80a6a4f
parenta686ea5ba7a26bb5c755b5d65d05155770e5de5a (diff)
downloadgcc-cf22909ceee710ab2f61b4d689b02cff8d62ec79.zip
gcc-cf22909ceee710ab2f61b4d689b02cff8d62ec79.tar.gz
gcc-cf22909ceee710ab2f61b4d689b02cff8d62ec79.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog73
-rw-r--r--gcc/cp/config-lang.in2
-rw-r--r--gcc/cp/cp-tree.h42
-rw-r--r--gcc/cp/decl.c9
-rw-r--r--gcc/cp/parser.c391
-rw-r--r--gcc/cp/search.c35
-rw-r--r--gcc/cp/semantics.c206
7 files changed, 343 insertions, 415 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b209ca4..aad06b7 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/config-lang.in b/gcc/cp/config-lang.in
index 66db7ea..d230bc6 100644
--- a/gcc/cp/config-lang.in
+++ b/gcc/cp/config-lang.in
@@ -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"
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 313b124..612fd56 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index dd0e69a..42bbdc8 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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));
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 21d5d21..68997ad 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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;
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 5e9b395..0895a76 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -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,
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 3ed9f2e..e3ae9be 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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"