From cf22909ceee710ab2f61b4d689b02cff8d62ec79 Mon Sep 17 00:00:00 2001 From: Kriang Lerdsuwanakij Date: Tue, 14 Jan 2003 13:40:53 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 73 ++++++++ gcc/cp/config-lang.in | 2 +- gcc/cp/cp-tree.h | 42 ++++- gcc/cp/decl.c | 9 +- gcc/cp/parser.c | 391 ++++++++++-------------------------------- gcc/cp/search.c | 35 ---- gcc/cp/semantics.c | 206 +++++++++++++++------- 7 files changed, 343 insertions(+), 415 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index b209ca4c0ea9..aad06b772592 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,76 @@ +2003-01-14 Kriang Lerdsuwanakij + + * 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 PR c++/8748 diff --git a/gcc/cp/config-lang.in b/gcc/cp/config-lang.in index 66db7ea42406..d230bc66236c 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 313b124e56e0..612fd568a735 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 dd0e69a84c98..42bbdc87af2f 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 21d5d21f7eb1..68997ad170b2 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 5e9b3955ad47..0895a76567f9 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 3ed9f2e20a3d..e3ae9be7a9a3 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" -- 2.43.5