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:
parent
a686ea5ba7
commit
cf22909cee
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
391
gcc/cp/parser.c
391
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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue