cp-tree.h (struct deferred_access): Move to ...
authorNathan Sidwell <nathan@codesourcery.com>
Mon, 28 Jun 2004 15:06:06 +0000 (15:06 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Mon, 28 Jun 2004 15:06:06 +0000 (15:06 +0000)
* 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
gcc/cp/cp-tree.h
gcc/cp/semantics.c

index 74d845710ac46e02118ef903b473f0ba16e596d2..66019074e6554d43fe7ce495fdd52baaff01cd95 100644 (file)
@@ -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.
index 23e660e0a4d4ee4183979595a0f785e6e6047b23..71f4f9a99f75ba2909dcca867f6429a310476be9 100644 (file)
@@ -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
index 66c892b7d094f2b670a0094b165a3e73d9cd84cd..5974a7a66837c56ab2fce37a7fc5fc4e3b78d903 100644 (file)
@@ -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,