This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: More compile-time improvement
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 13 Jul 2004 09:27:06 -0700
- Subject: C++ PATCH: More compile-time improvement
- Reply-to: mark at codesourcery dot com
This patch does several things:
* Removes two different quadratic behaviors relating to pushing and
popping class scopes. In the most important, we were doubling the
length of the type_shadowed list every time we entered and exited a
class. In the second, we were doing a quadratic search for names
already entered.
* Removes IDENTIFIER_CLASS_VALUE. This cache was not being used
effectively, and setting it up and tearing it down was very
expensive. We want to make pushclass/popclass go much faster; that
will be my next project. We may also need a cache on lookup_member,
but we can use an LRU cache, rather than IDENTIFIER_CLASS_VALUE. We
may not need the cache at all, since it looks like most calls to
lookup_member come from pushclass...
* Removes push_stack_level/pop_stack_level in search.c, which was
nothing but pointless obstack allocation and deallocation.
Tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2004-07-13 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (lang_identifier): Remove class_value.
(IDENTIFIER_CLASS_VALUE): Remove.
(pop_class_decls): Likewise.
(init_search_processing): Likewise.
* class.c (handle_using_decl): Use lookup_member, not
IDENTIFIER_CLASS_VALUE.
(restore_class_cache): New function, split out from ...
(pushclass): ... here. Do not call clear_identifier_class_values.
(invalidate_class_lookup_cache): Do not clear
IDENTIFIER_CLASS_VALUE.
(popclass): Do not call pop_class_decls.
(maybe_note_name_used_in_class): Do not save names looked up after
the class is complete. Use lookup_member, not
IDENTIFIER_CLASS_VALUE.
* config-lang.in (gtfiles): Add $(srcdir)/cp/search.c.
* decl.c (cxx_init_decl_processing): Do not call
init_search_processing.
* method.c (do_build_copy_constructor): Remove unnecessary code.
(do_build_assign_ref): Likewise.
* name-lookup.c (pushdecl): Use lookup_member, not
IDENTIFIER_CLASS_VALUE.
(set_identifier_type_value_with_scope): Set TREE_TYPE on the
type_shadowed list.
(poplevel_class): Do not restore IDENTIFIER_CLASS_VALUE.
(push_class_binding): Do not set it.
(clear_identifier_class_values): Remove.
(push_class_level_binding): Do not set IDENTIFIER_CLASS_VALUE.
(store_binding): Do not save it.
(pop_from_top_level): Do not restore it.
* name-lookup.h (cxx_saved_binding): Remove class_value.
(clear_identifier_class_values): Remove.
* ptree.c (cxx_print_identifier): Do not print
IDENTIFIER_CLASS_VALUE.
* search.c (search_obstack): Remove.
(push_stack_level): Remove.
(pop_stack_level): Remove.
(search_level): Remove.
(search_stack): Remove.
(lookup_member): Don't check IDENTIFIER_CLASS_VALUE.
(setup_class_bindings): Use IDENTIFIER_MARKED, not
IDENTIFIER_CLASS_VALUE.
(marked_identifiers): New variable.
(push_class_decls): Clear IDENTIFIER_MARKED.
(pop_class_decls): Don't call pop_search_level.
(init_search_processing): Remove.
Index: class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.630
diff -c -5 -p -r1.630 class.c
*** class.c 12 Jul 2004 16:06:21 -0000 1.630
--- class.c 13 Jul 2004 16:01:19 -0000
*************** handle_using_decl (tree using_decl, tree
*** 1128,1138 ****
if (BASELINK_P (fdecl))
/* Ignore base type this came from. */
fdecl = BASELINK_FUNCTIONS (fdecl);
! old_value = IDENTIFIER_CLASS_VALUE (name);
if (old_value)
{
if (is_overloaded_fn (old_value))
old_value = OVL_CURRENT (old_value);
--- 1128,1138 ----
if (BASELINK_P (fdecl))
/* Ignore base type this came from. */
fdecl = BASELINK_FUNCTIONS (fdecl);
! old_value = lookup_member (t, name, /*protect=*/0, /*want_type=*/false);
if (old_value)
{
if (is_overloaded_fn (old_value))
old_value = OVL_CURRENT (old_value);
*************** init_class_processing (void)
*** 5477,5499 ****
ridpointers[(int) RID_PUBLIC] = access_public_node;
ridpointers[(int) RID_PRIVATE] = access_private_node;
ridpointers[(int) RID_PROTECTED] = access_protected_node;
}
/* Set global variables CURRENT_CLASS_NAME and CURRENT_CLASS_TYPE as
appropriate for TYPE.
So that we may avoid calls to lookup_name, we cache the _TYPE
nodes of local TYPE_DECLs in the TREE_TYPE field of the name.
For multiple inheritance, we perform a two-pass depth-first search
! of the type lattice. The first pass performs a pre-order search,
! marking types after the type has had its fields installed in
! the appropriate IDENTIFIER_CLASS_VALUE slot. The second pass merely
! unmarks the marked types. If a field or member function name
! appears in an ambiguous way, the IDENTIFIER_CLASS_VALUE of
! that name becomes `error_mark_node'. */
void
pushclass (tree type)
{
type = TYPE_MAIN_VARIANT (type);
--- 5477,5528 ----
ridpointers[(int) RID_PUBLIC] = access_public_node;
ridpointers[(int) RID_PRIVATE] = access_private_node;
ridpointers[(int) RID_PROTECTED] = access_protected_node;
}
+ /* Restore the cached PREVIOUS_CLASS_LEVEL. */
+
+ static void
+ restore_class_cache (void)
+ {
+ cp_class_binding *cb;
+ tree type;
+ size_t i;
+
+ /* We are re-entering the same class we just left, so we don't
+ have to search the whole inheritance matrix to find all the
+ decls to bind again. Instead, we install the cached
+ class_shadowed list and walk through it binding names. */
+ push_binding_level (previous_class_level);
+ class_binding_level = previous_class_level;
+ for (i = 0;
+ (cb = VEC_iterate (cp_class_binding,
+ previous_class_level->class_shadowed,
+ i));
+ ++i)
+ {
+ tree id;
+
+ id = cb->identifier;
+ cb->base.previous = IDENTIFIER_BINDING (id);
+ IDENTIFIER_BINDING (id) = &cb->base;
+ }
+ /* Restore IDENTIFIER_TYPE_VALUE. */
+ for (type = class_binding_level->type_shadowed;
+ type;
+ type = TREE_CHAIN (type))
+ SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (type), TREE_TYPE (type));
+ }
+
/* Set global variables CURRENT_CLASS_NAME and CURRENT_CLASS_TYPE as
appropriate for TYPE.
So that we may avoid calls to lookup_name, we cache the _TYPE
nodes of local TYPE_DECLs in the TREE_TYPE field of the name.
For multiple inheritance, we perform a two-pass depth-first search
! of the type lattice. */
void
pushclass (tree type)
{
type = TYPE_MAIN_VARIANT (type);
*************** pushclass (tree type)
*** 5533,5547 ****
{
/* Forcibly remove any old class remnants. */
invalidate_class_lookup_cache ();
}
- /* If we're about to enter a nested class, clear
- IDENTIFIER_CLASS_VALUE for the enclosing classes. */
- if (current_class_depth > 1)
- clear_identifier_class_values ();
-
if (!previous_class_level
|| type != previous_class_level->this_entity
|| current_class_depth > 1)
{
pushlevel_class ();
--- 5562,5571 ----
*************** pushclass (tree type)
*** 5558,5630 ****
if (TREE_CODE (fields) == USING_DECL && !TREE_TYPE (fields))
pushdecl_class_level (fields);
}
}
else
! {
! cp_class_binding *cb;
! size_t i;
!
! /* We are re-entering the same class we just left, so we don't
! have to search the whole inheritance matrix to find all the
! decls to bind again. Instead, we install the cached
! class_shadowed list, and walk through it binding names and
! setting up IDENTIFIER_TYPE_VALUEs. */
! push_binding_level (previous_class_level);
! class_binding_level = previous_class_level;
! for (i = 0;
! (cb = VEC_iterate (cp_class_binding,
! previous_class_level->class_shadowed,
! i));
! ++i)
! {
! tree id;
! tree type_decl;
!
! id = cb->identifier;
! cb->base.previous = IDENTIFIER_BINDING (id);
! IDENTIFIER_BINDING (id) = &cb->base;
! type_decl = cb->base.value;
! if (!type_decl || TREE_CODE (type_decl) != TYPE_DECL)
! type_decl = cb->base.type;
! if (type_decl && TREE_CODE (type_decl) == TYPE_DECL)
! set_identifier_type_value (id, type_decl);
! }
! }
cxx_remember_type_decls (CLASSTYPE_NESTED_UTDS (type));
}
! /* When we exit a toplevel class scope, we save the
! IDENTIFIER_CLASS_VALUEs so that we can restore them quickly if we
! reenter the class. Here, we've entered some other class, so we
! must invalidate our cache. */
void
invalidate_class_lookup_cache (void)
{
- size_t i;
- cp_class_binding *cb;
-
- /* The IDENTIFIER_CLASS_VALUEs are no longer valid. */
- for (i = 0;
- (cb = VEC_iterate (cp_class_binding,
- previous_class_level->class_shadowed, i));
- ++i)
- IDENTIFIER_CLASS_VALUE (cb->identifier) = NULL_TREE;
-
previous_class_level = NULL;
}
/* Get out of the current class scope. If we were in a class scope
previously, that is the one popped to. */
void
popclass (void)
{
poplevel_class ();
- pop_class_decls ();
current_class_depth--;
current_class_name = current_class_stack[current_class_depth].name;
current_class_type = current_class_stack[current_class_depth].type;
current_access_specifier = current_class_stack[current_class_depth].access;
--- 5582,5613 ----
if (TREE_CODE (fields) == USING_DECL && !TREE_TYPE (fields))
pushdecl_class_level (fields);
}
}
else
! restore_class_cache ();
cxx_remember_type_decls (CLASSTYPE_NESTED_UTDS (type));
}
! /* When we exit a toplevel class scope, we save its binding level so
! that we can restore it quickly. Here, we've entered some other
! class, so we must invalidate our cache. */
void
invalidate_class_lookup_cache (void)
{
previous_class_level = NULL;
}
/* Get out of the current class scope. If we were in a class scope
previously, that is the one popped to. */
void
popclass (void)
{
poplevel_class ();
current_class_depth--;
current_class_name = current_class_stack[current_class_depth].name;
current_class_type = current_class_stack[current_class_depth].type;
current_access_specifier = current_class_stack[current_class_depth].access;
*************** void
*** 6446,6461 ****
maybe_note_name_used_in_class (tree name, tree decl)
{
splay_tree names_used;
/* If we're not defining a class, there's nothing to do. */
! if (innermost_scope_kind() != sk_class)
return;
/* If there's already a binding for this NAME, then we don't have
anything to worry about. */
! if (IDENTIFIER_CLASS_VALUE (name))
return;
if (!current_class_stack[current_class_depth - 1].names_used)
current_class_stack[current_class_depth - 1].names_used
= splay_tree_new (splay_tree_compare_pointers, 0, 0);
--- 6429,6446 ----
maybe_note_name_used_in_class (tree name, tree decl)
{
splay_tree names_used;
/* If we're not defining a class, there's nothing to do. */
! if (!(innermost_scope_kind() == sk_class
! && TYPE_BEING_DEFINED (current_class_type)))
return;
/* If there's already a binding for this NAME, then we don't have
anything to worry about. */
! if (lookup_member (current_class_type, name,
! /*protect=*/0, /*want_type=*/false))
return;
if (!current_class_stack[current_class_depth - 1].names_used)
current_class_stack[current_class_depth - 1].names_used
= splay_tree_new (splay_tree_compare_pointers, 0, 0);
Index: config-lang.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/config-lang.in,v
retrieving revision 1.23
diff -c -5 -p -r1.23 config-lang.in
*** config-lang.in 12 Jul 2004 10:07:26 -0000 1.23
--- config-lang.in 13 Jul 2004 16:01:19 -0000
*************** compilers="cc1plus\$(exeext)"
*** 32,37 ****
stagestuff="g++\$(exeext) g++-cross\$(exeext) cc1plus\$(exeext)"
target_libs="target-libstdc++-v3 target-gperf"
! gtfiles="\$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-lex.c \$(srcdir)/c-pragma.c"
--- 32,37 ----
stagestuff="g++\$(exeext) g++-cross\$(exeext) cc1plus\$(exeext)"
target_libs="target-libstdc++-v3 target-gperf"
! gtfiles="\$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/search.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/cp/typeck2.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-lex.c \$(srcdir)/c-pragma.c"
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1004
diff -c -5 -p -r1.1004 cp-tree.h
*** cp-tree.h 12 Jul 2004 23:53:13 -0000 1.1004
--- cp-tree.h 13 Jul 2004 16:01:19 -0000
*************** struct diagnostic_context;
*** 168,178 ****
struct lang_identifier GTY(())
{
struct c_common_identifier c_common;
cxx_binding *namespace_bindings;
cxx_binding *bindings;
- tree class_value;
tree class_template_info;
tree label_value;
};
/* In an IDENTIFIER_NODE, nonzero if this identifier is actually a
--- 168,177 ----
*************** typedef enum cp_id_kind
*** 338,355 ****
/* The IDENTIFIER_VALUE is the value of the IDENTIFIER_BINDING, or
NULL_TREE if there is no binding. */
#define IDENTIFIER_VALUE(NODE) \
(IDENTIFIER_BINDING (NODE) ? IDENTIFIER_BINDING (NODE)->value : NULL)
- /* If IDENTIFIER_CLASS_VALUE is set, then NODE is bound in the current
- class, and IDENTIFIER_CLASS_VALUE is the value binding. This is
- just a pointer to the VALUE field of one of the bindings in the
- IDENTIFIER_BINDINGs list, so any time that this is non-NULL so is
- IDENTIFIER_BINDING. */
- #define IDENTIFIER_CLASS_VALUE(NODE) \
- (LANG_IDENTIFIER_CAST (NODE)->class_value)
-
/* TREE_TYPE only indicates on local and class scope the current
type. For namespace scope, the presence of a type in any namespace
is indicated with global_type_node, and the real type behind must
be found through lookup. */
#define IDENTIFIER_TYPE_VALUE(NODE) identifier_type_value (NODE)
--- 337,346 ----
*************** extern tree lookup_member (tree, tree,
*** 4011,4023 ****
extern int look_for_overrides (tree, tree);
extern void get_pure_virtuals (tree);
extern void maybe_suppress_debug_info (tree);
extern void note_debug_info_needed (tree);
extern void push_class_decls (tree);
- extern void pop_class_decls (void);
extern void print_search_statistics (void);
- extern void init_search_processing (void);
extern void reinit_search_statistics (void);
extern tree current_scope (void);
extern int at_function_scope_p (void);
extern bool at_class_scope_p (void);
extern bool at_namespace_scope_p (void);
--- 4002,4012 ----
Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1246
diff -c -5 -p -r1.1246 decl.c
*** decl.c 12 Jul 2004 17:54:47 -0000 1.1246
--- decl.c 13 Jul 2004 16:01:19 -0000
*************** cxx_init_decl_processing (void)
*** 3045,3055 ****
abort_fndecl
= build_library_fn_ptr ("__cxa_pure_virtual", void_ftype);
/* Perform other language dependent initializations. */
init_class_processing ();
- init_search_processing ();
init_rtti_processing ();
if (flag_exceptions)
init_exception_processing ();
--- 3045,3054 ----
Index: method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.295
diff -c -5 -p -r1.295 method.c
*** method.c 7 Jul 2004 10:20:35 -0000 1.295
--- method.c 13 Jul 2004 16:01:19 -0000
*************** do_build_copy_constructor (tree fndecl)
*** 565,578 ****
init = parm;
if (DECL_NAME (field))
{
if (VFIELD_NAME_P (DECL_NAME (field)))
continue;
-
- /* True for duplicate members. */
- if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field)
- continue;
}
else if ((t = TREE_TYPE (field)) != NULL_TREE
&& ANON_AGGR_TYPE_P (t)
&& TYPE_FIELDS (t) != NULL_TREE)
/* Just use the field; anonymous types can't have
--- 565,574 ----
*************** do_build_assign_ref (tree fndecl)
*** 671,684 ****
if (DECL_NAME (field))
{
if (VFIELD_NAME_P (DECL_NAME (field)))
continue;
-
- /* True for duplicate members. */
- if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field)
- continue;
}
else if ((t = TREE_TYPE (field)) != NULL_TREE
&& ANON_AGGR_TYPE_P (t)
&& TYPE_FIELDS (t) != NULL_TREE)
/* Just use the field; anonymous types can't have
--- 667,676 ----
Index: name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.72
diff -c -5 -p -r1.72 name-lookup.c
*** name-lookup.c 12 Jul 2004 22:53:47 -0000 1.72
--- name-lookup.c 13 Jul 2004 16:01:20 -0000
*************** pushdecl (tree x)
*** 995,1007 ****
/* No shadow warnings for internally generated vars. */
&& ! DECL_ARTIFICIAL (x)
/* No shadow warnings for vars made for inlining. */
&& ! DECL_FROM_INLINE (x))
{
! if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE
! && current_class_ptr
! && !TREE_STATIC (name))
{
/* Location of previous decl is not useful in this case. */
warning ("declaration of '%D' shadows a member of 'this'",
x);
}
--- 995,1015 ----
/* No shadow warnings for internally generated vars. */
&& ! DECL_ARTIFICIAL (x)
/* No shadow warnings for vars made for inlining. */
&& ! DECL_FROM_INLINE (x))
{
! tree member;
!
! if (current_class_ptr)
! member = lookup_member (current_class_type,
! name,
! /*protect=*/0,
! /*want_type=*/false);
! else
! member = NULL_TREE;
!
! if (member && !TREE_STATIC (member))
{
/* Location of previous decl is not useful in this case. */
warning ("declaration of '%D' shadows a member of 'this'",
x);
}
*************** set_identifier_type_value_with_scope (tr
*** 1775,1784 ****
--- 1783,1793 ----
gets restored later. */
tree old_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
b->type_shadowed
= tree_cons (id, old_type_value, b->type_shadowed);
type = decl ? TREE_TYPE (decl) : NULL_TREE;
+ TREE_TYPE (b->type_shadowed) = type;
}
else
{
cxx_binding *binding =
binding_for_name (NAMESPACE_LEVEL (current_namespace), id);
*************** poplevel_class (void)
*** 2627,2676 ****
tree shadowed;
timevar_push (TV_NAME_LOOKUP);
my_friendly_assert (level != 0, 354);
! /* If we're leaving a toplevel class, don't bother to do the setting
! of IDENTIFIER_CLASS_VALUE to NULL_TREE, since first of all this slot
! shouldn't even be used when current_class_type isn't set, and second,
! if we don't touch it here, we're able to use the cache effect if the
! next time we're entering a class scope, it is the same class. */
! if (current_class_depth != 1)
! {
! struct cp_binding_level* b;
! cp_class_binding* cb;
! size_t i;
!
! /* Clear out our IDENTIFIER_CLASS_VALUEs. */
! clear_identifier_class_values ();
!
! /* Find the next enclosing class, and recreate
! IDENTIFIER_CLASS_VALUEs appropriate for that class. */
! b = level->level_chain;
! while (b && b->kind != sk_class)
! b = b->level_chain;
!
! if (b)
! for (i = 0;
! (cb = VEC_iterate (cp_class_binding,
! b->class_shadowed,
! i));
! ++i)
! {
! cxx_binding *binding;
!
! binding = IDENTIFIER_BINDING (cb->identifier);
! while (binding && binding->scope != b)
! binding = binding->previous;
!
! if (binding)
! IDENTIFIER_CLASS_VALUE (cb->identifier) = binding->value;
! }
! }
! else
! /* Remember to save what IDENTIFIER's were bound in this scope so we
! can recover from cache misses. */
previous_class_level = level;
for (shadowed = level->type_shadowed;
shadowed;
shadowed = TREE_CHAIN (shadowed))
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed), TREE_VALUE (shadowed));
--- 2636,2647 ----
tree shadowed;
timevar_push (TV_NAME_LOOKUP);
my_friendly_assert (level != 0, 354);
! /* If we're leaving a toplevel class, cache its binding level. */
! if (current_class_depth == 1)
previous_class_level = level;
for (shadowed = level->type_shadowed;
shadowed;
shadowed = TREE_CHAIN (shadowed))
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed), TREE_VALUE (shadowed));
*************** push_class_binding (tree id, tree decl)
*** 2711,2727 ****
result = supplement_binding (IDENTIFIER_BINDING (id), decl);
else
/* Create a new binding. */
push_binding (id, decl, class_binding_level);
- /* Update the IDENTIFIER_CLASS_VALUE for this ID to be the
- class-level declaration. Note that we do not use DECL here
- because of the possibility of the `struct stat' hack; if DECL is
- a class-name or enum-name we might prefer a field-name, or some
- such. */
- IDENTIFIER_CLASS_VALUE (id) = IDENTIFIER_BINDING (id)->value;
-
/* If this is a binding from a base class, mark it as such. */
binding = IDENTIFIER_BINDING (id);
if (binding->value == decl && TREE_CODE (decl) != TREE_LIST)
{
if (TREE_CODE (decl) == OVERLOAD)
--- 2682,2691 ----
*************** push_class_binding (tree id, tree decl)
*** 2744,2771 ****
INHERITED_VALUE_BINDING_P (binding) = 1;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result);
}
- /* We are entering the scope of a class. Clear IDENTIFIER_CLASS_VALUE
- for any names in enclosing classes. */
-
- void
- clear_identifier_class_values (void)
- {
- size_t i;
- cp_class_binding *cb;
-
- if (class_binding_level)
- for (i = 0;
- (cb = VEC_iterate (cp_class_binding,
- class_binding_level->class_shadowed,
- i));
- ++i)
- IDENTIFIER_CLASS_VALUE (cb->identifier) = NULL_TREE;
- }
-
/* Make the declaration of X appear in CLASS scope. */
bool
pushdecl_class_level (tree x)
{
--- 2708,2717 ----
*************** push_class_level_binding (tree name, tre
*** 2819,2831 ****
parameter name in a member template. */
if (!class_binding_level)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
/* Check for invalid member names, if the class is being defined.
! This function is also used to restore IDENTIFIER_CLASS_VALUE,
! when reentering the class scope, and there is no point in
! checking again at that time. */
if (TYPE_BEING_DEFINED (current_class_type))
{
tree decl = x;
/* We could have been passed a tree list if this is an ambiguous
--- 2765,2777 ----
parameter name in a member template. */
if (!class_binding_level)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
/* Check for invalid member names, if the class is being defined.
! This function is also used to restore bindings when reentering
! the class scope, and there is no point in checking again at that
! time. */
if (TYPE_BEING_DEFINED (current_class_type))
{
tree decl = x;
/* We could have been passed a tree list if this is an ambiguous
*************** push_class_level_binding (tree name, tre
*** 2873,2884 ****
}
}
}
/* If this declaration shadows a declaration from an enclosing
! class, then we will need to restore IDENTIFIER_CLASS_VALUE when
! we leave this class. Record the shadowed declaration here. */
binding = IDENTIFIER_BINDING (name);
if (binding && binding->value)
{
tree bval = binding->value;
tree old_decl = NULL_TREE;
--- 2819,2830 ----
}
}
}
/* If this declaration shadows a declaration from an enclosing
! class, then we will need to restore bindings when we leave this
! class. Record the shadowed declaration here. */
binding = IDENTIFIER_BINDING (name);
if (binding && binding->value)
{
tree bval = binding->value;
tree old_decl = NULL_TREE;
*************** push_class_level_binding (tree name, tre
*** 2920,2930 ****
every name declared in the class and its base classes.
So, if we see a second binding for this name, it must be
coming from a definition in the body of the class
itself. */
INHERITED_VALUE_BINDING_P (binding) = 0;
- IDENTIFIER_CLASS_VALUE (name) = x;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
}
}
/* If we didn't replace an existing binding, put the binding on the
--- 2866,2875 ----
*************** qualified_lookup_using_namespace (tree n
*** 3992,4006 ****
If PREFER_TYPE is > 0, we prefer TYPE_DECLs or namespaces.
If PREFER_TYPE is > 1, we reject non-type decls (e.g. namespaces).
Otherwise we prefer non-TYPE_DECLs.
! If NONCLASS is nonzero, we don't look for the NAME in class scope,
! using IDENTIFIER_CLASS_VALUE.
!
! If BLOCK_P is true, block scopes are examined; otherwise, they are
! skipped. */
tree
lookup_name_real (tree name, int prefer_type, int nonclass, bool block_p,
int namespaces_only, int flags)
{
--- 3937,3948 ----
If PREFER_TYPE is > 0, we prefer TYPE_DECLs or namespaces.
If PREFER_TYPE is > 1, we reject non-type decls (e.g. namespaces).
Otherwise we prefer non-TYPE_DECLs.
! If NONCLASS is nonzero, bindings in class scopes are ignored. If
! BLOCK_P is false, bindings in block scopes are ignored. */
tree
lookup_name_real (tree name, int prefer_type, int nonclass, bool block_p,
int namespaces_only, int flags)
{
*************** struct saved_scope *scope_chain;
*** 4829,4857 ****
static void
store_binding (tree id, VEC(cxx_saved_binding) **old_bindings)
{
cxx_saved_binding *saved;
! if (!id
! /* Note that we may have an IDENTIFIER_CLASS_VALUE even when
! we have no IDENTIFIER_BINDING if we have left the class
! scope, but cached the class-level declarations. */
! || !(IDENTIFIER_BINDING (id) || IDENTIFIER_CLASS_VALUE (id)))
return;
if (IDENTIFIER_MARKED (id))
return;
IDENTIFIER_MARKED (id) = 1;
saved = VEC_safe_push (cxx_saved_binding, *old_bindings, NULL);
saved->identifier = id;
saved->binding = IDENTIFIER_BINDING (id);
- saved->class_value = IDENTIFIER_CLASS_VALUE (id);;
saved->real_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
IDENTIFIER_BINDING (id) = NULL;
- IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
}
static void
store_bindings (tree names, VEC(cxx_saved_binding) **old_bindings)
{
--- 4771,4793 ----
static void
store_binding (tree id, VEC(cxx_saved_binding) **old_bindings)
{
cxx_saved_binding *saved;
! if (!id || !IDENTIFIER_BINDING (id))
return;
if (IDENTIFIER_MARKED (id))
return;
IDENTIFIER_MARKED (id) = 1;
saved = VEC_safe_push (cxx_saved_binding, *old_bindings, NULL);
saved->identifier = id;
saved->binding = IDENTIFIER_BINDING (id);
saved->real_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
IDENTIFIER_BINDING (id) = NULL;
}
static void
store_bindings (tree names, VEC(cxx_saved_binding) **old_bindings)
{
*************** pop_from_top_level (void)
*** 4979,4989 ****
++i)
{
tree id = saved->identifier;
IDENTIFIER_BINDING (id) = saved->binding;
- IDENTIFIER_CLASS_VALUE (id) = saved->class_value;
SET_IDENTIFIER_TYPE_VALUE (id, saved->real_type_value);
}
/* If we were in the middle of compiling a function, restore our
state. */
--- 4915,4924 ----
Index: name-lookup.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.h,v
retrieving revision 1.25
diff -c -5 -p -r1.25 name-lookup.h
*** name-lookup.h 12 Jul 2004 01:33:47 -0000 1.25
--- name-lookup.h 13 Jul 2004 16:01:20 -0000
*************** typedef struct cxx_saved_binding GTY(())
*** 86,105 ****
{
/* The name of the current binding. */
tree identifier;
/* The binding we're saving. */
cxx_binding *binding;
- tree class_value;
tree real_type_value;
} cxx_saved_binding;
DEF_VEC_O(cxx_saved_binding);
extern tree identifier_type_value (tree);
extern void set_identifier_type_value (tree, tree);
extern void pop_binding (tree, tree);
- extern void clear_identifier_class_values (void);
extern tree constructor_name_full (tree);
extern tree constructor_name (tree);
extern bool constructor_name_p (tree, tree);
/* The kinds of scopes we recognize. */
--- 86,103 ----
Index: ptree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/ptree.c,v
retrieving revision 1.42
diff -c -5 -p -r1.42 ptree.c
*** ptree.c 12 Jul 2004 16:06:35 -0000 1.42
--- ptree.c 13 Jul 2004 16:01:20 -0000
*************** cxx_print_binding (FILE *stream, cxx_bin
*** 155,165 ****
void
cxx_print_identifier (FILE *file, tree node, int indent)
{
indent_to (file, indent);
cxx_print_binding (file, IDENTIFIER_NAMESPACE_BINDINGS (node), "bindings");
- print_node (file, "class", IDENTIFIER_CLASS_VALUE (node), indent + 4);
indent_to (file, indent);
cxx_print_binding (file, IDENTIFIER_BINDING (node), "local bindings");
print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4);
}
--- 155,164 ----
Index: search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.298
diff -c -5 -p -r1.298 search.c
*** search.c 12 Jul 2004 16:06:36 -0000 1.298
--- search.c 13 Jul 2004 16:01:20 -0000
*************** Boston, MA 02111-1307, USA. */
*** 34,76 ****
#include "rtl.h"
#include "output.h"
#include "toplev.h"
#include "stack.h"
- /* Obstack used for remembering decision points of breadth-first. */
-
- static struct obstack search_obstack;
-
- /* Methods for pushing and popping objects to and from obstacks. */
-
- struct stack_level *
- push_stack_level (struct obstack *obstack, char *tp,/* Sony NewsOS 5.0 compiler doesn't like void * here. */
- int size)
- {
- struct stack_level *stack;
- obstack_grow (obstack, tp, size);
- stack = (struct stack_level *) ((char*)obstack_next_free (obstack) - size);
- obstack_finish (obstack);
- stack->obstack = obstack;
- stack->first = (tree *) obstack_base (obstack);
- stack->limit = obstack_room (obstack) / sizeof (tree *);
- return stack;
- }
-
- struct stack_level *
- pop_stack_level (struct stack_level *stack)
- {
- struct stack_level *tem = stack;
- struct obstack *obstack = tem->obstack;
- stack = tem->prev;
- obstack_free (obstack, tem);
- return stack;
- }
-
- #define search_level stack_level
- static struct search_level *search_stack;
-
struct vbase_info
{
/* The class dominating the hierarchy. */
tree type;
/* A pointer to a complete object of the indicated TYPE. */
--- 34,43 ----
*************** static tree dfs_debug_unmarkedp (tree, i
*** 88,100 ****
static tree dfs_debug_mark (tree, void *);
static tree dfs_push_type_decls (tree, void *);
static tree dfs_push_decls (tree, void *);
static tree add_conversions (tree, void *);
static int look_for_overrides_r (tree, tree);
- static struct search_level *push_search_level (struct stack_level *,
- struct obstack *);
- static struct search_level *pop_search_level (struct stack_level *);
static tree bfs_walk (tree, tree (*) (tree, void *),
tree (*) (tree, int, void *), void *);
static tree lookup_field_queue_p (tree, int, void *);
static int shared_member_p (tree);
static tree lookup_field_r (tree, void *);
--- 55,64 ----
*************** static int protected_accessible_p (tree,
*** 106,135 ****
static int friend_accessible_p (tree, tree, tree);
static void setup_class_bindings (tree, int);
static int template_self_reference_p (tree, tree);
static tree dfs_get_pure_virtuals (tree, void *);
- /* Allocate a level of searching. */
-
- static struct search_level *
- push_search_level (struct stack_level *stack, struct obstack *obstack)
- {
- struct search_level tem;
-
- tem.prev = stack;
- return push_stack_level (obstack, (char *)&tem, sizeof (tem));
- }
-
- /* Discard a level of search allocation. */
-
- static struct search_level *
- pop_search_level (struct stack_level *obstack)
- {
- struct search_level *stack = pop_stack_level (obstack);
-
- return stack;
- }
/* Variables for gathering statistics. */
#ifdef GATHER_STATISTICS
static int n_fields_searched;
static int n_calls_lookup_field, n_calls_lookup_field_1;
--- 70,79 ----
*************** lookup_member (tree xbasetype, tree name
*** 1261,1281 ****
my_friendly_assert (IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype)), 20030624);
type = xbasetype;
xbasetype = NULL_TREE;
}
- if (type == current_class_type && TYPE_BEING_DEFINED (type)
- && IDENTIFIER_CLASS_VALUE (name))
- {
- tree field = IDENTIFIER_CLASS_VALUE (name);
- if (! is_overloaded_fn (field)
- && ! (want_type && TREE_CODE (field) != TYPE_DECL))
- /* We're in the scope of this class, and the value has already
- been looked up. Just return the cached value. */
- return field;
- }
-
type = complete_type (type);
if (!basetype_path)
basetype_path = TYPE_BINFO (type);
if (!basetype_path)
--- 1205,1214 ----
*************** note_debug_info_needed (tree type)
*** 2097,2119 ****
}
dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp, 0);
}
/* Subroutines of push_class_decls (). */
static void
setup_class_bindings (tree name, int type_binding_p)
{
tree type_binding = NULL_TREE;
tree value_binding;
/* If we've already done the lookup for this declaration, we're
done. */
! if (IDENTIFIER_CLASS_VALUE (name))
return;
/* First, deal with the type binding. */
if (type_binding_p)
{
type_binding = lookup_member (current_class_type, name,
/*protect=*/2, /*want_type=*/true);
--- 2030,2060 ----
}
dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp, 0);
}
+ /* A vector of IDENTIFIER_NODEs that have been processed by
+ setup_class_bindings. */
+
+ static GTY(()) VEC(tree) *marked_identifiers;
+
/* Subroutines of push_class_decls (). */
static void
setup_class_bindings (tree name, int type_binding_p)
{
tree type_binding = NULL_TREE;
tree value_binding;
/* If we've already done the lookup for this declaration, we're
done. */
! if (IDENTIFIER_MARKED (name))
return;
+ IDENTIFIER_MARKED (name) = 1;
+ VEC_safe_push (tree, marked_identifiers, name);
+
/* First, deal with the type binding. */
if (type_binding_p)
{
type_binding = lookup_member (current_class_type, name,
/*protect=*/2, /*want_type=*/true);
*************** setup_class_bindings (tree name, int typ
*** 2159,2170 ****
if (IDENTIFIER_TYPENAME_P (name)
&& is_overloaded_fn (value_binding))
{
tree fns;
for (fns = value_binding; fns; fns = OVL_NEXT (fns))
! if (IDENTIFIER_CLASS_VALUE (DECL_NAME (OVL_CURRENT (fns))))
! return;
}
pushdecl_class_level (value_binding);
}
}
}
--- 2100,2116 ----
if (IDENTIFIER_TYPENAME_P (name)
&& is_overloaded_fn (value_binding))
{
tree fns;
for (fns = value_binding; fns; fns = OVL_NEXT (fns))
! {
! tree name = DECL_NAME (OVL_CURRENT (fns));
! if (IDENTIFIER_MARKED (name))
! return;
! IDENTIFIER_MARKED (name) = 1;
! VEC_safe_push (tree, marked_identifiers, name);
! }
}
pushdecl_class_level (value_binding);
}
}
}
*************** dfs_push_decls (tree binfo, void *data)
*** 2243,2253 ****
message. */
void
push_class_decls (tree type)
{
! search_stack = push_search_level (search_stack, &search_obstack);
if (!TYPE_BINFO (type))
/* This occurs when parsing an invalid declarator id where the
scope is incomplete. */
return;
--- 2189,2200 ----
message. */
void
push_class_decls (tree type)
{
! tree id;
! size_t i;
if (!TYPE_BINFO (type))
/* This occurs when parsing an invalid declarator id where the
scope is incomplete. */
return;
*************** push_class_decls (tree type)
*** 2255,2273 ****
/* Enter type declarations and mark. */
dfs_walk (TYPE_BINFO (type), dfs_push_type_decls, unmarked_pushdecls_p, 0);
/* Enter non-type declarations and unmark. */
dfs_walk (TYPE_BINFO (type), dfs_push_decls, marked_pushdecls_p, 0);
- }
! void
! pop_class_decls (void)
! {
! /* We haven't pushed a search level when dealing with cached classes,
! so we'd better not try to pop it. */
! if (search_stack)
! search_stack = pop_search_level (search_stack);
}
void
print_search_statistics (void)
{
--- 2202,2219 ----
/* Enter type declarations and mark. */
dfs_walk (TYPE_BINFO (type), dfs_push_type_decls, unmarked_pushdecls_p, 0);
/* Enter non-type declarations and unmark. */
dfs_walk (TYPE_BINFO (type), dfs_push_decls, marked_pushdecls_p, 0);
! /* Clear the IDENTIFIER_MARKED bits. */
! for (i = 0;
! (id = VEC_iterate (tree, marked_identifiers, i));
! ++i)
! IDENTIFIER_MARKED (id) = 0;
! if (marked_identifiers)
! VEC_truncate (tree, marked_identifiers, 0);
}
void
print_search_statistics (void)
{
*************** print_search_statistics (void)
*** 2281,2296 ****
fprintf (stderr, "no search statistics\n");
#endif /* GATHER_STATISTICS */
}
void
- init_search_processing (void)
- {
- gcc_obstack_init (&search_obstack);
- }
-
- void
reinit_search_statistics (void)
{
#ifdef GATHER_STATISTICS
n_fields_searched = 0;
n_calls_lookup_field = 0, n_calls_lookup_field_1 = 0;
--- 2227,2236 ----
*************** original_binfo (tree binfo, tree here)
*** 2591,2595 ****
--- 2531,2536 ----
}
return result;
}
+ #include "gt-cp-search.h"