summaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorlerdsuwa <lerdsuwa@138bc75d-0d04-0410-961f-82ee72b054a4>2003-05-10 11:06:26 +0000
committerlerdsuwa <lerdsuwa@138bc75d-0d04-0410-961f-82ee72b054a4>2003-05-10 11:06:26 +0000
commit4f62c42e4d56c0363e3cc647167bf2cc6a428f56 (patch)
tree6751b007e2578a4d8d505023786d468444b3694f /gcc/cp
parentd7b22e237997540f61e195c0d2ad60454a84be0b (diff)
downloadgcc-4f62c42e4d56c0363e3cc647167bf2cc6a428f56.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@66659 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog15
-rw-r--r--gcc/cp/cp-tree.h13
-rw-r--r--gcc/cp/parser.c70
-rw-r--r--gcc/cp/semantics.c66
4 files changed, 114 insertions, 50 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 65cc24723c5..2087066e0e7 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2da12e2cf4c..89d068a2183 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 0181f2570bf..607749b2345 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 83440386e4d..dfe40ee0278 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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;