re PR c++/9554 (Out of class declaration of member class template specialisation rejected)
PR c++/9554 * parser.c (cp_parser_class_name): Remove check_access parameter. All caller adjusted. Update declaration. (cp_parser_lookup_name): Likewise. * semantics.c (push_deferring_access_checks): Change parameter type to enum deferring_kind. All caller adjusted. (resume_deferring_access_checks): Adjust to use new enum. (stop_deferring_access_checks): Likewise. (perform_or_defer_access_check): Likewise. * cp-tree.h (deferring_kind): New enum. (deferred_access): Adjust field type. (push_deferring_access_checks): Update declaration. * g++.dg/parse/access1.C: New test. From-SVN: r66659
This commit is contained in:
parent
9ca5e6948d
commit
8d241e0b57
@ -1,3 +1,18 @@
|
||||
2003-05-10 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
|
||||
|
||||
PR c++/9554
|
||||
* parser.c (cp_parser_class_name): Remove check_access parameter.
|
||||
All caller adjusted. Update declaration.
|
||||
(cp_parser_lookup_name): Likewise.
|
||||
* semantics.c (push_deferring_access_checks): Change parameter type
|
||||
to enum deferring_kind. All caller adjusted.
|
||||
(resume_deferring_access_checks): Adjust to use new enum.
|
||||
(stop_deferring_access_checks): Likewise.
|
||||
(perform_or_defer_access_check): Likewise.
|
||||
* cp-tree.h (deferring_kind): New enum.
|
||||
(deferred_access): Adjust field type.
|
||||
(push_deferring_access_checks): Update declaration.
|
||||
|
||||
2003-05-09 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
|
||||
|
||||
PR c++/10555, c++/10576
|
||||
|
@ -3030,6 +3030,13 @@ typedef enum base_access {
|
||||
ba_quiet = 4 /* Do not issue error messages (bit mask). */
|
||||
} base_access;
|
||||
|
||||
/* The various kinds of access check during parsing. */
|
||||
typedef enum deferring_kind {
|
||||
dk_no_deferred = 0, /* Check access immediately */
|
||||
dk_deferred = 1, /* Deferred check */
|
||||
dk_no_check = 2 /* No access check */
|
||||
} deferring_kind;
|
||||
|
||||
/* The kind of base we can find, looking in a class hierarchy.
|
||||
Values <0 indicate we failed. */
|
||||
typedef enum base_kind {
|
||||
@ -3088,8 +3095,8 @@ typedef struct deferred_access GTY(())
|
||||
name being looked up; the TREE_VALUE is the DECL to which the
|
||||
name was resolved. */
|
||||
tree deferred_access_checks;
|
||||
/* TRUE iff we are deferring access checks. */
|
||||
bool deferring_access_checks_p;
|
||||
/* The current mode of access checks. */
|
||||
enum deferring_kind deferring_access_checks_kind;
|
||||
/* The next deferred access data in stack or linked-list. */
|
||||
struct deferred_access *next;
|
||||
} deferred_access;
|
||||
@ -4044,7 +4051,7 @@ extern tree copied_binfo (tree, tree);
|
||||
extern tree original_binfo (tree, tree);
|
||||
|
||||
/* in semantics.c */
|
||||
extern void push_deferring_access_checks (bool defer_p);
|
||||
extern void push_deferring_access_checks (deferring_kind);
|
||||
extern void resume_deferring_access_checks (void);
|
||||
extern void stop_deferring_access_checks (void);
|
||||
extern void pop_deferring_access_checks (void);
|
||||
|
@ -1545,7 +1545,7 @@ static bool cp_parser_ctor_initializer_opt_and_function_body
|
||||
/* Classes [gram.class] */
|
||||
|
||||
static tree cp_parser_class_name
|
||||
(cp_parser *, bool, bool, bool, bool, bool, bool);
|
||||
(cp_parser *, bool, bool, bool, bool, bool);
|
||||
static tree cp_parser_class_specifier
|
||||
(cp_parser *);
|
||||
static tree cp_parser_class_head
|
||||
@ -1654,7 +1654,7 @@ static void cp_parser_label_declaration
|
||||
/* Utility Routines */
|
||||
|
||||
static tree cp_parser_lookup_name
|
||||
(cp_parser *, tree, bool, bool, bool, bool);
|
||||
(cp_parser *, tree, bool, bool, bool);
|
||||
static tree cp_parser_lookup_name_simple
|
||||
(cp_parser *, tree);
|
||||
static tree cp_parser_maybe_treat_template_as_class
|
||||
@ -1914,7 +1914,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser)
|
||||
{
|
||||
tree name;
|
||||
|
||||
/* If parsing tenatively, we should commit; we really are
|
||||
/* If parsing tentatively, we should commit; we really are
|
||||
looking at a declaration. */
|
||||
/* Consume the first identifier. */
|
||||
name = cp_lexer_consume_token (parser->lexer)->value;
|
||||
@ -3081,7 +3081,6 @@ cp_parser_unqualified_id (cp_parser* parser,
|
||||
/*typename_keyword_p=*/false,
|
||||
/*template_keyword_p=*/false,
|
||||
/*type_p=*/false,
|
||||
/*check_access_p=*/true,
|
||||
/*check_dependency=*/false,
|
||||
/*class_head_p=*/false);
|
||||
if (cp_parser_parse_definitely (parser))
|
||||
@ -3099,7 +3098,6 @@ cp_parser_unqualified_id (cp_parser* parser,
|
||||
/*typename_keyword_p=*/false,
|
||||
/*template_keyword_p=*/false,
|
||||
/*type_p=*/false,
|
||||
/*check_access_p=*/true,
|
||||
/*check_dependency=*/false,
|
||||
/*class_head_p=*/false);
|
||||
if (cp_parser_parse_definitely (parser))
|
||||
@ -3117,7 +3115,6 @@ cp_parser_unqualified_id (cp_parser* parser,
|
||||
/*typename_keyword_p=*/false,
|
||||
/*template_keyword_p=*/false,
|
||||
/*type_p=*/false,
|
||||
/*check_access_p=*/true,
|
||||
/*check_dependency=*/false,
|
||||
/*class_head_p=*/false);
|
||||
if (cp_parser_parse_definitely (parser))
|
||||
@ -3132,7 +3129,6 @@ cp_parser_unqualified_id (cp_parser* parser,
|
||||
/*typename_keyword_p=*/false,
|
||||
/*template_keyword_p=*/false,
|
||||
/*type_p=*/false,
|
||||
/*check_access_p=*/true,
|
||||
/*check_dependency=*/false,
|
||||
/*class_head_p=*/false);
|
||||
/* If an error occurred, assume that the name of the
|
||||
@ -3232,7 +3228,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
|
||||
else
|
||||
start = -1;
|
||||
|
||||
push_deferring_access_checks (true);
|
||||
push_deferring_access_checks (dk_deferred);
|
||||
|
||||
while (true)
|
||||
{
|
||||
@ -3485,7 +3481,6 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
|
||||
typename_keyword_p,
|
||||
template_keyword_p,
|
||||
type_p,
|
||||
/*check_access_p=*/true,
|
||||
check_dependency_p,
|
||||
/*class_head_p=*/false);
|
||||
/* If that didn't work, try for a namespace-name. */
|
||||
@ -6535,7 +6530,7 @@ cp_parser_simple_declaration (cp_parser* parser,
|
||||
/* Defer access checks until we know what is being declared; the
|
||||
checks for names appearing in the decl-specifier-seq should be
|
||||
done as if we were in the scope of the thing being declared. */
|
||||
push_deferring_access_checks (true);
|
||||
push_deferring_access_checks (dk_deferred);
|
||||
|
||||
/* Parse the decl-specifier-seq. We have to keep track of whether
|
||||
or not the decl-specifier-seq declares a named class or
|
||||
@ -6564,7 +6559,7 @@ cp_parser_simple_declaration (cp_parser* parser,
|
||||
where "T" should name a type -- but does not. */
|
||||
if (cp_parser_diagnose_invalid_type_name (parser))
|
||||
{
|
||||
/* If parsing tenatively, we should commit; we really are
|
||||
/* If parsing tentatively, we should commit; we really are
|
||||
looking at a declaration. */
|
||||
cp_parser_commit_to_tentative_parse (parser);
|
||||
/* Give up. */
|
||||
@ -7312,7 +7307,6 @@ cp_parser_mem_initializer_id (cp_parser* parser)
|
||||
/*typename_keyword_p=*/true,
|
||||
/*template_keyword_p=*/false,
|
||||
/*type_p=*/false,
|
||||
/*check_access_p=*/true,
|
||||
/*check_dependency_p=*/true,
|
||||
/*class_head_p=*/false);
|
||||
/* Otherwise, we could also be looking for an ordinary identifier. */
|
||||
@ -7322,7 +7316,6 @@ cp_parser_mem_initializer_id (cp_parser* parser)
|
||||
/*typename_keyword_p=*/true,
|
||||
/*template_keyword_p=*/false,
|
||||
/*type_p=*/false,
|
||||
/*check_access_p=*/true,
|
||||
/*check_dependency_p=*/true,
|
||||
/*class_head_p=*/false);
|
||||
/* If we found one, we're done. */
|
||||
@ -7942,7 +7935,7 @@ cp_parser_template_id (cp_parser *parser,
|
||||
else
|
||||
start_of_id = -1;
|
||||
|
||||
push_deferring_access_checks (true);
|
||||
push_deferring_access_checks (dk_deferred);
|
||||
|
||||
/* Parse the template-name. */
|
||||
template = cp_parser_template_name (parser, template_keyword_p,
|
||||
@ -8116,7 +8109,6 @@ cp_parser_template_name (cp_parser* parser,
|
||||
|
||||
/* Look up the name. */
|
||||
decl = cp_parser_lookup_name (parser, identifier,
|
||||
/*check_access=*/true,
|
||||
/*is_type=*/false,
|
||||
/*is_namespace=*/false,
|
||||
check_dependency_p);
|
||||
@ -8343,7 +8335,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
|
||||
}
|
||||
/* We're done with the instantiation. */
|
||||
end_explicit_instantiation ();
|
||||
/* Trun access control back on. */
|
||||
/* Turn access control back on. */
|
||||
scope_chain->check_access = flag_access_control;
|
||||
|
||||
cp_parser_consume_semicolon_at_end_of_statement (parser);
|
||||
@ -8687,7 +8679,6 @@ cp_parser_type_name (cp_parser* parser)
|
||||
/*typename_keyword_p=*/false,
|
||||
/*template_keyword_p=*/false,
|
||||
/*type_p=*/false,
|
||||
/*check_access_p=*/true,
|
||||
/*check_dependency_p=*/true,
|
||||
/*class_head_p=*/false);
|
||||
/* If it's not a class-name, keep looking. */
|
||||
@ -8846,7 +8837,6 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
|
||||
types, so we set IS_TYPE to TRUE when calling
|
||||
cp_parser_lookup_name. */
|
||||
decl = cp_parser_lookup_name (parser, identifier,
|
||||
/*check_access=*/true,
|
||||
/*is_type=*/true,
|
||||
/*is_namespace=*/false,
|
||||
/*check_dependency=*/true);
|
||||
@ -9114,7 +9104,6 @@ cp_parser_namespace_name (cp_parser* parser)
|
||||
function if the token after the name is the scope resolution
|
||||
operator.) */
|
||||
namespace_decl = cp_parser_lookup_name (parser, identifier,
|
||||
/*check_access=*/true,
|
||||
/*is_type=*/false,
|
||||
/*is_namespace=*/true,
|
||||
/*check_dependency=*/true);
|
||||
@ -10957,7 +10946,7 @@ cp_parser_function_definition (cp_parser* parser, bool* friend_p)
|
||||
function is being defined. There is no need to do this for the
|
||||
definition of member functions; we cannot be defining a member
|
||||
from another class. */
|
||||
push_deferring_access_checks (!member_p);
|
||||
push_deferring_access_checks (member_p ? dk_no_check: dk_deferred);
|
||||
|
||||
/* Parse the decl-specifier-seq. */
|
||||
decl_specifiers
|
||||
@ -11301,10 +11290,9 @@ cp_parser_initializer_list (cp_parser* parser)
|
||||
keyword has been used to indicate that the name that appears next
|
||||
is a template. TYPE_P is true iff the next name should be treated
|
||||
as class-name, even if it is declared to be some other kind of name
|
||||
as well. The accessibility of the class-name is checked iff
|
||||
CHECK_ACCESS_P is true. If CHECK_DEPENDENCY_P is FALSE, names are
|
||||
looked up in dependent scopes. If CLASS_HEAD_P is TRUE, this class
|
||||
is the class being defined in a class-head.
|
||||
as well. If CHECK_DEPENDENCY_P is FALSE, names are looked up in
|
||||
dependent scopes. If CLASS_HEAD_P is TRUE, this class is the class
|
||||
being defined in a class-head.
|
||||
|
||||
Returns the TYPE_DECL representing the class. */
|
||||
|
||||
@ -11313,7 +11301,6 @@ cp_parser_class_name (cp_parser *parser,
|
||||
bool typename_keyword_p,
|
||||
bool template_keyword_p,
|
||||
bool type_p,
|
||||
bool check_access_p,
|
||||
bool check_dependency_p,
|
||||
bool class_head_p)
|
||||
{
|
||||
@ -11368,7 +11355,6 @@ cp_parser_class_name (cp_parser *parser,
|
||||
type_p = true;
|
||||
/* Look up the name. */
|
||||
decl = cp_parser_lookup_name (parser, identifier,
|
||||
check_access_p,
|
||||
type_p,
|
||||
/*is_namespace=*/false,
|
||||
check_dependency_p);
|
||||
@ -11434,7 +11420,7 @@ cp_parser_class_specifier (cp_parser* parser)
|
||||
bool nested_name_specifier_p;
|
||||
unsigned saved_num_template_parameter_lists;
|
||||
|
||||
push_deferring_access_checks (false);
|
||||
push_deferring_access_checks (dk_no_deferred);
|
||||
|
||||
/* Parse the class-head. */
|
||||
type = cp_parser_class_head (parser,
|
||||
@ -11635,6 +11621,8 @@ cp_parser_class_head (cp_parser* parser,
|
||||
if (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false))
|
||||
qualified_p = true;
|
||||
|
||||
push_deferring_access_checks (dk_no_check);
|
||||
|
||||
/* Determine the name of the class. Begin by looking for an
|
||||
optional nested-name-specifier. */
|
||||
nested_name_specifier
|
||||
@ -11659,8 +11647,6 @@ cp_parser_class_head (cp_parser* parser,
|
||||
class A { class B; };
|
||||
class A::B {};
|
||||
|
||||
So, we ask cp_parser_class_name not to check accessibility.
|
||||
|
||||
We do not know if we will see a class-name, or a
|
||||
template-name. We look for a class-name first, in case the
|
||||
class-name is a template-id; if we looked for the
|
||||
@ -11670,7 +11656,6 @@ cp_parser_class_head (cp_parser* parser,
|
||||
/*typename_keyword_p=*/false,
|
||||
/*template_keyword_p=*/false,
|
||||
/*type_p=*/true,
|
||||
/*check_access_p=*/false,
|
||||
/*check_dependency_p=*/false,
|
||||
/*class_head_p=*/true);
|
||||
/* If that didn't work, ignore the nested-name-specifier. */
|
||||
@ -11729,6 +11714,8 @@ cp_parser_class_head (cp_parser* parser,
|
||||
}
|
||||
}
|
||||
|
||||
pop_deferring_access_checks ();
|
||||
|
||||
/* If it's not a `:' or a `{' then we can't really be looking at a
|
||||
class-head, since a class-head only appears as part of a
|
||||
class-specifier. We have to detect this situation before calling
|
||||
@ -12528,7 +12515,6 @@ cp_parser_base_specifier (cp_parser* parser)
|
||||
class_scope_p,
|
||||
template_p,
|
||||
/*type_p=*/true,
|
||||
/*check_access=*/true,
|
||||
/*check_dependency_p=*/true,
|
||||
/*class_head_p=*/false);
|
||||
|
||||
@ -13172,10 +13158,6 @@ cp_parser_label_declaration (cp_parser* parser)
|
||||
If there was no entity with the indicated NAME, the ERROR_MARK_NODE
|
||||
is returned.
|
||||
|
||||
If CHECK_ACCESS is TRUE, then access control is performed on the
|
||||
declaration to which the name resolves, and an error message is
|
||||
issued if the declaration is inaccessible.
|
||||
|
||||
If IS_TYPE is TRUE, bindings that do not refer to types are
|
||||
ignored.
|
||||
|
||||
@ -13186,7 +13168,7 @@ cp_parser_label_declaration (cp_parser* parser)
|
||||
types. */
|
||||
|
||||
static tree
|
||||
cp_parser_lookup_name (cp_parser *parser, tree name, bool check_access,
|
||||
cp_parser_lookup_name (cp_parser *parser, tree name,
|
||||
bool is_type, bool is_namespace, bool check_dependency)
|
||||
{
|
||||
tree decl;
|
||||
@ -13354,7 +13336,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name, bool check_access,
|
||||
|
||||
During an explicit instantiation, access is not checked at all,
|
||||
as per [temp.explicit]. */
|
||||
if (check_access && scope_chain->check_access && DECL_P (decl))
|
||||
if (DECL_P (decl))
|
||||
{
|
||||
tree qualifying_type;
|
||||
|
||||
@ -13379,7 +13361,6 @@ static tree
|
||||
cp_parser_lookup_name_simple (cp_parser* parser, tree name)
|
||||
{
|
||||
return cp_parser_lookup_name (parser, name,
|
||||
/*check_access=*/true,
|
||||
/*is_type=*/false,
|
||||
/*is_namespace=*/false,
|
||||
/*check_dependency=*/true);
|
||||
@ -13664,6 +13645,9 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
|
||||
cp_parser_parse_tentatively (parser);
|
||||
/* Assume that we are looking at a constructor declarator. */
|
||||
constructor_p = true;
|
||||
|
||||
push_deferring_access_checks (dk_no_check);
|
||||
|
||||
/* Look for the optional `::' operator. */
|
||||
cp_parser_global_scope_opt (parser,
|
||||
/*current_scope_valid_p=*/false);
|
||||
@ -13699,12 +13683,14 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
|
||||
/*typename_keyword_p=*/false,
|
||||
/*template_keyword_p=*/false,
|
||||
/*type_p=*/false,
|
||||
/*check_access_p=*/false,
|
||||
/*check_dependency_p=*/false,
|
||||
/*class_head_p=*/false);
|
||||
/* If there was no class-name, then this is not a constructor. */
|
||||
constructor_p = !cp_parser_error_occurred (parser);
|
||||
}
|
||||
|
||||
pop_deferring_access_checks ();
|
||||
|
||||
/* If we're still considering a constructor, we have to see a `(',
|
||||
to begin the parameter-declaration-clause, followed by either a
|
||||
`)', an `...', or a decl-specifier. We need to check for a
|
||||
@ -13968,7 +13954,7 @@ cp_parser_single_declaration (cp_parser* parser,
|
||||
whether it will be a function-definition. */
|
||||
cp_parser_parse_tentatively (parser);
|
||||
/* Defer access checks until we know what is being declared. */
|
||||
push_deferring_access_checks (true);
|
||||
push_deferring_access_checks (dk_deferred);
|
||||
|
||||
/* Try the `decl-specifier-seq [opt] init-declarator [opt]'
|
||||
alternative. */
|
||||
@ -14558,7 +14544,7 @@ cp_parser_parse_tentatively (cp_parser* parser)
|
||||
/* In order to avoid repetitive access control error messages,
|
||||
access checks are queued up until we are no longer parsing
|
||||
tentatively. */
|
||||
push_deferring_access_checks (true);
|
||||
push_deferring_access_checks (dk_deferred);
|
||||
}
|
||||
|
||||
/* Commit to the currently active tentative parse. */
|
||||
@ -14678,7 +14664,7 @@ yyparse (void)
|
||||
bool error_occurred;
|
||||
|
||||
the_parser = cp_parser_new ();
|
||||
push_deferring_access_checks (false);
|
||||
push_deferring_access_checks (dk_no_deferred);
|
||||
error_occurred = cp_parser_translation_unit (the_parser);
|
||||
the_parser = NULL;
|
||||
|
||||
|
@ -79,6 +79,57 @@ static tree clear_decl_rtl PARAMS ((tree *, int *, void *));
|
||||
(SUBSTMT) = (COND); \
|
||||
} while (0)
|
||||
|
||||
/* Deferred Access Checking Overview
|
||||
---------------------------------
|
||||
|
||||
Most C++ expressions and declarations require access checking
|
||||
to be performed during parsing. However, in several cases,
|
||||
this has to be treated differently.
|
||||
|
||||
For member declarations, access checking has to be deferred
|
||||
until more information about the declaration is known. For
|
||||
example:
|
||||
|
||||
class A {
|
||||
typedef int X;
|
||||
public:
|
||||
X f();
|
||||
};
|
||||
|
||||
A::X A::f();
|
||||
A::X g();
|
||||
|
||||
When we are parsing the function return type `A::X', we don't
|
||||
really know if this is allowed until we parse the function name.
|
||||
|
||||
Furthermore, some contexts require that access checking is
|
||||
never performed at all. These include class heads, and template
|
||||
instantiations.
|
||||
|
||||
Typical use of access checking functions is described here:
|
||||
|
||||
1. When we enter a context that requires certain access checking
|
||||
mode, the function `push_deferring_access_checks' is called with
|
||||
DEFERRING argument specifying the desired mode. Access checking
|
||||
may be performed immediately (dk_no_deferred), deferred
|
||||
(dk_deferred), or not performed (dk_no_check).
|
||||
|
||||
2. When a declaration such as a type, or a variable, is encountered,
|
||||
the function `perform_or_defer_access_check' is called. It
|
||||
maintains a TREE_LIST of all deferred checks.
|
||||
|
||||
3. The global `current_class_type' or `current_function_decl' is then
|
||||
setup by the parser. `enforce_access' relies on these information
|
||||
to check access.
|
||||
|
||||
4. Upon exiting the context mentioned in step 1,
|
||||
`perform_deferred_access_checks' is called to check all declaration
|
||||
stored in the TREE_LIST. `pop_deferring_access_checks' is then
|
||||
called to restore the previous access checking mode.
|
||||
|
||||
In case of parsing error, we simply call `pop_deferring_access_checks'
|
||||
without `perform_deferred_access_checks'. */
|
||||
|
||||
/* Data for deferred access checking. */
|
||||
static GTY(()) deferred_access *deferred_access_stack;
|
||||
static GTY(()) deferred_access *deferred_access_free_list;
|
||||
@ -86,7 +137,7 @@ static GTY(()) deferred_access *deferred_access_free_list;
|
||||
/* Save the current deferred access states and start deferred
|
||||
access checking iff DEFER_P is true. */
|
||||
|
||||
void push_deferring_access_checks (bool deferring_p)
|
||||
void push_deferring_access_checks (deferring_kind deferring)
|
||||
{
|
||||
deferred_access *d;
|
||||
|
||||
@ -101,7 +152,7 @@ void push_deferring_access_checks (bool deferring_p)
|
||||
|
||||
d->next = deferred_access_stack;
|
||||
d->deferred_access_checks = NULL_TREE;
|
||||
d->deferring_access_checks_p = deferring_p;
|
||||
d->deferring_access_checks_kind = deferring;
|
||||
deferred_access_stack = d;
|
||||
}
|
||||
|
||||
@ -110,14 +161,16 @@ void push_deferring_access_checks (bool deferring_p)
|
||||
|
||||
void resume_deferring_access_checks (void)
|
||||
{
|
||||
deferred_access_stack->deferring_access_checks_p = true;
|
||||
if (deferred_access_stack->deferring_access_checks_kind == dk_no_deferred)
|
||||
deferred_access_stack->deferring_access_checks_kind = dk_deferred;
|
||||
}
|
||||
|
||||
/* Stop deferring access checks. */
|
||||
|
||||
void stop_deferring_access_checks (void)
|
||||
{
|
||||
deferred_access_stack->deferring_access_checks_p = false;
|
||||
if (deferred_access_stack->deferring_access_checks_kind == dk_deferred)
|
||||
deferred_access_stack->deferring_access_checks_kind = dk_no_deferred;
|
||||
}
|
||||
|
||||
/* Discard the current deferred access checks and restore the
|
||||
@ -199,11 +252,14 @@ void perform_or_defer_access_check (tree class_type, tree decl)
|
||||
tree check;
|
||||
|
||||
/* If we are not supposed to defer access checks, just check now. */
|
||||
if (!deferred_access_stack->deferring_access_checks_p)
|
||||
if (deferred_access_stack->deferring_access_checks_kind == dk_no_deferred)
|
||||
{
|
||||
enforce_access (class_type, decl);
|
||||
return;
|
||||
}
|
||||
/* Exit if we are in a context that no access checking is performed. */
|
||||
else if (deferred_access_stack->deferring_access_checks_kind == dk_no_check)
|
||||
return;
|
||||
|
||||
/* See if we are already going to perform this check. */
|
||||
for (check = deferred_access_stack->deferred_access_checks;
|
||||
|
@ -1,3 +1,8 @@
|
||||
2003-05-10 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
|
||||
|
||||
PR c++/9554
|
||||
* g++.dg/parse/access1.C: New test.
|
||||
|
||||
2003-05-09 DJ Delorie <dj@redhat.com>
|
||||
|
||||
* g++.dg/other/stdarg1.C: Make sure arg "3" is passed as a
|
||||
|
13
gcc/testsuite/g++.dg/parse/access1.C
Normal file
13
gcc/testsuite/g++.dg/parse/access1.C
Normal file
@ -0,0 +1,13 @@
|
||||
// { dg-do compile }
|
||||
|
||||
// Origin: Volker Lukas <vlukas@gmx.de>
|
||||
|
||||
// PR c++/9554: Access checking for template ID as class head.
|
||||
|
||||
class enclose
|
||||
{
|
||||
template<typename T> struct enclosed;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct enclose::enclosed<int>;
|
Loading…
Reference in New Issue
Block a user