This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: C++ PATCH [3.3] Improve name-lookup time
- From: Gabriel Dos Reis <gdr at integrable-solutions dot net>
- To: gcc at integrable-solutions dot net
- Cc: gcc-patches at gcc dot gnu dot org, mark at codesourcery dot com, austern at apple dot com
- Date: 10 May 2003 11:26:16 +0200
- Subject: Re: C++ PATCH [3.3] Improve name-lookup time
- Organization: Integrable Solutions
- References: <m23ck3b9i8.fsf@dromion.integrable-solutions.net>
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;
}