Commit 8d241e0b by Kriang Lerdsuwanakij Committed by Kriang Lerdsuwanakij

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
parent 9ca5e694
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);
......
......@@ -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;
......
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
......
// { 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>;
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