Commit 6b648482 by Mark Mitchell Committed by Mark Mitchell

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
parent d0b89852
2006-05-15 Mark Mitchell <mark@codesourcery.com> 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 PR c++/27505
* call.c (convert_like_real): Convert bitfields to their declared * call.c (convert_like_real): Convert bitfields to their declared
types when forming an rvalue. types when forming an rvalue.
......
...@@ -4153,6 +4153,7 @@ extern void stop_deferring_access_checks (void); ...@@ -4153,6 +4153,7 @@ extern void stop_deferring_access_checks (void);
extern void pop_deferring_access_checks (void); extern void pop_deferring_access_checks (void);
extern tree get_deferred_access_checks (void); extern tree get_deferred_access_checks (void);
extern void pop_to_parent_deferring_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_deferred_access_checks (void);
extern void perform_or_defer_access_check (tree, tree); extern void perform_or_defer_access_check (tree, tree);
extern int stmts_are_full_exprs_p (void); extern int stmts_are_full_exprs_p (void);
......
...@@ -1527,7 +1527,7 @@ static void cp_parser_linkage_specification ...@@ -1527,7 +1527,7 @@ static void cp_parser_linkage_specification
/* Declarators [gram.dcl.decl] */ /* Declarators [gram.dcl.decl] */
static tree cp_parser_init_declarator 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 static cp_declarator *cp_parser_declarator
(cp_parser *, cp_parser_declarator_kind, int *, bool *, bool); (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool);
static cp_declarator *cp_parser_direct_declarator static cp_declarator *cp_parser_direct_declarator
...@@ -1726,8 +1726,10 @@ static tree cp_parser_function_definition_after_declarator ...@@ -1726,8 +1726,10 @@ static tree cp_parser_function_definition_after_declarator
(cp_parser *, bool); (cp_parser *, bool);
static void cp_parser_template_declaration_after_export static void cp_parser_template_declaration_after_export
(cp_parser *, bool); (cp_parser *, bool);
static void cp_parser_perform_template_parameter_access_checks
(tree);
static tree cp_parser_single_declaration static tree cp_parser_single_declaration
(cp_parser *, bool, bool *); (cp_parser *, tree, bool, bool *);
static tree cp_parser_functional_cast static tree cp_parser_functional_cast
(cp_parser *, tree); (cp_parser *, tree);
static tree cp_parser_save_member_function_body static tree cp_parser_save_member_function_body
...@@ -7271,6 +7273,7 @@ cp_parser_simple_declaration (cp_parser* parser, ...@@ -7271,6 +7273,7 @@ cp_parser_simple_declaration (cp_parser* parser,
/* Parse the init-declarator. */ /* Parse the init-declarator. */
decl = cp_parser_init_declarator (parser, &decl_specifiers, decl = cp_parser_init_declarator (parser, &decl_specifiers,
/*checks=*/NULL_TREE,
function_definition_allowed_p, function_definition_allowed_p,
/*member_p=*/false, /*member_p=*/false,
declares_class_or_enum, declares_class_or_enum,
...@@ -8574,7 +8577,9 @@ cp_parser_type_parameter (cp_parser* parser) ...@@ -8574,7 +8577,9 @@ cp_parser_type_parameter (cp_parser* parser)
/* Consume the `=' token. */ /* Consume the `=' token. */
cp_lexer_consume_token (parser->lexer); cp_lexer_consume_token (parser->lexer);
/* Parse the default-argument. */ /* Parse the default-argument. */
push_deferring_access_checks (dk_no_deferred);
default_argument = cp_parser_type_id (parser); default_argument = cp_parser_type_id (parser);
pop_deferring_access_checks ();
} }
else else
default_argument = NULL_TREE; default_argument = NULL_TREE;
...@@ -8628,6 +8633,7 @@ cp_parser_type_parameter (cp_parser* parser) ...@@ -8628,6 +8633,7 @@ cp_parser_type_parameter (cp_parser* parser)
/* Consume the `='. */ /* Consume the `='. */
cp_lexer_consume_token (parser->lexer); cp_lexer_consume_token (parser->lexer);
/* Parse the id-expression. */ /* Parse the id-expression. */
push_deferring_access_checks (dk_no_deferred);
default_argument default_argument
= cp_parser_id_expression (parser, = cp_parser_id_expression (parser,
/*template_keyword_p=*/false, /*template_keyword_p=*/false,
...@@ -8652,6 +8658,7 @@ cp_parser_type_parameter (cp_parser* parser) ...@@ -8652,6 +8658,7 @@ cp_parser_type_parameter (cp_parser* parser)
/* See if the default argument is valid. */ /* See if the default argument is valid. */
default_argument default_argument
= check_template_template_default_arg (default_argument); = check_template_template_default_arg (default_argument);
pop_deferring_access_checks ();
} }
else else
default_argument = NULL_TREE; default_argument = NULL_TREE;
...@@ -9500,6 +9507,7 @@ cp_parser_explicit_specialization (cp_parser* parser) ...@@ -9500,6 +9507,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
else else
/* Parse the dependent declaration. */ /* Parse the dependent declaration. */
cp_parser_single_declaration (parser, cp_parser_single_declaration (parser,
/*checks=*/NULL_TREE,
/*member_p=*/false, /*member_p=*/false,
/*friend_p=*/NULL); /*friend_p=*/NULL);
/* We're done with the specialization. */ /* We're done with the specialization. */
...@@ -10870,10 +10878,14 @@ cp_parser_asm_definition (cp_parser* parser) ...@@ -10870,10 +10878,14 @@ cp_parser_asm_definition (cp_parser* parser)
function-definition: function-definition:
__extension__ function-definition __extension__ function-definition
The DECL_SPECIFIERS and PREFIX_ATTRIBUTES apply to this declarator. The DECL_SPECIFIERS apply to this declarator. Returns a
Returns a representation of the entity declared. If MEMBER_P is TRUE, representation of the entity declared. If MEMBER_P is TRUE, then
then this declarator appears in a class scope. The new DECL created this declarator appears in a class scope. The new DECL created by
by this declarator is returned. 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 If FUNCTION_DEFINITION_ALLOWED_P then we handle the declarator and
for a function-definition here as well. If the declarator is a for a function-definition here as well. If the declarator is a
...@@ -10887,6 +10899,7 @@ cp_parser_asm_definition (cp_parser* parser) ...@@ -10887,6 +10899,7 @@ cp_parser_asm_definition (cp_parser* parser)
static tree static tree
cp_parser_init_declarator (cp_parser* parser, cp_parser_init_declarator (cp_parser* parser,
cp_decl_specifier_seq *decl_specifiers, cp_decl_specifier_seq *decl_specifiers,
tree checks,
bool function_definition_allowed_p, bool function_definition_allowed_p,
bool member_p, bool member_p,
int declares_class_or_enum, int declares_class_or_enum,
...@@ -11096,6 +11109,9 @@ cp_parser_init_declarator (cp_parser* parser, ...@@ -11096,6 +11109,9 @@ cp_parser_init_declarator (cp_parser* parser,
current_function_decl = decl; 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 /* Perform the access control checks for the declarator and the
the decl-specifiers. */ the decl-specifiers. */
perform_deferred_access_checks (); perform_deferred_access_checks ();
...@@ -12438,8 +12454,12 @@ cp_parser_parameter_declaration (cp_parser *parser, ...@@ -12438,8 +12454,12 @@ cp_parser_parameter_declaration (cp_parser *parser,
to avoid collecting live data on the stack. */ to avoid collecting live data on the stack. */
++function_depth; ++function_depth;
/* Parse the assignment-expression. */ /* Parse the assignment-expression. */
if (template_parm_p)
push_deferring_access_checks (dk_no_deferred);
default_argument default_argument
= cp_parser_assignment_expression (parser, /*cast_p=*/false); = cp_parser_assignment_expression (parser, /*cast_p=*/false);
if (template_parm_p)
pop_deferring_access_checks ();
/* Restore saved state. */ /* Restore saved state. */
--function_depth; --function_depth;
parser->greater_than_is_operator_p parser->greater_than_is_operator_p
...@@ -15418,6 +15438,7 @@ static void ...@@ -15418,6 +15438,7 @@ static void
cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
{ {
tree decl = NULL_TREE; tree decl = NULL_TREE;
tree checks;
tree parameter_list; tree parameter_list;
bool friend_p = false; bool friend_p = false;
bool need_lang_pop; bool need_lang_pop;
...@@ -15442,6 +15463,12 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) ...@@ -15442,6 +15463,12 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
} }
else else
need_lang_pop = false; 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 /* If the next token is `>', then we have an invalid
specialization. Rather than complain about an invalid template specialization. Rather than complain about an invalid template
parameter, issue an error message here. */ parameter, issue an error message here. */
...@@ -15455,6 +15482,12 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) ...@@ -15455,6 +15482,12 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
/* Parse the template parameters. */ /* Parse the template parameters. */
parameter_list = cp_parser_template_parameter_list (parser); 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 `>'. */ /* Look for the `>'. */
cp_parser_skip_until_found (parser, CPP_GREATER, "`>'"); cp_parser_skip_until_found (parser, CPP_GREATER, "`>'");
/* We just processed one more parameter list. */ /* We just processed one more parameter list. */
...@@ -15469,11 +15502,10 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) ...@@ -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 /* There are no access checks when parsing a template, as we do not
know if a specialization will be a friend. */ know if a specialization will be a friend. */
push_deferring_access_checks (dk_no_check); push_deferring_access_checks (dk_no_check);
decl = cp_parser_single_declaration (parser, decl = cp_parser_single_declaration (parser,
checks,
member_p, member_p,
&friend_p); &friend_p);
pop_deferring_access_checks (); pop_deferring_access_checks ();
/* If this is a member template declaration, let the front /* 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) ...@@ -15492,6 +15524,8 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
/* We are done with the current parameter list. */ /* We are done with the current parameter list. */
--parser->num_template_parameter_lists; --parser->num_template_parameter_lists;
pop_deferring_access_checks ();
/* Finish up. */ /* Finish up. */
finish_template_decl (parameter_list); finish_template_decl (parameter_list);
...@@ -15513,6 +15547,18 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) ...@@ -15513,6 +15547,18 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
TREE_VALUE (parser->unparsed_functions_queues)); 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 /* Parse a `decl-specifier-seq [opt] init-declarator [opt] ;' or
`function-definition' sequence. MEMBER_P is true, this declaration `function-definition' sequence. MEMBER_P is true, this declaration
appears in a class scope. appears in a class scope.
...@@ -15522,6 +15568,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) ...@@ -15522,6 +15568,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
static tree static tree
cp_parser_single_declaration (cp_parser* parser, cp_parser_single_declaration (cp_parser* parser,
tree checks,
bool member_p, bool member_p,
bool* friend_p) bool* friend_p)
{ {
...@@ -15583,6 +15630,9 @@ cp_parser_single_declaration (cp_parser* parser, ...@@ -15583,6 +15630,9 @@ cp_parser_single_declaration (cp_parser* parser,
decl = TYPE_NAME (decl); decl = TYPE_NAME (decl);
else else
decl = error_mark_node; 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 /* If it's not a template class, try for a template function. If
...@@ -15595,6 +15645,7 @@ cp_parser_single_declaration (cp_parser* parser, ...@@ -15595,6 +15645,7 @@ cp_parser_single_declaration (cp_parser* parser,
|| decl_specifiers.type != error_mark_node)) || decl_specifiers.type != error_mark_node))
decl = cp_parser_init_declarator (parser, decl = cp_parser_init_declarator (parser,
&decl_specifiers, &decl_specifiers,
checks,
/*function_definition_allowed_p=*/true, /*function_definition_allowed_p=*/true,
member_p, member_p,
declares_class_or_enum, declares_class_or_enum,
......
...@@ -261,6 +261,21 @@ pop_to_parent_deferring_access_checks (void) ...@@ -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. /* Perform the deferred access checks.
After performing the checks, we still have to keep the list After performing the checks, we still have to keep the list
...@@ -280,14 +295,7 @@ pop_to_parent_deferring_access_checks (void) ...@@ -280,14 +295,7 @@ pop_to_parent_deferring_access_checks (void)
void void
perform_deferred_access_checks (void) perform_deferred_access_checks (void)
{ {
tree deferred_check; perform_access_checks (get_deferred_access_checks ());
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));
} }
/* Defer checking the accessibility of DECL, when looked up in /* Defer checking the accessibility of DECL, when looked up in
......
2006-05-15 Mark Mitchell <mark@codesourcery.com>
PR c++/27339
* g++.dg/parser/access8.C: Adjust error marker.
* g++.dg/template/access17.C: New test.
* g++.dg/template/access18.C: Likewise.
2006-05-15 Roger Sayle <roger@eyesopen.com> 2006-05-15 Roger Sayle <roger@eyesopen.com>
PR target/26600 PR target/26600
...@@ -5,8 +5,8 @@ class foo ...@@ -5,8 +5,8 @@ class foo
typedef int memfun; // { dg-error "private" } typedef int memfun; // { dg-error "private" }
}; };
template<foo::memfun> // { dg-error "context" } template<foo::memfun>
struct fm_obj { }; struct fm_obj { }; // { dg-error "context" }
template <typename T = foo::memfun> // { dg-error "context" } template <typename T = foo::memfun> // { dg-error "context" }
struct S {}; struct S {};
// PR c++/27339
class A
{
private:
enum private_enum {a};
template<A::private_enum v> // OK
struct B
{
void bm();
};
public:
void am()
{
B<a> instance; //OK
instance.bm();
}
};
template<A::private_enum v> // FAIL
void
A::B<v>::bm(){}
// DR 401
class X {
typedef int a; // { dg-error "private" }
static const int b = 5; // { dg-error "private" }
template <typename>
struct c; // { dg-error "private" }
};
template <typename = X::a> // { dg-error "context" }
struct A;
template <int = X::b> // { dg-error "context" }
struct B;
template <template <typename> class T = X::c> // { dg-error "context" }
struct C;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment