Commit 3e1f1ba5 by Nathan Sidwell Committed by Nathan Sidwell

cp-tree.h (struct deferred_access): Move to ...

	* cp-tree.h (struct deferred_access): Move to ...
	* semantics.c (struct deferred_access): ... here. Adjust.
	(deferred_access_stack): Make a VEC(deferred_access),
	(deferred_access_free_list): Remove.
	(deferred_access_no_check): New.
	(push_deferring_access_checks, resume_deferring_access_checks,
	stop_deferring_access_checks, pop_deferring_access_checks,
	get_deferred_access_checks, pop_to_parent_deferring_access_checks,
	perform_deferred_access_checks, perform_or_defer_access_check): Adjust.

From-SVN: r83790
parent 246d2ceb
2004-06-28 Nathan Sidwell <nathan@codesourcery.com> 2004-06-28 Nathan Sidwell <nathan@codesourcery.com>
* cp-tree.h (struct deferred_access): Move to ...
* semantics.c (struct deferred_access): ... here. Adjust.
(deferred_access_stack): Make a VEC(deferred_access),
(deferred_access_free_list): Remove.
(deferred_access_no_check): New.
(push_deferring_access_checks, resume_deferring_access_checks,
stop_deferring_access_checks, pop_deferring_access_checks,
get_deferred_access_checks, pop_to_parent_deferring_access_checks,
perform_deferred_access_checks, perform_or_defer_access_check): Adjust.
2004-06-28 Nathan Sidwell <nathan@codesourcery.com>
PR C++/16174 PR C++/16174
* call.c (build_temp): Declare. * call.c (build_temp): Declare.
(check_constructor_callable): New. (check_constructor_callable): New.
...@@ -10,6 +22,8 @@ ...@@ -10,6 +22,8 @@
* cp-tree.h (LOOKUP_CONSTRUCTOR_CALLABLE): New. * cp-tree.h (LOOKUP_CONSTRUCTOR_CALLABLE): New.
(LOOKUP_*): Renumber. (LOOKUP_*): Renumber.
2004-06-28 Nathan Sidwell <nathan@codesourcery.com>
* friend.c (add_friend): Only perform access checks when context * friend.c (add_friend): Only perform access checks when context
is a class. is a class.
* lex.c (cxx_make_type): Only create a binfo for aggregate types. * lex.c (cxx_make_type): Only create a binfo for aggregate types.
......
...@@ -3102,32 +3102,6 @@ extern GTY(()) tree integer_three_node; ...@@ -3102,32 +3102,6 @@ extern GTY(()) tree integer_three_node;
function, two inside the body of a function in a local class, etc.) */ function, two inside the body of a function in a local class, etc.) */
extern int function_depth; extern int function_depth;
typedef struct deferred_access GTY(())
{
/* A TREE_LIST representing name-lookups for which we have deferred
checking access controls. We cannot check the accessibility of
names used in a decl-specifier-seq until we know what is being
declared because code like:
class A {
class B {};
B* f();
}
A::B* A::f() { return 0; }
is valid, even though `A::B' is not generally accessible.
The TREE_PURPOSE of each node is the scope used to qualify the
name being looked up; the TREE_VALUE is the DECL to which the
name was resolved. */
tree deferred_access_checks;
/* 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;
/* in pt.c */ /* in pt.c */
/* These values are used for the `STRICT' parameter to type_unification and /* These values are used for the `STRICT' parameter to type_unification and
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
#include "diagnostic.h" #include "diagnostic.h"
#include "cgraph.h" #include "cgraph.h"
#include "tree-iterator.h" #include "tree-iterator.h"
#include "vec.h"
/* There routines provide a modular interface to perform many parsing /* There routines provide a modular interface to perform many parsing
operations. They may therefore be used during actual parsing, or operations. They may therefore be used during actual parsing, or
...@@ -111,9 +112,36 @@ static tree finalize_nrv_r (tree *, int *, void *); ...@@ -111,9 +112,36 @@ static tree finalize_nrv_r (tree *, int *, void *);
In case of parsing error, we simply call `pop_deferring_access_checks' In case of parsing error, we simply call `pop_deferring_access_checks'
without `perform_deferred_access_checks'. */ without `perform_deferred_access_checks'. */
typedef struct deferred_access GTY(())
{
/* A TREE_LIST representing name-lookups for which we have deferred
checking access controls. We cannot check the accessibility of
names used in a decl-specifier-seq until we know what is being
declared because code like:
class A {
class B {};
B* f();
}
A::B* A::f() { return 0; }
is valid, even though `A::B' is not generally accessible.
The TREE_PURPOSE of each node is the scope used to qualify the
name being looked up; the TREE_VALUE is the DECL to which the
name was resolved. */
tree deferred_access_checks;
/* The current mode of access checks. */
enum deferring_kind deferring_access_checks_kind;
} deferred_access;
DEF_VEC_O (deferred_access);
/* Data for deferred access checking. */ /* Data for deferred access checking. */
static GTY(()) deferred_access *deferred_access_stack; static GTY(()) VEC (deferred_access) *deferred_access_stack;
static GTY(()) deferred_access *deferred_access_free_list; static GTY(()) unsigned deferred_access_no_check;
/* Save the current deferred access states and start deferred /* Save the current deferred access states and start deferred
access checking iff DEFER_P is true. */ access checking iff DEFER_P is true. */
...@@ -121,27 +149,18 @@ static GTY(()) deferred_access *deferred_access_free_list; ...@@ -121,27 +149,18 @@ static GTY(()) deferred_access *deferred_access_free_list;
void void
push_deferring_access_checks (deferring_kind deferring) push_deferring_access_checks (deferring_kind deferring)
{ {
deferred_access *d;
/* For context like template instantiation, access checking /* For context like template instantiation, access checking
disabling applies to all nested context. */ disabling applies to all nested context. */
if (deferred_access_stack if (deferred_access_no_check || deferring == dk_no_check)
&& deferred_access_stack->deferring_access_checks_kind == dk_no_check) deferred_access_no_check++;
deferring = dk_no_check;
/* Recycle previously used free store if available. */
if (deferred_access_free_list)
{
d = deferred_access_free_list;
deferred_access_free_list = d->next;
}
else else
d = ggc_alloc (sizeof (deferred_access)); {
deferred_access *ptr;
d->next = deferred_access_stack; ptr = VEC_safe_push (deferred_access, deferred_access_stack, NULL);
d->deferred_access_checks = NULL_TREE; ptr->deferred_access_checks = NULL_TREE;
d->deferring_access_checks_kind = deferring; ptr->deferring_access_checks_kind = deferring;
deferred_access_stack = d; }
} }
/* Resume deferring access checks again after we stopped doing /* Resume deferring access checks again after we stopped doing
...@@ -150,8 +169,9 @@ push_deferring_access_checks (deferring_kind deferring) ...@@ -150,8 +169,9 @@ push_deferring_access_checks (deferring_kind deferring)
void void
resume_deferring_access_checks (void) resume_deferring_access_checks (void)
{ {
if (deferred_access_stack->deferring_access_checks_kind == dk_no_deferred) if (!deferred_access_no_check)
deferred_access_stack->deferring_access_checks_kind = dk_deferred; VEC_last (deferred_access, deferred_access_stack)
->deferring_access_checks_kind = dk_deferred;
} }
/* Stop deferring access checks. */ /* Stop deferring access checks. */
...@@ -159,8 +179,9 @@ resume_deferring_access_checks (void) ...@@ -159,8 +179,9 @@ resume_deferring_access_checks (void)
void void
stop_deferring_access_checks (void) stop_deferring_access_checks (void)
{ {
if (deferred_access_stack->deferring_access_checks_kind == dk_deferred) if (!deferred_access_no_check)
deferred_access_stack->deferring_access_checks_kind = dk_no_deferred; VEC_last (deferred_access, deferred_access_stack)
->deferring_access_checks_kind = dk_no_deferred;
} }
/* Discard the current deferred access checks and restore the /* Discard the current deferred access checks and restore the
...@@ -169,15 +190,10 @@ stop_deferring_access_checks (void) ...@@ -169,15 +190,10 @@ stop_deferring_access_checks (void)
void void
pop_deferring_access_checks (void) pop_deferring_access_checks (void)
{ {
deferred_access *d = deferred_access_stack; if (deferred_access_no_check)
deferred_access_stack = d->next; deferred_access_no_check--;
else
/* Remove references to access checks TREE_LIST. */ VEC_pop (deferred_access, deferred_access_stack);
d->deferred_access_checks = NULL_TREE;
/* Store in free list for later use. */
d->next = deferred_access_free_list;
deferred_access_free_list = d;
} }
/* Returns a TREE_LIST representing the deferred checks. /* Returns a TREE_LIST representing the deferred checks.
...@@ -188,7 +204,11 @@ pop_deferring_access_checks (void) ...@@ -188,7 +204,11 @@ pop_deferring_access_checks (void)
tree tree
get_deferred_access_checks (void) get_deferred_access_checks (void)
{ {
return deferred_access_stack->deferred_access_checks; if (deferred_access_no_check)
return NULL;
else
return (VEC_last (deferred_access, deferred_access_stack)
->deferred_access_checks);
} }
/* Take current deferred checks and combine with the /* Take current deferred checks and combine with the
...@@ -198,27 +218,48 @@ get_deferred_access_checks (void) ...@@ -198,27 +218,48 @@ get_deferred_access_checks (void)
void void
pop_to_parent_deferring_access_checks (void) pop_to_parent_deferring_access_checks (void)
{ {
tree deferred_check = get_deferred_access_checks (); if (deferred_access_no_check)
deferred_access *d1 = deferred_access_stack; deferred_access_no_check--;
deferred_access *d2 = deferred_access_stack->next; else
deferred_access *d3 = deferred_access_stack->next->next; {
tree checks;
/* Temporary swap the order of the top two states, just to make deferred_access *ptr;
sure the garbage collector will not reclaim the memory during
processing below. */
deferred_access_stack = d2;
d2->next = d1;
d1->next = d3;
for ( ; deferred_check; deferred_check = TREE_CHAIN (deferred_check)) checks = (VEC_last (deferred_access, deferred_access_stack)
/* Perform deferred check if required. */ ->deferred_access_checks);
perform_or_defer_access_check (TREE_PURPOSE (deferred_check),
TREE_VALUE (deferred_check));
deferred_access_stack = d1; VEC_pop (deferred_access, deferred_access_stack);
d1->next = d2; ptr = VEC_last (deferred_access, deferred_access_stack);
d2->next = d3; if (ptr->deferring_access_checks_kind == dk_no_deferred)
pop_deferring_access_checks (); {
/* Check access. */
for (; checks; checks = TREE_CHAIN (checks))
enforce_access (TREE_PURPOSE (checks),
TREE_VALUE (checks));
}
else
{
/* Merge with parent. */
tree next;
tree original = ptr->deferred_access_checks;
for (; checks; checks = next)
{
tree probe;
next = TREE_CHAIN (checks);
for (probe = original; probe; probe = TREE_CHAIN (probe))
if (TREE_VALUE (probe) == TREE_VALUE (checks)
&& TREE_PURPOSE (probe) == TREE_PURPOSE (checks))
goto found;
/* Insert into parent's checks. */
TREE_CHAIN (checks) = ptr->deferred_access_checks;
ptr->deferred_access_checks = checks;
found:;
}
}
}
} }
/* Perform the deferred access checks. /* Perform the deferred access checks.
...@@ -241,7 +282,9 @@ void ...@@ -241,7 +282,9 @@ void
perform_deferred_access_checks (void) perform_deferred_access_checks (void)
{ {
tree deferred_check; tree deferred_check;
for (deferred_check = deferred_access_stack->deferred_access_checks;
for (deferred_check = (VEC_last (deferred_access, deferred_access_stack)
->deferred_access_checks);
deferred_check; deferred_check;
deferred_check = TREE_CHAIN (deferred_check)) deferred_check = TREE_CHAIN (deferred_check))
/* Check access. */ /* Check access. */
...@@ -256,30 +299,33 @@ void ...@@ -256,30 +299,33 @@ void
perform_or_defer_access_check (tree binfo, tree decl) perform_or_defer_access_check (tree binfo, tree decl)
{ {
tree check; tree check;
deferred_access *ptr;
/* Exit if we are in a context that no access checking is performed. */ /* Exit if we are in a context that no access checking is performed.
if (deferred_access_stack->deferring_access_checks_kind == dk_no_check) */
if (deferred_access_no_check)
return; return;
my_friendly_assert (TREE_CODE (binfo) == TREE_VEC, 20030623); my_friendly_assert (TREE_CODE (binfo) == TREE_VEC, 20030623);
ptr = VEC_last (deferred_access, deferred_access_stack);
/* If we are not supposed to defer access checks, just check now. */ /* If we are not supposed to defer access checks, just check now. */
if (deferred_access_stack->deferring_access_checks_kind == dk_no_deferred) if (ptr->deferring_access_checks_kind == dk_no_deferred)
{ {
enforce_access (binfo, decl); enforce_access (binfo, decl);
return; return;
} }
/* See if we are already going to perform this check. */ /* See if we are already going to perform this check. */
for (check = deferred_access_stack->deferred_access_checks; for (check = ptr->deferred_access_checks;
check; check;
check = TREE_CHAIN (check)) check = TREE_CHAIN (check))
if (TREE_VALUE (check) == decl && TREE_PURPOSE (check) == binfo) if (TREE_VALUE (check) == decl && TREE_PURPOSE (check) == binfo)
return; return;
/* If not, record the check. */ /* If not, record the check. */
deferred_access_stack->deferred_access_checks ptr->deferred_access_checks
= tree_cons (binfo, decl, = tree_cons (binfo, decl, ptr->deferred_access_checks);
deferred_access_stack->deferred_access_checks);
} }
/* Returns nonzero if the current statement is a full expression, /* Returns nonzero if the current statement is a full expression,
......
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