From 6b6484828fb7d580efae23d5a637bc7229a68fff Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Tue, 16 May 2006 05:39:49 +0000 Subject: re PR c++/27339 (out-of-class definition of value template parameter with private type) PR c++/27339 * cp-tree.h (perform_access_checks): New function. * semantics.c (perform_access_checks): New function. (perform_deferred_access_checks): Use it. * parser.c (cp_parser_simple_declaration): Adjust call to cp_parser_init_declarator. (cp_parser_type_parameter): Do not defer checks in default arguments. (cp_parser_explicit_specialization): Adjust call to cp_parser_single_declaration. (cp_parser_init_declarator): Perform template-parameter access checks. (cp_parser_parameter_declaration): Do not defer checks for template parameter default arguments. (cp_parser_template_declaration_after_export): Gather access checks for template parameters, and pass them to cp_parser_single_declaration. (cp_parser_template_parameter_access_checks): New function. (cp_parser_single_declaration): Add checks parameter. PR c++/27339 * g++.dg/parser/access8.C: Adjust error marker. * g++.dg/template/access17.C: New test. * g++.dg/template/access18.C: Likewise. From-SVN: r113819 --- gcc/cp/ChangeLog | 20 ++++++++++++++++ gcc/cp/cp-tree.h | 1 + gcc/cp/parser.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++------- gcc/cp/semantics.c | 24 ++++++++++++------- 4 files changed, 96 insertions(+), 16 deletions(-) (limited to 'gcc/cp') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3bdf214..42af5fd 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,25 @@ 2006-05-15 Mark Mitchell + PR c++/27339 + * cp-tree.h (perform_access_checks): New function. + * semantics.c (perform_access_checks): New function. + (perform_deferred_access_checks): Use it. + * parser.c (cp_parser_simple_declaration): Adjust call to + cp_parser_init_declarator. + (cp_parser_type_parameter): Do not defer checks in default + arguments. + (cp_parser_explicit_specialization): Adjust call to + cp_parser_single_declaration. + (cp_parser_init_declarator): Perform template-parameter access + checks. + (cp_parser_parameter_declaration): Do not defer checks for + template parameter default arguments. + (cp_parser_template_declaration_after_export): Gather access + checks for template parameters, and pass them to + cp_parser_single_declaration. + (cp_parser_template_parameter_access_checks): New function. + (cp_parser_single_declaration): Add checks parameter. + PR c++/27505 * call.c (convert_like_real): Convert bitfields to their declared types when forming an rvalue. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8e56a9f..3837628 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4153,6 +4153,7 @@ 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_access_checks (tree); extern void perform_deferred_access_checks (void); extern void perform_or_defer_access_check (tree, tree); extern int stmts_are_full_exprs_p (void); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index bee7e9a..c89c357 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1527,7 +1527,7 @@ static void cp_parser_linkage_specification /* Declarators [gram.dcl.decl] */ static tree cp_parser_init_declarator - (cp_parser *, cp_decl_specifier_seq *, bool, bool, int, bool *); + (cp_parser *, cp_decl_specifier_seq *, tree, bool, bool, int, bool *); static cp_declarator *cp_parser_declarator (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool); static cp_declarator *cp_parser_direct_declarator @@ -1726,8 +1726,10 @@ static tree cp_parser_function_definition_after_declarator (cp_parser *, bool); static void cp_parser_template_declaration_after_export (cp_parser *, bool); +static void cp_parser_perform_template_parameter_access_checks + (tree); static tree cp_parser_single_declaration - (cp_parser *, bool, bool *); + (cp_parser *, tree, bool, bool *); static tree cp_parser_functional_cast (cp_parser *, tree); static tree cp_parser_save_member_function_body @@ -7271,6 +7273,7 @@ cp_parser_simple_declaration (cp_parser* parser, /* Parse the init-declarator. */ decl = cp_parser_init_declarator (parser, &decl_specifiers, + /*checks=*/NULL_TREE, function_definition_allowed_p, /*member_p=*/false, declares_class_or_enum, @@ -8574,7 +8577,9 @@ cp_parser_type_parameter (cp_parser* parser) /* Consume the `=' token. */ cp_lexer_consume_token (parser->lexer); /* Parse the default-argument. */ + push_deferring_access_checks (dk_no_deferred); default_argument = cp_parser_type_id (parser); + pop_deferring_access_checks (); } else default_argument = NULL_TREE; @@ -8628,6 +8633,7 @@ cp_parser_type_parameter (cp_parser* parser) /* Consume the `='. */ cp_lexer_consume_token (parser->lexer); /* Parse the id-expression. */ + push_deferring_access_checks (dk_no_deferred); default_argument = cp_parser_id_expression (parser, /*template_keyword_p=*/false, @@ -8652,6 +8658,7 @@ cp_parser_type_parameter (cp_parser* parser) /* See if the default argument is valid. */ default_argument = check_template_template_default_arg (default_argument); + pop_deferring_access_checks (); } else default_argument = NULL_TREE; @@ -9500,6 +9507,7 @@ cp_parser_explicit_specialization (cp_parser* parser) else /* Parse the dependent declaration. */ cp_parser_single_declaration (parser, + /*checks=*/NULL_TREE, /*member_p=*/false, /*friend_p=*/NULL); /* We're done with the specialization. */ @@ -10870,10 +10878,14 @@ cp_parser_asm_definition (cp_parser* parser) function-definition: __extension__ function-definition - The DECL_SPECIFIERS and PREFIX_ATTRIBUTES apply to this declarator. - Returns a representation 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. + The DECL_SPECIFIERS apply to this declarator. Returns a + representation 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. + + The CHECKS are access checks that should be performed once we know + what entity is being declared (and, therefore, what classes have + befriended it). If FUNCTION_DEFINITION_ALLOWED_P then we handle the declarator and for a function-definition here as well. If the declarator is a @@ -10887,6 +10899,7 @@ cp_parser_asm_definition (cp_parser* parser) static tree cp_parser_init_declarator (cp_parser* parser, cp_decl_specifier_seq *decl_specifiers, + tree checks, bool function_definition_allowed_p, bool member_p, int declares_class_or_enum, @@ -11096,6 +11109,9 @@ cp_parser_init_declarator (cp_parser* parser, current_function_decl = decl; } + /* Perform access checks for template parameters. */ + cp_parser_perform_template_parameter_access_checks (checks); + /* Perform the access control checks for the declarator and the the decl-specifiers. */ perform_deferred_access_checks (); @@ -12438,8 +12454,12 @@ cp_parser_parameter_declaration (cp_parser *parser, to avoid collecting live data on the stack. */ ++function_depth; /* Parse the assignment-expression. */ + if (template_parm_p) + push_deferring_access_checks (dk_no_deferred); default_argument = cp_parser_assignment_expression (parser, /*cast_p=*/false); + if (template_parm_p) + pop_deferring_access_checks (); /* Restore saved state. */ --function_depth; parser->greater_than_is_operator_p @@ -15418,6 +15438,7 @@ static void cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) { tree decl = NULL_TREE; + tree checks; tree parameter_list; bool friend_p = false; bool need_lang_pop; @@ -15442,6 +15463,12 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) } else need_lang_pop = false; + + /* We cannot perform access checks on the template parameter + declarations until we know what is being declared, just as we + cannot check the decl-specifier list. */ + push_deferring_access_checks (dk_deferred); + /* If the next token is `>', then we have an invalid specialization. Rather than complain about an invalid template parameter, issue an error message here. */ @@ -15455,6 +15482,12 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) /* Parse the template parameters. */ parameter_list = cp_parser_template_parameter_list (parser); + /* Get the deferred access checks from the parameter list. These + will be checked once we know what is being declared, as for a + member template the checks must be performed in the scope of the + class containing the member. */ + checks = get_deferred_access_checks (); + /* Look for the `>'. */ cp_parser_skip_until_found (parser, CPP_GREATER, "`>'"); /* We just processed one more parameter list. */ @@ -15469,11 +15502,10 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) /* There are no access checks when parsing a template, as we do not know if a specialization will be a friend. */ push_deferring_access_checks (dk_no_check); - decl = cp_parser_single_declaration (parser, + checks, member_p, &friend_p); - pop_deferring_access_checks (); /* If this is a member template declaration, let the front @@ -15492,6 +15524,8 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) /* We are done with the current parameter list. */ --parser->num_template_parameter_lists; + pop_deferring_access_checks (); + /* Finish up. */ finish_template_decl (parameter_list); @@ -15513,6 +15547,18 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) TREE_VALUE (parser->unparsed_functions_queues)); } +/* Perform the deferred access checks from a template-parameter-list. + CHECKS is a TREE_LIST of access checks, as returned by + get_deferred_access_checks. */ + +static void +cp_parser_perform_template_parameter_access_checks (tree checks) +{ + ++processing_template_parmlist; + perform_access_checks (checks); + --processing_template_parmlist; +} + /* Parse a `decl-specifier-seq [opt] init-declarator [opt] ;' or `function-definition' sequence. MEMBER_P is true, this declaration appears in a class scope. @@ -15522,6 +15568,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) static tree cp_parser_single_declaration (cp_parser* parser, + tree checks, bool member_p, bool* friend_p) { @@ -15583,6 +15630,9 @@ cp_parser_single_declaration (cp_parser* parser, decl = TYPE_NAME (decl); else decl = error_mark_node; + + /* Perform access checks for template parameters. */ + cp_parser_perform_template_parameter_access_checks (checks); } } /* If it's not a template class, try for a template function. If @@ -15595,6 +15645,7 @@ cp_parser_single_declaration (cp_parser* parser, || decl_specifiers.type != error_mark_node)) decl = cp_parser_init_declarator (parser, &decl_specifiers, + checks, /*function_definition_allowed_p=*/true, member_p, declares_class_or_enum, diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 23ab2d8..1e315e2 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -261,6 +261,21 @@ pop_to_parent_deferring_access_checks (void) } } +/* Perform the access checks in CHECKS. The TREE_PURPOSE of each node + is the BINFO indicating the qualifying scope used to access the + DECL node stored in the TREE_VALUE of the node. */ + +void +perform_access_checks (tree checks) +{ + while (checks) + { + enforce_access (TREE_PURPOSE (checks), + TREE_VALUE (checks)); + checks = TREE_CHAIN (checks); + } +} + /* Perform the deferred access checks. After performing the checks, we still have to keep the list @@ -280,14 +295,7 @@ pop_to_parent_deferring_access_checks (void) void perform_deferred_access_checks (void) { - tree deferred_check; - - for (deferred_check = get_deferred_access_checks (); - deferred_check; - deferred_check = TREE_CHAIN (deferred_check)) - /* Check access. */ - enforce_access (TREE_PURPOSE (deferred_check), - TREE_VALUE (deferred_check)); + perform_access_checks (get_deferred_access_checks ()); } /* Defer checking the accessibility of DECL, when looked up in -- cgit v1.1