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
This commit is contained in:
Mark Mitchell 2006-05-16 05:39:49 +00:00 committed by Mark Mitchell
parent d0b898529b
commit 6b6484828f
8 changed files with 147 additions and 18 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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,

View File

@ -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

View File

@ -1,3 +1,10 @@
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>
PR target/26600

View File

@ -5,8 +5,8 @@ class foo
typedef int memfun; // { dg-error "private" }
};
template<foo::memfun> // { dg-error "context" }
struct fm_obj { };
template<foo::memfun>
struct fm_obj { }; // { dg-error "context" }
template <typename T = foo::memfun> // { dg-error "context" }
struct S {};

View File

@ -0,0 +1,23 @@
// 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(){}

View File

@ -0,0 +1,19 @@
// 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;