aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2004-06-28 15:06:06 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2004-06-28 15:06:06 +0000
commit3e1f1ba5dc85513e05db6a7605ecd51ba476b597 (patch)
tree567d2eb2f5efbe94ad86b984d8c1ee8f056b20dd
parent246d2ceb324bb3483062b211a262aa290f5ecf41 (diff)
downloadgcc-3e1f1ba5dc85513e05db6a7605ecd51ba476b597.zip
gcc-3e1f1ba5dc85513e05db6a7605ecd51ba476b597.tar.gz
gcc-3e1f1ba5dc85513e05db6a7605ecd51ba476b597.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/cp-tree.h26
-rw-r--r--gcc/cp/semantics.c166
3 files changed, 120 insertions, 86 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 74d8457..6601907 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,17 @@
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
* call.c (build_temp): Declare.
(check_constructor_callable): New.
@@ -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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 23e660e..71f4f9a 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 66c892b..5974a7a 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,