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
This commit is contained in:
parent
246d2ceb32
commit
3e1f1ba5dc
3 changed files with 119 additions and 85 deletions
|
@ -1,3 +1,15 @@
|
|||
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
|
||||
|
@ -10,6 +22,8 @@
|
|||
* cp-tree.h (LOOKUP_CONSTRUCTOR_CALLABLE): New.
|
||||
(LOOKUP_*): Renumber.
|
||||
|
||||
2004-06-28 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* friend.c (add_friend): Only perform access checks when context
|
||||
is a class.
|
||||
* lex.c (cxx_make_type): Only create a binfo for aggregate types.
|
||||
|
|
|
@ -3102,32 +3102,6 @@ extern GTY(()) tree integer_three_node;
|
|||
function, two inside the body of a function in a local class, etc.) */
|
||||
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 */
|
||||
|
||||
/* These values are used for the `STRICT' parameter to type_unification and
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "diagnostic.h"
|
||||
#include "cgraph.h"
|
||||
#include "tree-iterator.h"
|
||||
#include "vec.h"
|
||||
|
||||
/* There routines provide a modular interface to perform many parsing
|
||||
operations. They may therefore be used during actual parsing, or
|
||||
|
@ -111,9 +112,36 @@ static tree finalize_nrv_r (tree *, int *, void *);
|
|||
In case of parsing error, we simply call `pop_deferring_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. */
|
||||
static GTY(()) deferred_access *deferred_access_stack;
|
||||
static GTY(()) deferred_access *deferred_access_free_list;
|
||||
static GTY(()) VEC (deferred_access) *deferred_access_stack;
|
||||
static GTY(()) unsigned deferred_access_no_check;
|
||||
|
||||
/* Save the current deferred access states and start deferred
|
||||
access checking iff DEFER_P is true. */
|
||||
|
@ -121,27 +149,18 @@ static GTY(()) deferred_access *deferred_access_free_list;
|
|||
void
|
||||
push_deferring_access_checks (deferring_kind deferring)
|
||||
{
|
||||
deferred_access *d;
|
||||
|
||||
/* For context like template instantiation, access checking
|
||||
disabling applies to all nested context. */
|
||||
if (deferred_access_stack
|
||||
&& deferred_access_stack->deferring_access_checks_kind == dk_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;
|
||||
}
|
||||
if (deferred_access_no_check || deferring == dk_no_check)
|
||||
deferred_access_no_check++;
|
||||
else
|
||||
d = ggc_alloc (sizeof (deferred_access));
|
||||
{
|
||||
deferred_access *ptr;
|
||||
|
||||
d->next = deferred_access_stack;
|
||||
d->deferred_access_checks = NULL_TREE;
|
||||
d->deferring_access_checks_kind = deferring;
|
||||
deferred_access_stack = d;
|
||||
ptr = VEC_safe_push (deferred_access, deferred_access_stack, NULL);
|
||||
ptr->deferred_access_checks = NULL_TREE;
|
||||
ptr->deferring_access_checks_kind = deferring;
|
||||
}
|
||||
}
|
||||
|
||||
/* Resume deferring access checks again after we stopped doing
|
||||
|
@ -150,8 +169,9 @@ push_deferring_access_checks (deferring_kind deferring)
|
|||
void
|
||||
resume_deferring_access_checks (void)
|
||||
{
|
||||
if (deferred_access_stack->deferring_access_checks_kind == dk_no_deferred)
|
||||
deferred_access_stack->deferring_access_checks_kind = dk_deferred;
|
||||
if (!deferred_access_no_check)
|
||||
VEC_last (deferred_access, deferred_access_stack)
|
||||
->deferring_access_checks_kind = dk_deferred;
|
||||
}
|
||||
|
||||
/* Stop deferring access checks. */
|
||||
|
@ -159,8 +179,9 @@ resume_deferring_access_checks (void)
|
|||
void
|
||||
stop_deferring_access_checks (void)
|
||||
{
|
||||
if (deferred_access_stack->deferring_access_checks_kind == dk_deferred)
|
||||
deferred_access_stack->deferring_access_checks_kind = dk_no_deferred;
|
||||
if (!deferred_access_no_check)
|
||||
VEC_last (deferred_access, deferred_access_stack)
|
||||
->deferring_access_checks_kind = dk_no_deferred;
|
||||
}
|
||||
|
||||
/* Discard the current deferred access checks and restore the
|
||||
|
@ -169,15 +190,10 @@ stop_deferring_access_checks (void)
|
|||
void
|
||||
pop_deferring_access_checks (void)
|
||||
{
|
||||
deferred_access *d = deferred_access_stack;
|
||||
deferred_access_stack = d->next;
|
||||
|
||||
/* Remove references to access checks TREE_LIST. */
|
||||
d->deferred_access_checks = NULL_TREE;
|
||||
|
||||
/* Store in free list for later use. */
|
||||
d->next = deferred_access_free_list;
|
||||
deferred_access_free_list = d;
|
||||
if (deferred_access_no_check)
|
||||
deferred_access_no_check--;
|
||||
else
|
||||
VEC_pop (deferred_access, deferred_access_stack);
|
||||
}
|
||||
|
||||
/* Returns a TREE_LIST representing the deferred checks.
|
||||
|
@ -188,7 +204,11 @@ pop_deferring_access_checks (void)
|
|||
tree
|
||||
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
|
||||
|
@ -198,27 +218,48 @@ get_deferred_access_checks (void)
|
|||
void
|
||||
pop_to_parent_deferring_access_checks (void)
|
||||
{
|
||||
tree deferred_check = get_deferred_access_checks ();
|
||||
deferred_access *d1 = deferred_access_stack;
|
||||
deferred_access *d2 = deferred_access_stack->next;
|
||||
deferred_access *d3 = deferred_access_stack->next->next;
|
||||
if (deferred_access_no_check)
|
||||
deferred_access_no_check--;
|
||||
else
|
||||
{
|
||||
tree checks;
|
||||
deferred_access *ptr;
|
||||
|
||||
/* Temporary swap the order of the top two states, just to make
|
||||
sure the garbage collector will not reclaim the memory during
|
||||
processing below. */
|
||||
deferred_access_stack = d2;
|
||||
d2->next = d1;
|
||||
d1->next = d3;
|
||||
checks = (VEC_last (deferred_access, deferred_access_stack)
|
||||
->deferred_access_checks);
|
||||
|
||||
for ( ; deferred_check; deferred_check = TREE_CHAIN (deferred_check))
|
||||
/* Perform deferred check if required. */
|
||||
perform_or_defer_access_check (TREE_PURPOSE (deferred_check),
|
||||
TREE_VALUE (deferred_check));
|
||||
VEC_pop (deferred_access, deferred_access_stack);
|
||||
ptr = VEC_last (deferred_access, deferred_access_stack);
|
||||
if (ptr->deferring_access_checks_kind == dk_no_deferred)
|
||||
{
|
||||
/* 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);
|
||||
|
||||
deferred_access_stack = d1;
|
||||
d1->next = d2;
|
||||
d2->next = d3;
|
||||
pop_deferring_access_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.
|
||||
|
@ -241,7 +282,9 @@ void
|
|||
perform_deferred_access_checks (void)
|
||||
{
|
||||
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 = TREE_CHAIN (deferred_check))
|
||||
/* Check access. */
|
||||
|
@ -256,30 +299,33 @@ void
|
|||
perform_or_defer_access_check (tree binfo, tree decl)
|
||||
{
|
||||
tree check;
|
||||
deferred_access *ptr;
|
||||
|
||||
/* Exit if we are in a context that no access checking is performed. */
|
||||
if (deferred_access_stack->deferring_access_checks_kind == dk_no_check)
|
||||
/* Exit if we are in a context that no access checking is performed.
|
||||
*/
|
||||
if (deferred_access_no_check)
|
||||
return;
|
||||
|
||||
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 (deferred_access_stack->deferring_access_checks_kind == dk_no_deferred)
|
||||
if (ptr->deferring_access_checks_kind == dk_no_deferred)
|
||||
{
|
||||
enforce_access (binfo, decl);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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 = TREE_CHAIN (check))
|
||||
if (TREE_VALUE (check) == decl && TREE_PURPOSE (check) == binfo)
|
||||
return;
|
||||
/* If not, record the check. */
|
||||
deferred_access_stack->deferred_access_checks
|
||||
= tree_cons (binfo, decl,
|
||||
deferred_access_stack->deferred_access_checks);
|
||||
ptr->deferred_access_checks
|
||||
= tree_cons (binfo, decl, ptr->deferred_access_checks);
|
||||
}
|
||||
|
||||
/* Returns nonzero if the current statement is a full expression,
|
||||
|
|
Loading…
Add table
Reference in a new issue