aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2006-05-16 05:39:49 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2006-05-16 05:39:49 +0000
commit6b6484828fb7d580efae23d5a637bc7229a68fff (patch)
treee988ca30c77d6ca9b32595fdbd4b59589db99563 /gcc/cp
parentd0b898529b9ac6e3c227567a197d12dcf71dc800 (diff)
downloadgcc-6b6484828fb7d580efae23d5a637bc7229a68fff.zip
gcc-6b6484828fb7d580efae23d5a637bc7229a68fff.tar.gz
gcc-6b6484828fb7d580efae23d5a637bc7229a68fff.tar.bz2
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog20
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/parser.c67
-rw-r--r--gcc/cp/semantics.c24
4 files changed, 96 insertions, 16 deletions
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 <mark@codesourcery.com>
+ 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