From 3e1f1ba5dc85513e05db6a7605ecd51ba476b597 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Mon, 28 Jun 2004 15:06:06 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 14 ++++ gcc/cp/cp-tree.h | 26 ------- gcc/cp/semantics.c | 166 +++++++++++++++++++++++++++++---------------- 3 files changed, 120 insertions(+), 86 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 74d845710ac..66019074e65 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2004-06-28 Nathan Sidwell + + * 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 PR C++/16174 @@ -10,6 +22,8 @@ * cp-tree.h (LOOKUP_CONSTRUCTOR_CALLABLE): New. (LOOKUP_*): Renumber. +2004-06-28 Nathan Sidwell + * 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. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 23e660e0a4d..71f4f9a99f7 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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 diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 66c892b7d09..5974a7a6683 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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; - - /* 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; + if (deferred_access_no_check) + deferred_access_no_check--; + else + { + tree checks; + deferred_access *ptr; - 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)); + checks = (VEC_last (deferred_access, deferred_access_stack) + ->deferred_access_checks); - deferred_access_stack = d1; - d1->next = d2; - d2->next = d3; - pop_deferring_access_checks (); + 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); + + 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, -- 2.30.2