* cp-tree.h (scope_kind): Add new enumerator.
authorgdr <gdr@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 23 Sep 2003 15:42:21 +0000 (15:42 +0000)
committergdr <gdr@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 23 Sep 2003 15:42:21 +0000 (15:42 +0000)
(keep_next_level): Change parameter type to bool.
(begin_scope):  Change prototype.
(pushlevel): Remove declaration.
* decl.c (push_binding_level): Fold in begin_scope.  Remove.
(struct cp_binding_level): Remove tag_tranparent field.  Make keep
of bitsize one.
(keep_next_level_flag): Make a bool.
(cxx_scope_descriptor): Update scope names table
(make_cxx_scope): Fold in begin_scope.  Remove..
(namespace_scope_ht_size): New function.
(begin_scope): Change prototype.  Return a scope.  Tidy.
(kept_level_p): Update.
(pushlevel): Remove.
(maybe_push_cleanup_level): Simplify.
(poplevel): Update for sk_cleanup and keep change.
(print_binding_level): Likewise.
(initial_push_namespace_scope): Fold in begin_scope.  Remove.
(push_namespace): Update.
(pushtag): Likewise.
(lookup_tag): Likewise.
(lookup_name_current_level): Likewise.
(lookup_type_current_level): Likewise.
(cxx_init_decl_processing): Likewise.
(start_function): Likewise.
(begin_function_body): Likewise.
(start_method): Likewise.
* pt.c (push_inline_template_parms_recursive): Likewise.
(begin_template_parm_list): Likewise.
(begin_specialization): Likewise.
* semantics.c (do_pushlevel): Likewise.
(begin_compound_stmt): Likewise.
(begin_stmt_expr): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@71683 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/pt.c
gcc/cp/semantics.c

index 7f85eaf..5804f9f 100644 (file)
@@ -1,3 +1,39 @@
+2003-09-22  Gabriel Dos Reis  <gcc@integrable-solutions.net>
+
+       * cp-tree.h (scope_kind): Add new enumerator.
+       (keep_next_level): Change parameter type to bool.
+       (begin_scope):  Change prototype.
+       (pushlevel): Remove declaration.
+       * decl.c (push_binding_level): Fold in begin_scope.  Remove.
+       (struct cp_binding_level): Remove tag_tranparent field.  Make keep
+       of bitsize one.
+       (keep_next_level_flag): Make a bool.
+       (cxx_scope_descriptor): Update scope names table
+       (make_cxx_scope): Fold in begin_scope.  Remove..
+       (namespace_scope_ht_size): New function.
+       (begin_scope): Change prototype.  Return a scope.  Tidy.
+       (kept_level_p): Update.
+       (pushlevel): Remove.
+       (maybe_push_cleanup_level): Simplify.
+       (poplevel): Update for sk_cleanup and keep change.
+       (print_binding_level): Likewise.
+       (initial_push_namespace_scope): Fold in begin_scope.  Remove.
+       (push_namespace): Update.
+       (pushtag): Likewise.
+       (lookup_tag): Likewise.
+       (lookup_name_current_level): Likewise.
+       (lookup_type_current_level): Likewise.
+       (cxx_init_decl_processing): Likewise.
+       (start_function): Likewise.
+       (begin_function_body): Likewise.
+       (start_method): Likewise.
+       * pt.c (push_inline_template_parms_recursive): Likewise.
+       (begin_template_parm_list): Likewise.
+       (begin_specialization): Likewise.
+       * semantics.c (do_pushlevel): Likewise.
+       (begin_compound_stmt): Likewise.
+       (begin_stmt_expr): Likewise.
+
 2003-09-21  Richard Henderson  <rth@redhat.com>
 
        * class.c, cp-tree.h, decl.c, decl2.c, error.c, init.c,
index ef38d55..5118b78 100644 (file)
@@ -2935,6 +2935,9 @@ typedef enum scope_kind {
                        is initialized by using "memset" to set the
                        contents to zero, and the default scope kind
                        is "sk_block".  */
+  sk_cleanup,        /* A scope for (pseudo-)scope for cleanup.  It is
+                        peusdo in that it is transparent to name lookup
+                        activities.  */
   sk_try,           /* A try-block.  */
   sk_catch,          /* A catch-block.  */
   sk_for,            /* The scope of the variable declared in a
@@ -3609,7 +3612,6 @@ extern void adjust_clone_args                     (tree);
 extern int global_bindings_p                   (void);
 extern int kept_level_p                                (void);
 extern tree getdecls                           (void);
-extern void pushlevel                          (int);
 extern void insert_block                       (tree);
 extern void set_block                          (tree);
 extern tree pushdecl                           (tree);
@@ -3622,12 +3624,12 @@ extern void cxx_pop_function_context            (struct function *);
 extern void cxx_mark_function_context          (struct function *);
 extern int toplevel_bindings_p                 (void);
 extern int namespace_bindings_p                        (void);
-extern void keep_next_level                    (int);
+extern void keep_next_level (bool);
 extern scope_kind innermost_scope_kind          (void);
 extern int template_parm_scope_p               (void);
 extern void set_class_shadows                  (tree);
 extern void maybe_push_cleanup_level           (tree);
-extern void begin_scope                         (scope_kind);
+extern cxx_scope *begin_scope (scope_kind, tree);
 extern void finish_scope                        (void);
 extern void resume_level                       (struct cp_binding_level *);
 extern void delete_block                       (tree);
index 892affa..9538a1e 100644 (file)
@@ -55,7 +55,6 @@ Boston, MA 02111-1307, USA.  */
 static tree grokparms (tree);
 static const char *redeclaration_error_message (tree, tree);
 
-static void push_binding_level (cxx_scope *);
 static void pop_binding_level (void);
 static void suspend_binding_level (void);
 static void resume_binding_level (struct cp_binding_level *);
@@ -382,19 +381,15 @@ struct cp_binding_level GTY(())
        only valid if KIND == SK_TEMPLATE_PARMS.  */
     bool explicit_spec_p : 1;
 
-    /* 1 means make a BLOCK for this level regardless of all else.
-       2 for temporary binding contours created by the compiler.  */
-    unsigned keep : 2;
+    /* true means make a BLOCK for this level regardless of all else.  */
+    unsigned keep : 1;
 
     /* Nonzero if this level can safely have additional
        cleanup-needing variables added to it.  */
     unsigned more_cleanups_ok : 1;
     unsigned have_cleanups : 1;
 
-    /* Nonzero if this level "doesn't exist" for tags.  */
-    unsigned tag_transparent : 1;
-
-    /* 20 bits left to fill a 32-bit word.  */
+    /* 22 bits left to fill a 32-bit word.  */
   };
 
 #define NULL_BINDING_LEVEL ((struct cp_binding_level *) NULL)
@@ -414,9 +409,9 @@ struct cp_binding_level GTY(())
 
 static GTY((deletable (""))) struct cp_binding_level *free_binding_level;
 
-/* Nonzero means unconditionally make a BLOCK for the next level pushed.  */
+/* true means unconditionally make a BLOCK for the next level pushed.  */
 
-static int keep_next_level_flag;
+static bool keep_next_level_flag;
 
 /* A TREE_LIST of VAR_DECLs.  The TREE_PURPOSE is a RECORD_TYPE or
    UNION_TYPE; the TREE_VALUE is a VAR_DECL with that type.  At the
@@ -452,6 +447,7 @@ cxx_scope_descriptor (cxx_scope *scope)
      enumerators.  */
   static const char* scope_kind_names[] = {
     "block-scope",
+    "cleanup-scope",
     "try-scope",
     "catch-scope",
     "for-scope",
@@ -461,8 +457,10 @@ cxx_scope_descriptor (cxx_scope *scope)
     "template-parameter-scope",
     "template-explicit-spec-scope"
   };
+  const scope_kind kind = scope->explicit_spec_p
+    ? sk_template_spec : scope->kind;
 
-  return scope_kind_names[scope->kind];
+  return scope_kind_names[kind];
 }
 
 /* Output a debugging information about SCOPE when performning
@@ -478,10 +476,27 @@ cxx_scope_debug (cxx_scope *scope, int line, const char *action)
     verbatim ("%s %s %p %d\n", action, desc, (void *) scope, line);
 }
 
-/* Construct a scope that may be TAG-TRANSPARENT, the sub-blocks of
-   which may be KEPT.  */
-static inline cxx_scope *
-make_cxx_scope (bool tag_transparent, int keep)
+/* Return the estimated initial size of the hashtable of a NAMESPACE
+   scope.  */
+
+static inline size_t
+namespace_scope_ht_size (tree ns)
+{
+  tree name = DECL_NAME (ns);
+
+  return name == std_identifier
+    ? NAMESPACE_STD_HT_SIZE
+    : (name == global_scope_name
+       ? GLOBAL_SCOPE_HT_SIZE
+       : NAMESPACE_ORDINARY_HT_SIZE);
+}
+
+/* Create a new KIND scope and make it the top of the active scopes stack.
+   ENTITY is the scope of the associated C++ entity (namespace, class,
+   function); it is NULL otherwise.  */
+
+cxx_scope *
+begin_scope (scope_kind kind, tree entity)
 {
   cxx_scope *scope;
   
@@ -493,31 +508,62 @@ make_cxx_scope (bool tag_transparent, int keep)
     }
   else
     scope = ggc_alloc (sizeof (cxx_scope));
-
   memset (scope, 0, sizeof (cxx_scope));
-  scope->tag_transparent = tag_transparent;
-  scope->keep = keep;
+
+  scope->this_entity = entity;
   scope->more_cleanups_ok = true;
+  switch (kind)
+    {
+    case sk_cleanup:
+      scope->keep = true;
+      break;
+      
+    case sk_template_spec:
+      scope->explicit_spec_p = true;
+      kind = sk_template_parms;
+      /* fall through */
+    case sk_template_parms:
+    case sk_block:
+    case sk_try:
+    case sk_catch:
+    case sk_for:
+    case sk_class:
+    case sk_function_parms:
+      scope->keep = keep_next_level_flag;
+      break;
 
-  return scope;
-}
+    case sk_namespace:
+      scope->type_decls = binding_table_new (namespace_scope_ht_size (entity));
+      NAMESPACE_LEVEL (entity) = scope;
+      VARRAY_TREE_INIT (scope->static_decls,
+                        DECL_NAME (entity) == std_identifier
+                        || DECL_NAME (entity) == global_scope_name
+                        ? 200 : 10,
+                        "Static declarations");
+      break;
 
-static void
-push_binding_level (cxx_scope *newlevel)
-{
-  /* Add this level to the front of the chain (stack) of levels that
-     are active.  */
-  newlevel->level_chain = current_binding_level;
-  current_binding_level = newlevel;
+    default:
+      /* Should not happen.  */
+      my_friendly_assert (false, 20030922);
+      break;
+    }
+  scope->kind = kind;
+
+  /* Add it to the front of currently active scopes stack.  */
+  scope->level_chain = current_binding_level;
+  current_binding_level = scope;
+  keep_next_level_flag = false;
 
   if (ENABLE_SCOPE_CHECKING)
     {
-      newlevel->binding_depth = binding_depth;
+      scope->binding_depth = binding_depth;
       indent (binding_depth);
-      cxx_scope_debug (newlevel, input_location.line, "push");
+      cxx_scope_debug (scope, input_location.line, "push");
       is_class_level = 0;
       binding_depth++;
     }
+
+  return scope;
 }
 
 /* Find the innermost enclosing class scope, and reset
@@ -664,12 +710,12 @@ namespace_bindings_p (void)
   return b->kind == sk_namespace;
 }
 
-/* If KEEP is nonzero, make a BLOCK node for the next binding level,
+/* If KEEP is true, make a BLOCK node for the next binding level,
    unconditionally.  Otherwise, use the normal logic to decide whether
    or not to create a BLOCK.  */
 
 void
-keep_next_level (int keep)
+keep_next_level (bool keep)
 {
   keep_next_level_flag = keep;
 }
@@ -681,9 +727,9 @@ kept_level_p (void)
 {
   return (current_binding_level->blocks != NULL_TREE
          || current_binding_level->keep
+          || current_binding_level->kind == sk_cleanup
          || current_binding_level->names != NULL_TREE
-         || (current_binding_level->type_decls != NULL
-             && !current_binding_level->tag_transparent));
+         || current_binding_level->type_decls != NULL);
 }
 
 /* Returns the kind of the innermost scope.  */
@@ -799,17 +845,6 @@ set_class_shadows (tree shadows)
   class_binding_level->class_shadowed = shadows;
 }
 
-/* Enter a new binding level.
-   If TAG_TRANSPARENT is nonzero, do so only for the name space of variables,
-   not for that of tags.  */
-
-void
-pushlevel (int tag_transparent)
-{
-  push_binding_level (make_cxx_scope (tag_transparent, keep_next_level_flag));
-  keep_next_level_flag = 0;
-}
-
 /* We're defining an object of type TYPE.  If it needs a cleanup, but
    we're not allowed to add any more objects with cleanups to the current
    scope, create a new binding level.  */
@@ -820,27 +855,11 @@ maybe_push_cleanup_level (tree type)
   if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
       && current_binding_level->more_cleanups_ok == 0)
     {
-      keep_next_level (2);
-      pushlevel (1);
+      begin_scope (sk_cleanup, NULL);
       clear_last_expr ();
       add_scope_stmt (/*begin_p=*/1, /*partial_p=*/1);
     }
 }
-  
-/* Enter a new scope.  The KIND indicates what kind of scope is being
-   created.  */
-
-void
-begin_scope (scope_kind sk)
-{
-  pushlevel (0);
-  if (sk == sk_template_spec)
-    {
-      current_binding_level->explicit_spec_p = true;
-      sk = sk_template_parms;
-    }
-  current_binding_level->kind = sk;
-}
 
 /* Exit the current scope.  */
 
@@ -1116,12 +1135,13 @@ poplevel (int keep, int reverse, int functionbody)
   tree block = NULL_TREE;
   tree decl;
   int leaving_for_scope;
+  scope_kind kind;
 
   timevar_push (TV_NAME_LOOKUP);
 
   my_friendly_assert (current_binding_level->kind != sk_class, 19990916);
 
-  real_functionbody = (current_binding_level->keep == 2
+  real_functionbody = (current_binding_level->kind == sk_cleanup
                       ? ((functionbody = 0), tmp) : functionbody);
   subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
 
@@ -1133,7 +1153,7 @@ poplevel (int keep, int reverse, int functionbody)
      rather than the end.  This hack is no longer used.  */
   my_friendly_assert (keep == 0 || keep == 1, 0);
 
-  if (current_binding_level->keep == 1)
+  if (current_binding_level->keep)
     keep = 1;
 
   /* Any uses of undefined labels, and any defined labels, now operate
@@ -1365,7 +1385,7 @@ poplevel (int keep, int reverse, int functionbody)
       pop_labels (block);
     }
 
-  tmp = current_binding_level->keep;
+  kind = current_binding_level->kind;
 
   pop_binding_level ();
   if (functionbody)
@@ -1390,7 +1410,7 @@ poplevel (int keep, int reverse, int functionbody)
     TREE_USED (block) = 1;
 
   /* Take care of compiler's internal binding structures.  */
-  if (tmp == 2)
+  if (kind == sk_cleanup)
     {
       tree scope_stmts;
 
@@ -1461,9 +1481,7 @@ pushlevel_class (void)
   if (ENABLE_SCOPE_CHECKING)
     is_class_level = 1;
 
-  begin_scope (sk_class);
-  class_binding_level = current_binding_level;
-  class_binding_level->this_entity = current_class_type;
+  class_binding_level = begin_scope (sk_class, current_class_type);
 }
 
 /* ...and a poplevel for class declarations.  */
@@ -1770,8 +1788,6 @@ print_binding_level (struct cp_binding_level* lvl)
   tree t;
   int i = 0, len;
   fprintf (stderr, " blocks=" HOST_PTR_PRINTF, (void *) lvl->blocks);
-  if (lvl->tag_transparent)
-    fprintf (stderr, " tag-transparent");
   if (lvl->more_cleanups_ok)
     fprintf (stderr, " more-cleanups-ok");
   if (lvl->have_cleanups)
@@ -1877,30 +1893,6 @@ print_binding_stack (void)
    the identifier is polymorphic, with three possible values:
    NULL_TREE, a list of "cxx_binding"s.  */
 
-
-/* Push the initial binding contour of NAMESPACE-scope.  Any subsequent
-   push of NS is actually a resume.  */
-static void
-initial_push_namespace_scope (tree ns)
-{
-  tree name = DECL_NAME (ns);
-  cxx_scope *scope;
-
-  begin_scope (sk_namespace);
-  scope = current_binding_level;
-  scope->type_decls = binding_table_new (name == std_identifier
-                                         ? NAMESPACE_STD_HT_SIZE
-                                         : (name == global_scope_name
-                                            ? GLOBAL_SCOPE_HT_SIZE
-                                            : NAMESPACE_ORDINARY_HT_SIZE));
-  VARRAY_TREE_INIT (scope->static_decls,
-                    name == std_identifier || name == global_scope_name
-                    ? 200 : 10,
-                    "Static declarations");
-  scope->this_entity = ns;
-  NAMESPACE_LEVEL (ns) = scope;
-}
-
 /* Push into the scope of the NAME namespace.  If NAME is NULL_TREE, then we
    select a name that is unique to this compilation unit.  */
 
@@ -1954,7 +1946,7 @@ push_namespace (tree name)
       d = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
       DECL_CONTEXT (d) = FROB_CONTEXT (current_namespace);
       d = pushdecl (d);
-      initial_push_namespace_scope (d);
+      begin_scope (sk_namespace, d);
     }
   else
     resume_binding_level (NAMESPACE_LEVEL (d));
@@ -2400,7 +2392,7 @@ push_local_name (tree decl)
 }
 
 /* Push a tag name NAME for struct/class/union/enum type TYPE.
-   Normally put it into the inner-most non-tag-transparent scope,
+   Normally put it into the inner-most non-sk_cleanup scope,
    but if GLOBALIZE is true, put it in the inner-most non-class scope.
    The latter is needed for implicit declarations.  */
 
@@ -2411,7 +2403,7 @@ pushtag (tree name, tree type, int globalize)
 
   timevar_push (TV_NAME_LOOKUP);
   b = current_binding_level;
-  while (b->tag_transparent
+  while (b->kind == sk_cleanup
         || (b->kind == sk_class
             && (globalize
                 /* We may be defining a new type in the initializer
@@ -2553,7 +2545,7 @@ clear_anon_tags (void)
     return;
 
   b = current_binding_level;
-  while (b->tag_transparent)
+  while (b->kind == sk_cleanup)
     b = b->level_chain;
   if (b->type_decls != NULL)
     binding_table_remove_anonymous_types (b->type_decls);
@@ -5015,7 +5007,7 @@ follow_tag_typedef (tree type)
    return the structure (or union or enum) definition for that name.
    Searches binding levels from BINDING_SCOPE up to the global level.
    If THISLEVEL_ONLY is nonzero, searches only the specified context
-   (but skips any tag-transparent contexts to find one that is
+   (but skips any sk_cleanup contexts to find one that is
    meaningful for tags).
    FORM says which kind of type the caller wants;
    it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE.
@@ -5103,7 +5095,7 @@ lookup_tag (enum tree_code form, tree name,
               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->type);
             }
          }
-      if (thislevel_only && ! level->tag_transparent)
+      if (thislevel_only && level->kind != sk_cleanup)
        {
          if (level->kind == sk_template_parms && allow_template_parms_p)
            {
@@ -5869,7 +5861,7 @@ lookup_name_current_level (tree name)
          if (BINDING_SCOPE (IDENTIFIER_BINDING (name)) == b)
            POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, IDENTIFIER_VALUE (name));
 
-         if (b->keep == 2)
+         if (b->kind == sk_cleanup)
            b = b->level_chain;
          else
            break;
@@ -5899,7 +5891,7 @@ lookup_type_current_level (tree name)
          if (purpose_member (name, b->type_shadowed))
            POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
                                     REAL_IDENTIFIER_TYPE_VALUE (name));
-         if (b->keep == 2)
+         if (b->kind == sk_cleanup)
            b = b->level_chain;
          else
            break;
@@ -6100,7 +6092,7 @@ cxx_init_decl_processing (void)
   my_friendly_assert (global_namespace == NULL_TREE, 375);
   global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name,
                                       void_type_node);
-  initial_push_namespace_scope (global_namespace);
+  begin_scope (sk_namespace, global_namespace);
 
   current_lang_name = NULL_TREE;
 
@@ -13582,7 +13574,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
        DECL_INTERFACE_KNOWN (decl1) = 1;
     }
 
-  begin_scope (sk_function_parms);
+  begin_scope (sk_function_parms, decl1);
 
   ++function_depth;
 
@@ -13834,7 +13826,7 @@ begin_function_body (void)
     /* Always keep the BLOCK node associated with the outermost pair of
        curly braces of a function.  These are needed for correct
        operation of dwarfout.c.  */
-    keep_next_level (1);
+    keep_next_level (true);
 
   stmt = begin_compound_stmt (/*has_no_scope=*/false);
   COMPOUND_STMT_BODY_BLOCK (stmt) = 1;
@@ -14159,7 +14151,7 @@ start_method (tree declspecs, tree declarator, tree attrlist)
   cp_finish_decl (fndecl, NULL_TREE, NULL_TREE, 0);
 
   /* Make a place for the parms */
-  begin_scope (sk_function_parms);
+  begin_scope (sk_function_parms, fndecl);
 
   DECL_IN_AGGR_P (fndecl) = 1;
   return fndecl;
index 12baea1..aad6c60 100644 (file)
@@ -352,7 +352,8 @@ push_inline_template_parms_recursive (tree parmlist, int levels)
                 parms, current_template_parms);
   TEMPLATE_PARMS_FOR_INLINE (current_template_parms) = 1;
 
-  pushlevel (0);
+  begin_scope (TREE_VEC_LENGTH (parms) ? sk_template_parms : sk_template_spec,
+               NULL);
   for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) 
     {
       tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
@@ -609,7 +610,7 @@ begin_template_parm_list (void)
 
      pushtag contains special code to call pushdecl_with_scope on the
      TEMPLATE_DECL for S2.  */
-  begin_scope (sk_template_parms);
+  begin_scope (sk_template_parms, NULL);
   ++processing_template_decl;
   ++processing_template_parmlist;
   note_template_header (0);
@@ -653,7 +654,7 @@ check_specialization_scope (void)
 void
 begin_specialization (void)
 {
-  begin_scope (sk_template_spec);
+  begin_scope (sk_template_spec, NULL);
   note_template_header (1);
   check_specialization_scope ();
 }
index ef42579..6650bff 100644 (file)
@@ -360,7 +360,7 @@ do_pushlevel (scope_kind sk)
     {
       if (!processing_template_decl)
        add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
-      begin_scope (sk);
+      begin_scope (sk, NULL);
     }
 }
 
@@ -1004,7 +1004,7 @@ begin_compound_stmt (bool has_no_scope)
        statement-expression.  But, if it's a statement-expression with
        a scopeless block, there's nothing to keep, and we don't want
        to accidentally keep a block *inside* the scopeless block.  */ 
-    keep_next_level (0);
+    keep_next_level (false);
 
   return r;
 }
@@ -1408,7 +1408,7 @@ begin_stmt_expr (void)
 
   last_expr_type = NULL_TREE;
   
-  keep_next_level (1);
+  keep_next_level (true);
 
   return last_tree; 
 }