This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: C++ PATCH [3.3] Improve name-lookup time


gcc@integrable-solutions.net writes:

[...]

| This patch was successfully bootstrapped and regtested on an
| i686-pc-linux-gnu with no regression.
| 
| OK for 3.3 and mainline?

That patch has been reviewed, commented on by Mark Mitchell and approved
for 3.3.1 and mainline.  This version integrates comments made by
Mark.  It also integrates a correction for an initialization bug found
by Matt Austern.  I'm not going to apply it right now because I have
compile-time gain issues to resolve with Matt.  I'm posting it there so
that people can experiment with it and report numbers.

Thanks,

-- Gaby

Index: ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ChangeLog,v
retrieving revision 1.16114.2.514
diff -p -r1.16114.2.514 ChangeLog
*** ChangeLog	9 May 2003 04:25:59 -0000	1.16114.2.514
--- ChangeLog	10 May 2003 09:08:41 -0000
***************
*** 1,3 ****
--- 1,10 ----
+ 2003-05-10  Gabriel Dos Reis  <gdr@integrable-solutions.net>
+ 
+ 	* hashtable.h (struct ht_identifier): Add new field "hash_value".
+ 	* hashtable.c (ht_lookup): Use it.
+ 	(ht_expand): Likewise.  Avoid doing the same computation twice.
+ 	* tree.h (IDENTIFIER_HASH_VALUE): New macro.
+ 
  2003-05-08  J"orn Rennecke <joern.rennecke@superh.com>
  
  	* sh.c (gen_block_redirect, split_branches): Use
Index: hashtable.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/hashtable.h,v
retrieving revision 1.4
diff -p -r1.4 hashtable.h
*** hashtable.h	14 Sep 2002 15:51:42 -0000	1.4
--- hashtable.h	10 May 2003 09:08:41 -0000
*************** Foundation, 59 Temple Place - Suite 330,
*** 25,32 ****
  typedef struct ht_identifier ht_identifier;
  struct ht_identifier GTY(())
  {
-   unsigned int len;
    const unsigned char *str;
  };
  
  #define HT_LEN(NODE) ((NODE)->len)
--- 25,33 ----
  typedef struct ht_identifier ht_identifier;
  struct ht_identifier GTY(())
  {
    const unsigned char *str;
+   unsigned int len;
+   unsigned int hash_value;
  };
  
  #define HT_LEN(NODE) ((NODE)->len)
Index: hashtable.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/hashtable.c,v
retrieving revision 1.5
diff -p -r1.5 hashtable.c
*** hashtable.c	14 Sep 2002 15:51:42 -0000	1.5
--- hashtable.c	10 May 2003 09:08:42 -0000
*************** ht_lookup (table, str, len, insert)
*** 141,147 ****
        if (node == NULL)
  	break;
  
!       if (HT_LEN (node) == len && !memcmp (HT_STR (node), str, len))
  	{
  	  if (insert == HT_ALLOCED)
  	    /* The string we search for was placed at the end of the
--- 141,148 ----
        if (node == NULL)
  	break;
  
!       if (node->hash_value == hash && HT_LEN (node) == len
!           && !memcmp (HT_STR (node), str, len))
  	{
  	  if (insert == HT_ALLOCED)
  	    /* The string we search for was placed at the end of the
*************** ht_lookup (table, str, len, insert)
*** 161,166 ****
--- 162,168 ----
    table->entries[index] = node;
  
    HT_LEN (node) = len;
+   node->hash_value = hash;
    if (insert == HT_ALLOC)
      HT_STR (node) = obstack_copy0 (&table->stack, str, len);
    else
*************** ht_expand (table)
*** 193,199 ****
        {
  	unsigned int index, hash, hash2;
  
! 	hash = calc_hash (HT_STR (*p), HT_LEN (*p));
  	hash2 = ((hash * 17) & sizemask) | 1;
  	index = hash & sizemask;
  
--- 195,201 ----
        {
  	unsigned int index, hash, hash2;
  
! 	hash = (*p)->hash_value;
  	hash2 = ((hash * 17) & sizemask) | 1;
  	index = hash & sizemask;
  
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.367.2.4
diff -p -r1.367.2.4 tree.h
*** tree.h	24 Mar 2003 17:59:37 -0000	1.367.2.4
--- tree.h	10 May 2003 09:08:49 -0000
*************** struct tree_vector GTY(())
*** 798,803 ****
--- 798,805 ----
    (IDENTIFIER_NODE_CHECK (NODE)->identifier.id.len)
  #define IDENTIFIER_POINTER(NODE) \
    ((const char *) IDENTIFIER_NODE_CHECK (NODE)->identifier.id.str)
+ #define IDENTIFIER_HASH_VALUE(NODE) \
+   (IDENTIFIER_NODE_CHECK (NODE)->identifier.id.hash_value)
  
  /* Translate a hash table identifier pointer to a tree_identifier
     pointer, and vice versa.  */
Index: cp/ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/ChangeLog,v
retrieving revision 1.3076.2.128
diff -p -r1.3076.2.128 ChangeLog
*** cp/ChangeLog	2 May 2003 21:01:22 -0000	1.3076.2.128
--- cp/ChangeLog	10 May 2003 09:09:23 -0000
***************
*** 1,3 ****
--- 1,64 ----
+ 2003-05-10  Gabriel Dos Reis <gdr@integrable-solutions.net>
+ 
+ 	* cp-tree.h (struct binding_entry_s): New datatype.
+ 	(binding_table): Declare.
+ 	(binding_entry): Likewise.
+ 	(bt_foreach_proc): Likewise.
+ 	(binding_table_foreach): Likewise.
+ 	(binding_table_find): Likewise.
+ 	(cxx_remember_type_decls): Likewise.
+ 	(CLASSTYPE_TAGS): Remove.
+ 	(CLASSTYPE_NESTED_UDT): New macro.
+ 	(struct lang_type_class):  Remove tags field.  Add nested_types.
+ 	* decl.c (ENTRY_INDEX): New macro.
+ 	(free_binding_entry):  New free list.
+ 	(binding_entry_make): New function.
+ 	(binding_entry_free): Likewise.
+ 	(struct binding_table_s): New datatype.
+ 	(SCOPE_DEFAULT_HT_SIZE): New macro.
+ 	(CLASS_SCOPE_HT_SIZE): Likewise.
+ 	(NAMESPACE_ORDINARY_HT_SIZE): Likewise.
+ 	(NAMESPACE_STD_HT_SIZE): Likewise.
+ 	(GLOBAL_SCOPE_HT_SIZE): Likewise.
+ 	(binding_table_construct): New function.
+ 	(binding_table_free): Likewise.
+ 	(binding_table_new): Likewise.
+ 	(binding_table_expand): Likewise.
+ 	(binding_table_insert): Likewise.
+ 	(binding_table_find): Likewise.
+ 	(binding_table_find_anon_type): Likewise.
+ 	(binding_table_reverse_maybe_remap): Likewise.
+ 	(binding_table_remove_anonymous_types): Likewise.
+ 	(binding_table_foreach): Likewise.
+ 	(struct cp_binding_level): Remove tags field.  Add type_decls.
+ 	(pop_binding_level): Free binding_entries if possible.
+ 	(kept_level_p): Tidy.
+ 	(poplevel): Remove unused variable tags.
+ 	(bt_print_entry): New function.
+ 	(print_binding_level): Use it.
+ 	(push_namespace): Construct binding table.
+ 	(maybe_process_template_type_declaration): Tidy.
+ 	(pushtag): Likewise.
+ 	(clear_anon_tags): Likewise.
+ 	(cxx_remember_type_decls): New function.
+ 	(lookup_tag): Tidy. 
+ 	(lookup_tag_reverse): Likewise.
+ 	(cxx_init_decl_processing): Construct binding_table for the global
+ 	scope.
+ 	(store_parm_decls): Remove pointless code.
+ 	(gettags): Remove.
+ 	(storetags): Likewise.
+ 	* class.c (unreverse_member_declarations): Don't touch
+ 	CLASSTYPE_TAGS. 
+ 	(pushclass): Remember CLASSTYPE_NESTED_UDT.
+ 	* pt.c (instantiate_class_template): Remove reference to
+ 	CLASSTYPE_TAGS. Remeber CLASSTYPE_NESTED_UDT.
+ 	(bt_instantiate_type_proc): New function.
+ 	(do_type_instantiation): Use it.
+ 	* search.c (lookup_field_r): Use binding_table_find.
+ 	* semantics.c (begin_class_definition): Remove reference to
+ 	CLASSTYPE_TAGS.  Nullify CLASSTYPE_NESTED_UDT.
+ 
  2003-05-02  Richard Henderson  <rth@redhat.com>
  
  	PR c++/10570
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.499.2.13
diff -p -r1.499.2.13 class.c
*** cp/class.c	29 Apr 2003 21:34:49 -0000	1.499.2.13
--- cp/class.c	10 May 2003 09:09:38 -0000
*************** unreverse_member_declarations (t)
*** 5418,5424 ****
    /* The following lists are all in reverse order.  Put them in
       declaration order now.  */
    TYPE_METHODS (t) = nreverse (TYPE_METHODS (t));
-   CLASSTYPE_TAGS (t) = nreverse (CLASSTYPE_TAGS (t));
    CLASSTYPE_DECL_LIST (t) = nreverse (CLASSTYPE_DECL_LIST (t));
  
    /* Actually, for the TYPE_FIELDS, only the non TYPE_DECLs are in
--- 5418,5423 ----
*************** pushclass (type, modify)
*** 5780,5786 ****
  	  unuse_fields (type);
  	}
  
!       storetags (CLASSTYPE_TAGS (type));
      }
  }
  
--- 5779,5785 ----
  	  unuse_fields (type);
  	}
  
!       cxx_remember_type_decls (CLASSTYPE_NESTED_UDT (type));
      }
  }
  
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.776.2.18
diff -p -r1.776.2.18 cp-tree.h
*** cp/cp-tree.h	29 Apr 2003 18:51:55 -0000	1.776.2.18
--- cp/cp-tree.h	10 May 2003 09:09:50 -0000
*************** struct cxx_binding GTY(())
*** 249,254 ****
--- 249,272 ----
    unsigned is_local : 1;
  };
  
+ /* The type of dictionary used to map names to types declared at
+    a given scope.  */
+ typedef struct binding_table_s *binding_table;
+ typedef struct binding_entry_s *binding_entry;
+ 
+ /* The type of a routine repeatedly called by binding_table_foreach.  */
+ typedef void (*bt_foreach_proc) (binding_entry, void *);
+ 
+ struct binding_entry_s GTY(())
+ {
+   binding_entry chain;
+   tree name;
+   tree type;
+ };
+ 
+ extern void binding_table_foreach (binding_table, bt_foreach_proc, void *);
+ extern binding_entry binding_table_find (binding_table, tree);
+ extern void cxx_remember_type_decls (binding_table);
  
  /* Language-dependent contents of an identifier.  */
  
*************** struct lang_type_class GTY(())
*** 1185,1191 ****
    tree vtables;
    tree typeinfo_var;
    tree vbases;
!   tree tags;
    tree as_base;
    tree pure_virtuals;
    tree friend_classes;
--- 1203,1209 ----
    tree vtables;
    tree typeinfo_var;
    tree vbases;
!   binding_table nested_types;
    tree as_base;
    tree pure_virtuals;
    tree friend_classes;
*************** struct lang_type GTY(())
*** 1397,1407 ****
  #define SET_CLASSTYPE_MARKED6(NODE)   SET_CLASSTYPE_MARKED_N (NODE, 5)
  #define CLEAR_CLASSTYPE_MARKED6(NODE) CLEAR_CLASSTYPE_MARKED_N (NODE, 5)
  
! /* A list of the nested tag-types (class, struct, union, or enum)
!    found within this class.  The TREE_PURPOSE of each node is the name
!    of the type; the TREE_VALUE is the type itself.  This list includes
     nested member class templates.  */
! #define CLASSTYPE_TAGS(NODE)		(LANG_TYPE_CLASS_CHECK (NODE)->tags)
  
  /* Nonzero if NODE has a primary base class, i.e., a base class with
     which it shares the virtual function table pointer.  */
--- 1415,1426 ----
  #define SET_CLASSTYPE_MARKED6(NODE)   SET_CLASSTYPE_MARKED_N (NODE, 5)
  #define CLEAR_CLASSTYPE_MARKED6(NODE) CLEAR_CLASSTYPE_MARKED_N (NODE, 5)
  
! /* A binding_table of the nested tag-types (class, struct, union, or enum)
!    found within this class.  The ENTRY->name of each node is the name
!    of the type; the ENTRY->type is the type itself.  This table includes
     nested member class templates.  */
! #define CLASSTYPE_NESTED_UDT(NODE)    \
!    (LANG_TYPE_CLASS_CHECK (NODE)->nested_types)
  
  /* Nonzero if NODE has a primary base class, i.e., a base class with
     which it shares the virtual function table pointer.  */
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.965.2.42
diff -p -r1.965.2.42 decl.c
*** cp/decl.c	29 Apr 2003 18:51:56 -0000	1.965.2.42
--- cp/decl.c	10 May 2003 09:10:18 -0000
*************** int adding_implicit_members = 0;
*** 291,296 ****
--- 291,538 ----
  bool have_extern_spec;
  
  
+ /* Compute the chain index of a binding_entry given the HASH value of its
+    name and the total COUNT of chains.  COUNT is assumed to be a power
+    of 2.  */
+ #define ENTRY_INDEX(HASH, COUNT) (((HASH) >> 3) & ((COUNT) - 1))
+ 
+ /* A free list of "binding_entry"s awaiting for re-use.  */
+ static binding_entry GTY((deletable(""))) free_binding_entry;
+ 
+ /* Create a binding_entry object for (NAME, TYPE).  */
+ static inline binding_entry
+ binding_entry_make (tree name, tree type)
+ {
+   binding_entry entry;
+ 
+   if (free_binding_entry)
+     {
+       entry = free_binding_entry;
+       free_binding_entry = entry->chain;
+     }
+   else
+     entry = ggc_alloc (sizeof (struct binding_entry_s));
+ 
+   entry->name = name;
+   entry->type = type;
+ 
+   return entry;
+ }
+ 
+ /* Put ENTRY back on the free list.  */
+ static inline void
+ binding_entry_free (binding_entry entry)
+ {
+   entry->chain = free_binding_entry;
+   free_binding_entry = entry;
+ }
+ 
+ /* The datatype used to implement the mapping from names to types at
+    a given scope.  */
+ struct binding_table_s GTY(())
+ {
+   /* Array of chains of "binding_entry"s  */
+   binding_entry * GTY((length ("%h.chain_count"))) chain;
+ 
+   /* The number of chains in this table.  This is the length of the
+      the member "chaiin" considered as an array.  */
+   size_t chain_count;
+ 
+   /* Number of "binding_entry"s in this table.  */
+   size_t entry_count;
+ };
+ 
+ /* These macros indicate the initial chains count for binding_table.  */
+ #define SCOPE_DEFAULT_HT_SIZE                        (1 << 3)
+ #define CLASS_SCOPE_HT_SIZE                          (1 << 3)
+ #define NAMESPACE_ORDINARY_HT_SIZE                   (1 << 5)
+ #define NAMESPACE_STD_HT_SIZE                        (1 << 8)
+ #define GLOBAL_SCOPE_HT_SIZE                         (1 << 8)
+ 
+ /* Construct TABLE with an initial CHAIN_COUNT.  */
+ static inline void
+ binding_table_construct (binding_table table, size_t chain_count)
+ {
+   table->chain_count = chain_count;
+   table->entry_count = 0;
+   table->chain = ggc_alloc_cleared
+     (table->chain_count * sizeof (binding_entry));
+ }
+ 
+ /* Free TABLE by making its entries ready for reuse. */
+ static inline void
+ binding_table_free (binding_table table)
+ {
+   size_t i;
+   if (table == NULL)
+     return;
+   
+   for (i = 0; i < table->chain_count; ++i)
+     {
+       while (table->chain[i] != NULL)
+         {
+           binding_entry entry = table->chain[i];
+           table->chain[i] = entry->chain;
+           binding_entry_free (entry);
+         }
+     }
+   table->entry_count = 0;
+ }
+ 
+ /* Allocate a table with CHAIN_COUNT, assumed to be a power of two.  */
+ static inline binding_table
+ binding_table_new (size_t chain_count)
+ {
+   binding_table table = ggc_alloc (sizeof (struct binding_table_s));
+   binding_table_construct (table, chain_count);
+   return table;
+ }
+ 
+ /* Expand TABLE to twice its current chain_count.  */
+ static void
+ binding_table_expand (binding_table table)
+ {
+   const size_t old_chain_count = table->chain_count;
+   const size_t old_entry_count = table->entry_count;
+   const size_t new_chain_count = 2 * old_chain_count;
+   binding_entry *old_chains = table->chain;
+   size_t i;
+   
+   binding_table_construct (table, new_chain_count);
+   for (i = 0; i < old_chain_count; ++i)
+     {
+       binding_entry entry = old_chains[i];
+       for (; entry != NULL; entry = old_chains[i])
+         {
+           const unsigned int hash = IDENTIFIER_HASH_VALUE (entry->name);
+           const size_t j = ENTRY_INDEX (hash, new_chain_count);
+ 
+           old_chains[i] = entry->chain;
+           entry->chain = table->chain[j];
+           table->chain[j] = entry;
+         }
+     }
+   table->entry_count = old_entry_count;
+ }
+ 
+ /* Insert a binding for NAME to TYPe into TABLE.  */
+ static inline void
+ binding_table_insert (binding_table table, tree name, tree type)
+ {
+   const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
+   const size_t i = ENTRY_INDEX (hash, table->chain_count);
+   binding_entry entry = binding_entry_make (name, type);
+   
+   entry->chain = table->chain[i];
+   table->chain[i] = entry;
+   ++table->entry_count;
+ 
+   if (3 * table->chain_count < 5 * table->entry_count)
+     binding_table_expand (table);
+ }
+ 
+ /* Return the binding_entry, if any, that maps NAME.  */
+ binding_entry
+ binding_table_find (binding_table table, tree name)
+ {
+   const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
+   binding_entry entry = table->chain[ENTRY_INDEX (hash, table->chain_count)];
+   
+   while (entry != NULL && entry->name != name)
+     entry = entry->chain;
+ 
+   return entry;
+ }
+ 
+ /* Return the binding_entry, if any, that maps name to an anonymous type.  */
+ static inline tree
+ binding_table_find_anon_type (binding_table table, tree name)
+ {
+   const unsigned int hash = IDENTIFIER_HASH_VALUE (name);
+   binding_entry entry = table->chain[ENTRY_INDEX (hash, table->chain_count)];
+ 
+   while (entry != NULL && TYPE_IDENTIFIER (entry->type) != name)
+     entry = entry->chain;
+ 
+   return entry ? entry->type : NULL;
+ }
+ 
+ /* Return the binding_entry, if any, that has TYPE as target.  If NAME
+    is non-null, then set the domain and rehash that entry.  */
+ static inline binding_entry
+ binding_table_reverse_maybe_remap (binding_table table, tree type, tree name)
+ {
+   const size_t chain_count = table->chain_count;
+   binding_entry entry = NULL;
+   binding_entry *p;
+   size_t i;
+ 
+   for (i = 0; i < chain_count && entry == NULL; ++i)
+     {
+       p = &table->chain[i];
+       while (*p != NULL && entry == NULL)
+         if ((*p)->type == type)
+           entry = *p;
+         else
+           p = &(*p)->chain;
+     }
+   
+   if (entry != NULL && name != NULL && entry->name != name)
+     {
+       /* Remove the bucket from the previous chain.  */
+       *p = (*p)->chain;
+ 
+       /* Remap the name type to type.  */
+       i = ENTRY_INDEX (IDENTIFIER_HASH_VALUE (name), chain_count);
+       entry->chain = table->chain[i];
+       entry->name = name;
+       table->chain[i] = entry;
+     }
+ 
+   return entry;
+ }
+ 
+ /* Remove from TABLE all entries that map to anonymous enums or
+    class-types.  */
+ static void
+ binding_table_remove_anonymous_types (binding_table table)
+ {
+   const size_t chain_count = table->chain_count;
+   size_t i;
+ 
+   for (i = 0; i < chain_count; ++i)
+     {
+       binding_entry *p = &table->chain[i];
+ 
+       while (*p != NULL)
+         if (ANON_AGGRNAME_P ((*p)->name))
+           {
+             binding_entry e = *p;
+             *p = (*p)->chain;
+             --table->entry_count;
+             binding_entry_free (e);
+           }
+         else
+           p = &(*p)->chain;
+     }
+ }
+ 
+ /* Apply PROC -- with DATA -- to all entries in TABLE.  */
+ void
+ binding_table_foreach (binding_table table, bt_foreach_proc proc, void *data)
+ {
+   const size_t chain_count = table->chain_count;
+   size_t i;
+   
+   for (i = 0; i < chain_count; ++i)
+     {
+       binding_entry entry = table->chain[i];
+       for (; entry != NULL; entry = entry->chain)
+         proc (entry, data);
+     }
+ }
+ 
+ 
  /* For each binding contour we allocate a binding_level structure
     which records the names defined in that contour.
     Contours include:
*************** struct cp_binding_level GTY(())
*** 335,349 ****
      /* A chain of VTABLE_DECL nodes.  */
      tree vtables; 
  
!     /* A list of structure, union and enum definitions, for looking up
!        tag names.
!        It is a chain of TREE_LIST nodes, each of whose TREE_PURPOSE is a name,
!        or NULL_TREE; and whose TREE_VALUE is a RECORD_TYPE, UNION_TYPE,
!        or ENUMERAL_TYPE node.
! 
!        C++: the TREE_VALUE nodes can be simple types for
!        component_bindings.  */
!     tree tags;
  
      /* A list of USING_DECL nodes.  */
      tree usings;
--- 577,584 ----
      /* A chain of VTABLE_DECL nodes.  */
      tree vtables; 
  
!     /* A dictionary for looking up enums or class-types names.  */
!     binding_table type_decls;
  
      /* A list of USING_DECL nodes.  */
      tree usings;
*************** pop_binding_level ()
*** 548,553 ****
--- 783,792 ----
      register struct cp_binding_level *level = current_binding_level;
      current_binding_level = current_binding_level->level_chain;
      level->level_chain = free_binding_level;
+     if (level->parm_flag != 2)
+       binding_table_free (level->type_decls);
+     else
+       level->type_decls = NULL;
  #if 0 /* defined(DEBUG_BINDING_LEVELS) */
      if (level->binding_depth != binding_depth)
        abort ();
*************** kept_level_p ()
*** 684,690 ****
    return (current_binding_level->blocks != NULL_TREE
  	  || current_binding_level->keep
  	  || current_binding_level->names != NULL_TREE
! 	  || (current_binding_level->tags != NULL_TREE
  	      && !current_binding_level->tag_transparent));
  }
  
--- 923,929 ----
    return (current_binding_level->blocks != NULL_TREE
  	  || current_binding_level->keep
  	  || current_binding_level->names != NULL_TREE
! 	  || (current_binding_level->type_decls != NULL
  	      && !current_binding_level->tag_transparent));
  }
  
*************** poplevel (keep, reverse, functionbody)
*** 1281,1287 ****
    tree decls;
    int tmp = functionbody;
    int real_functionbody;
-   tree tags;
    tree subblocks;
    tree block = NULL_TREE;
    tree decl;
--- 1520,1525 ----
*************** poplevel (keep, reverse, functionbody)
*** 1297,1303 ****
  
    real_functionbody = (current_binding_level->keep == 2
  		       ? ((functionbody = 0), tmp) : functionbody);
-   tags = functionbody >= 0 ? current_binding_level->tags : 0;
    subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
  
    my_friendly_assert (!current_binding_level->class_shadowed,
--- 1535,1540 ----
*************** wrapup_globals_for_namespace (namespace,
*** 1948,1953 ****
--- 2185,2228 ----
  static int no_print_functions = 0;
  static int no_print_builtins = 0;
  
+ /* Called from print_binding_level through binding_table_foreach to
+    print the content of binding ENTRY.  DATA is a pointer to line offset
+    marker.  */
+ static void
+ bt_print_entry (binding_entry entry, void *data)
+ {
+   int *p = (int *) data;
+   int len;
+ 
+   if (entry->name == NULL)
+     len = 3;
+   else if (entry->name == TYPE_IDENTIFIER (entry->type))
+     len = 2;
+   else
+     len = 4;
+ 
+   *p += len;
+ 
+   if (*p > 5)
+     {
+       fprintf (stderr, "\n\t");
+       *p = len;
+     }
+   if (entry->name == NULL)
+     {
+       print_node_brief (stderr, "<unnamed-typedef", entry->type, 0);
+       fprintf (stderr, ">");
+     }
+   else if (entry->name == TYPE_IDENTIFIER (entry->type))
+     print_node_brief (stderr, "", entry->type, 0);
+   else
+     {
+       print_node_brief (stderr, "<typedef", entry->name, 0);
+       print_node_brief (stderr, "", entry->type, 0);
+       fprintf (stderr, ">");
+     }
+ }
+ 
  void
  print_binding_level (lvl)
       struct cp_binding_level *lvl;
*************** print_binding_level (lvl)
*** 1994,2031 ****
        if (i)
          fprintf (stderr, "\n");
      }
!   if (lvl->tags)
      {
        fprintf (stderr, " tags:\t");
        i = 0;
!       for (t = lvl->tags; t; t = TREE_CHAIN (t))
! 	{
! 	  if (TREE_PURPOSE (t) == NULL_TREE)
! 	    len = 3;
! 	  else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t)))
! 	    len = 2;
! 	  else
! 	    len = 4;
! 	  i += len;
! 	  if (i > 5)
! 	    {
! 	      fprintf (stderr, "\n\t");
! 	      i = len;
! 	    }
! 	  if (TREE_PURPOSE (t) == NULL_TREE)
! 	    {
! 	      print_node_brief (stderr, "<unnamed-typedef", TREE_VALUE (t), 0);
! 	      fprintf (stderr, ">");
! 	    }
! 	  else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t)))
! 	    print_node_brief (stderr, "", TREE_VALUE (t), 0);
! 	  else
! 	    {
! 	      print_node_brief (stderr, "<typedef", TREE_PURPOSE (t), 0);
! 	      print_node_brief (stderr, "", TREE_VALUE (t), 0);
! 	      fprintf (stderr, ">");
! 	    }
! 	}
        if (i)
  	fprintf (stderr, "\n");
      }
--- 2269,2279 ----
        if (i)
          fprintf (stderr, "\n");
      }
!   if (lvl->type_decls)
      {
        fprintf (stderr, " tags:\t");
        i = 0;
!       binding_table_foreach (lvl->type_decls, bt_print_entry, &i);
        if (i)
  	fprintf (stderr, "\n");
      }
*************** push_namespace (name)
*** 2257,2262 ****
--- 2505,2514 ----
  	  pushlevel (0);
  	  declare_namespace_level ();
  	  NAMESPACE_LEVEL (d) = current_binding_level;
+           current_binding_level->type_decls =
+             binding_table_new (name == std_identifier
+                                ? NAMESPACE_STD_HT_SIZE
+                                : NAMESPACE_ORDINARY_HT_SIZE);
  	  VARRAY_TREE_INIT (current_binding_level->static_decls,
  			    name != std_identifier ? 10 : 200,
  			    "Static declarations");
*************** maybe_process_template_type_declaration 
*** 2638,2650 ****
  	      /* Put this tag on the list of tags for the class, since
  		 that won't happen below because B is not the class
  		 binding level, but is instead the pseudo-global level.  */
! 	      b->level_chain->tags =
! 		tree_cons (name, type, b->level_chain->tags);
  	      if (!COMPLETE_TYPE_P (current_class_type))
  		{
  		  maybe_add_class_template_decl_list (current_class_type,
  						      type, /*friend_p=*/0);
! 		  CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
  		}
  	    }
  	}
--- 2890,2905 ----
  	      /* Put this tag on the list of tags for the class, since
  		 that won't happen below because B is not the class
  		 binding level, but is instead the pseudo-global level.  */
!               if (b->level_chain->type_decls == NULL)
!                 b->level_chain->type_decls =
!                   binding_table_new (SCOPE_DEFAULT_HT_SIZE);
!               binding_table_insert (b->level_chain->type_decls, name, type);
  	      if (!COMPLETE_TYPE_P (current_class_type))
  		{
  		  maybe_add_class_template_decl_list (current_class_type,
  						      type, /*friend_p=*/0);
! 		  CLASSTYPE_NESTED_UDT (current_class_type) =
!                     b->level_chain->type_decls;
  		}
  	    }
  	}
*************** pushtag (name, type, globalize)
*** 2740,2746 ****
  		 || COMPLETE_TYPE_P (b->this_class))))
      b = b->level_chain;
  
!   b->tags = tree_cons (name, type, b->tags);
  
    if (name)
      {
--- 2995,3003 ----
  		 || COMPLETE_TYPE_P (b->this_class))))
      b = b->level_chain;
  
!   if (b->type_decls == NULL)
!     b->type_decls = binding_table_new (SCOPE_DEFAULT_HT_SIZE);
!   binding_table_insert (b->type_decls, name, type);
  
    if (name)
      {
*************** pushtag (name, type, globalize)
*** 2817,2823 ****
  	    {
  	      maybe_add_class_template_decl_list (current_class_type,
  						  type, /*friend_p=*/0);
! 	      CLASSTYPE_TAGS (current_class_type) = b->tags;
  	    }
  	}
      }
--- 3074,3080 ----
  	    {
  	      maybe_add_class_template_decl_list (current_class_type,
  						  type, /*friend_p=*/0);
! 	      CLASSTYPE_NESTED_UDT (current_class_type) = b->type_decls;
  	    }
  	}
      }
*************** void
*** 2865,2871 ****
  clear_anon_tags ()
  {
    register struct cp_binding_level *b;
-   register tree tags;
    static int last_cnt = 0;
  
    /* Fast out if no new anon names were declared.  */
--- 3122,3127 ----
*************** clear_anon_tags ()
*** 2875,2891 ****
    b = current_binding_level;
    while (b->tag_transparent)
      b = b->level_chain;
!   tags = b->tags;
!   while (tags)
!     {
!       /* A NULL purpose means we have already processed all tags
! 	 from here to the end of the list.  */
!       if (TREE_PURPOSE (tags) == NULL_TREE)
! 	break;
!       if (ANON_AGGRNAME_P (TREE_PURPOSE (tags)))
! 	TREE_PURPOSE (tags) = NULL_TREE;
!       tags = TREE_CHAIN (tags);
!     }
    last_cnt = anon_cnt;
  }
  
--- 3131,3138 ----
    b = current_binding_level;
    while (b->tag_transparent)
      b = b->level_chain;
!   if (b->type_decls != NULL)
!     binding_table_remove_anonymous_types (b->type_decls);
    last_cnt = anon_cnt;
  }
  
*************** getdecls ()
*** 5283,5296 ****
    return current_binding_level->names;
  }
  
- /* Return the list of type-tags (for structs, etc) of the current level.  */
- 
- tree
- gettags ()
- {
-   return current_binding_level->tags;
- }
- 
  /* Store the list of declarations of the current level.
     This is done for the parameter declarations of a function being defined,
     after they are modified in the light of any missing parameters.  */
--- 5530,5535 ----
*************** storedecls (decls)
*** 5302,5315 ****
    current_binding_level->names = decls;
  }
  
! /* Similarly, store the list of tags of the current level.  */
! 
  void
! storetags (tags)
!      tree tags;
  {
!   current_binding_level->tags = tags;
  }
  
  /* Return the type that should be used when TYPE's name is preceded
     by a tag such as 'struct' or 'union', or null if the name cannot
--- 5541,5555 ----
    current_binding_level->names = decls;
  }
  
! /* Set the current binding TABLE for type declarations..  This is a
!    temporary workaround of the fact that the data structure classtypes
!    does not currently carry its allocated cxx_scope structure.  */
  void
! cxx_remember_type_decls (binding_table table)
  {
!   current_binding_level->type_decls = table;
  }
+ 
  
  /* Return the type that should be used when TYPE's name is preceded
     by a tag such as 'struct' or 'union', or null if the name cannot
*************** lookup_tag (form, name, binding_level, t
*** 5374,5393 ****
    /* Nonzero if, we should look past a template parameter level, even
       if THISLEVEL_ONLY.  */
    int allow_template_parms_p = 1;
  
    timevar_push (TV_NAME_LOOKUP);
  
    for (level = binding_level; level; level = level->level_chain)
      {
        register tree tail;
!       if (ANON_AGGRNAME_P (name))
! 	for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
! 	  {
! 	    /* There's no need for error checking here, because
! 	       anon names are unique throughout the compilation.  */
! 	    if (TYPE_IDENTIFIER (TREE_VALUE (tail)) == name)
! 	      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_VALUE (tail));
! 	  }
        else if (level->namespace_p)
  	/* Do namespace lookup.  */
  	for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
--- 5614,5634 ----
    /* Nonzero if, we should look past a template parameter level, even
       if THISLEVEL_ONLY.  */
    int allow_template_parms_p = 1;
+   bool type_is_anonymous = ANON_AGGRNAME_P (name);
  
    timevar_push (TV_NAME_LOOKUP);
  
    for (level = binding_level; level; level = level->level_chain)
      {
        register tree tail;
!       if (type_is_anonymous && level->type_decls != NULL)
!         {
!           tree type = binding_table_find_anon_type (level->type_decls, name);
!           /* There's no need for error checking here, because
!              anon names are unique throughout the compilation.  */
!           if (type != NULL)
!             POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, type);
!         }
        else if (level->namespace_p)
  	/* Do namespace lookup.  */
  	for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
*************** lookup_tag (form, name, binding_level, t
*** 5429,5451 ****
  	    if (thislevel_only || tail == global_namespace)
  	      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
  	  }
!       else
! 	for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
! 	  {
! 	    if (TREE_PURPOSE (tail) == name)
! 	      {
! 		enum tree_code code = TREE_CODE (TREE_VALUE (tail));
! 		
! 		if (code != form
! 		    && (form == ENUMERAL_TYPE || code == ENUMERAL_TYPE))
! 		  {
! 		    /* Definition isn't the kind we were looking for.  */
! 		    error ("`%#D' redeclared as %C", TREE_VALUE (tail), form);
! 		    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
! 		  }
! 		POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_VALUE (tail));
! 	      }
! 	  }
        if (thislevel_only && ! level->tag_transparent)
  	{
  	  if (level->template_parms_p && allow_template_parms_p)
--- 5670,5692 ----
  	    if (thislevel_only || tail == global_namespace)
  	      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
  	  }
!       else if (level->type_decls != NULL)
!         {
!           binding_entry entry = binding_table_find (level->type_decls, name);
!           if (entry != NULL)
!             {
!               enum tree_code code = TREE_CODE (entry->type);
! 
!               if (code != form
!                   && (form == ENUMERAL_TYPE || code == ENUMERAL_TYPE))
!                 {
!                   /* Definition isn't the kind we were looking for.  */
!                   error ("`%#D' redeclared as %C", entry->type, form);
!                   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
!                 }
!               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->type);
!             }
!         }
        if (thislevel_only && ! level->tag_transparent)
  	{
  	  if (level->template_parms_p && allow_template_parms_p)
*************** lookup_tag_reverse (type, name)
*** 5498,5513 ****
  
    for (level = current_binding_level; level; level = level->level_chain)
      {
!       register tree tail;
!       for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
! 	{
! 	  if (TREE_VALUE (tail) == type)
! 	    {
! 	      if (name)
! 		TREE_PURPOSE (tail) = name;
! 	      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_PURPOSE (tail));
! 	    }
! 	}
      }
    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
  }
--- 5739,5749 ----
  
    for (level = current_binding_level; level; level = level->level_chain)
      {
!       binding_entry entry = level->type_decls == NULL
!         ? NULL
!         : binding_table_reverse_maybe_remap (level->type_decls, type, name);
!       if (entry)
!         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->name);
      }
    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
  }
*************** cxx_init_decl_processing ()
*** 6649,6654 ****
--- 6885,6891 ----
    /* Make the binding_level structure for global names.  */
    pushlevel (0);
    global_binding_level = current_binding_level;
+   global_binding_level->type_decls = binding_table_new (GLOBAL_SCOPE_HT_SIZE);
    /* The global level is the namespace level of ::.  */
    NAMESPACE_LEVEL (global_namespace) = global_binding_level;
    declare_namespace_level ();
*************** store_parm_decls (current_function_parms
*** 14328,14334 ****
  	 function.  This is all and only the PARM_DECLs that were
  	 pushed into scope by the loop above.  */
        DECL_ARGUMENTS (fndecl) = getdecls ();
-       storetags (gettags ());
      }
    else
      DECL_ARGUMENTS (fndecl) = NULL_TREE;
--- 14565,14570 ----
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.635.2.22
diff -p -r1.635.2.22 pt.c
*** cp/pt.c	29 Apr 2003 22:12:49 -0000	1.635.2.22
--- cp/pt.c	10 May 2003 09:10:37 -0000
*************** instantiate_class_template (type)
*** 5266,5272 ****
        TYPE_FIELDS (type) = TYPE_FIELDS (pattern);
        TYPE_METHODS (type) = TYPE_METHODS (pattern);
        CLASSTYPE_DECL_LIST (type) = CLASSTYPE_DECL_LIST (pattern);
!       CLASSTYPE_TAGS (type) = CLASSTYPE_TAGS (pattern);
        CLASSTYPE_VBASECLASSES (type) = CLASSTYPE_VBASECLASSES (pattern);
        
        /* Pretend that the type is complete, so that we will look
--- 5266,5272 ----
        TYPE_FIELDS (type) = TYPE_FIELDS (pattern);
        TYPE_METHODS (type) = TYPE_METHODS (pattern);
        CLASSTYPE_DECL_LIST (type) = CLASSTYPE_DECL_LIST (pattern);
!       CLASSTYPE_NESTED_UDT (type) = CLASSTYPE_NESTED_UDT (pattern);
        CLASSTYPE_VBASECLASSES (type) = CLASSTYPE_VBASECLASSES (pattern);
        
        /* Pretend that the type is complete, so that we will look
*************** instantiate_class_template (type)
*** 5428,5434 ****
  	{
  	  if (TYPE_P (t))
  	    {
! 	      /* Build new CLASSTYPE_TAGS.  */
  
  	      tree tag = t;
  	      tree name = TYPE_IDENTIFIER (tag);
--- 5428,5434 ----
  	{
  	  if (TYPE_P (t))
  	    {
! 	      /* Build new CLASSTYPE_NESTED_UDT.  */
  
  	      tree tag = t;
  	      tree name = TYPE_IDENTIFIER (tag);
*************** instantiate_class_template (type)
*** 5521,5527 ****
  		  /* If it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE,
  		     such a thing will already have been added to the field
  		     list by tsubst_enum in finish_member_declaration in the
! 		     CLASSTYPE_TAGS case above.  */
  		  if (!(TREE_CODE (r) == TYPE_DECL
  			&& TREE_CODE (TREE_TYPE (r)) == ENUMERAL_TYPE
  			&& TYPE_CONTEXT (TREE_TYPE (r)) == type))
--- 5521,5527 ----
  		  /* If it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE,
  		     such a thing will already have been added to the field
  		     list by tsubst_enum in finish_member_declaration in the
! 		     CLASSTYPE_NESTED_UDT case above.  */
  		  if (!(TREE_CODE (r) == TYPE_DECL
  			&& TREE_CODE (TREE_TYPE (r)) == ENUMERAL_TYPE
  			&& TYPE_CONTEXT (TREE_TYPE (r)) == type))
*************** mark_class_instantiated (t, extern_p)
*** 9887,9892 ****
--- 9887,9904 ----
      }
  }     
  
+ /* Called from do_type_instantiation through binding_table_foreach to
+    do recursive instantiation for the type bound in ENTRY.   */
+ static void
+ bt_instantiate_type_proc (binding_entry entry, void *data)
+ {
+   tree storage = *(tree *) data;
+ 
+   if (IS_AGGR_TYPE (entry->type)
+       && !uses_template_parms (CLASSTYPE_TI_ARGS (entry->type)))
+     do_type_instantiation (TYPE_MAIN_DECL (entry->type), storage, 0);
+ }
+ 
  /* Perform an explicit instantiation of template class T.  STORAGE, if
     non-null, is the RID for extern, inline or static.  COMPLAIN is
     nonzero if this is called from the parser, zero if called recursively,
*************** do_type_instantiation (t, storage, compl
*** 10027,10036 ****
  	    instantiate_decl (tmp, /*defer_ok=*/1);
  	}
  
!     for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
!       if (IS_AGGR_TYPE (TREE_VALUE (tmp))
! 	  && !uses_template_parms (CLASSTYPE_TI_ARGS (TREE_VALUE (tmp))))
! 	do_type_instantiation (TYPE_MAIN_DECL (TREE_VALUE (tmp)), storage, 0);
    }
  }
  
--- 10039,10047 ----
  	    instantiate_decl (tmp, /*defer_ok=*/1);
  	}
  
!     if (CLASSTYPE_NESTED_UDT (t))
!       binding_table_foreach (CLASSTYPE_NESTED_UDT (t),
!                              bt_instantiate_type_proc, &storage);
    }
  }
  
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.243.2.7
diff -p -r1.243.2.7 search.c
*** cp/search.c	29 Apr 2003 18:51:57 -0000	1.243.2.7
--- cp/search.c	10 May 2003 09:10:42 -0000
*************** lookup_field_r (binfo, data)
*** 1328,1338 ****
  	}
        else
  	nval = NULL_TREE;
!       if (!nval)
  	{
! 	  nval = purpose_member (lfi->name, CLASSTYPE_TAGS (type));
! 	  if (nval)
! 	    nval = TYPE_MAIN_DECL (TREE_VALUE (nval));
  	  else 
  	    return NULL_TREE;
  	}
--- 1328,1339 ----
  	}
        else
  	nval = NULL_TREE;
!       if (!nval && CLASSTYPE_NESTED_UDT (type) != NULL)
  	{
!           binding_entry e = binding_table_find (CLASSTYPE_NESTED_UDT (type),
!                                                 lfi->name);
! 	  if (e != NULL)
! 	    nval = TYPE_MAIN_DECL (e->type);
  	  else 
  	    return NULL_TREE;
  	}
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.282.4.3
diff -p -r1.282.4.3 semantics.c
*** cp/semantics.c	24 Mar 2003 18:21:44 -0000	1.282.4.3
--- cp/semantics.c	10 May 2003 09:10:46 -0000
*************** begin_class_definition (t)
*** 1755,1761 ****
  	  TYPE_FIELDS (t) = NULL_TREE;
  	  TYPE_METHODS (t) = NULL_TREE;
  	  CLASSTYPE_DECL_LIST (t) = NULL_TREE;
! 	  CLASSTYPE_TAGS (t) = NULL_TREE;
  	  CLASSTYPE_VBASECLASSES (t) = NULL_TREE;
  	  TYPE_SIZE (t) = NULL_TREE;
  	}
--- 1755,1761 ----
  	  TYPE_FIELDS (t) = NULL_TREE;
  	  TYPE_METHODS (t) = NULL_TREE;
  	  CLASSTYPE_DECL_LIST (t) = NULL_TREE;
! 	  CLASSTYPE_NESTED_UDT (t) = NULL;
  	  CLASSTYPE_VBASECLASSES (t) = NULL_TREE;
  	  TYPE_SIZE (t) = NULL_TREE;
  	}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]