mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-24 21:11:19 +08:00
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:
parent
d0b898529b
commit
6b6484828f
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {};
|
||||
|
23
gcc/testsuite/g++.dg/template/access17.C
Normal file
23
gcc/testsuite/g++.dg/template/access17.C
Normal 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(){}
|
19
gcc/testsuite/g++.dg/template/access18.C
Normal file
19
gcc/testsuite/g++.dg/template/access18.C
Normal 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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user