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]

C++ PATCH: More compile-time improvement


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"


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