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: Compile-time improvements and default arguments


This patch improves compile-time performance by:

* eliminating quadratic behavior in store_binding

* reducing the number of calls to push_nested_class/pop_nested_class

* removing unuse_fields, which did nothing but move useful stuff out
  of the cache.

Entering and exiting class scopes is one of the major hot spots in the
test cases I'm investigating at the momemnt; even after this patch,
there is still plenty more to do there.

In the process, I also fixed a problem with default argument
processing; for a non-member friend, we were not using the correct
scope for processing the default argument expressions.

Tested on i686-pc-linux-gnu, applied on the mainline.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2004-07-11  Mark Mitchell  <mark@codesourcery.com>

	* cp-tree.h (saved_scope): Make old_bindings a vector.
	(unuse_fields): Remove.
	* name-lookup.h (cxx_saved_binding): Define it.
	* class.c (pushclass): Don't use unuse_fields.
	* name-lookup.c (cxx_saved_binding_make): Remove.
	(store_binding): Add new bindings to a vector, using an
	accumulator style, rather than adding them to a list.
	(store_bindings): Adjust accordingly.
	(store_class_bindings): Likewise.
	(push_to_top_level): Likewise.
	(pop_from_top_level): Likewise.
	* optimize.c (maybe_clone_body): Must push_to_top_level and
	pop_from_top_level calls outside of loop.
	* parser.c (cp_parser_class_specifier): Move push_scope/pop_scope
	calls here from cp_parser_late_parsing_default_args.
	(cp_parser_save_default_args): Record the class type in which the
	function is declared.
	(cp_parser_late_parsing_default_args): Do not call
	push_nested_class/pop_nested_class.
	* search.c (dfs_unuse_fields): Remove.
	(unuse_fields): Remove.

2004-07-11  Mark Mitchell  <mark@codesourcery.com>

	* g++.dg/parse/defarg8.C: New test.

Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.626
diff -c -5 -p -r1.626 class.c
*** cp/class.c	8 Jul 2004 04:32:27 -0000	1.626
--- cp/class.c	11 Jul 2004 20:34:06 -0000
*************** pushclass (tree type)
*** 5546,5556 ****
  	  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);
  	}
-       unuse_fields (type);
      }
    
    cxx_remember_type_decls (CLASSTYPE_NESTED_UTDS (type));
  }
  
--- 5546,5555 ----
*************** push_nested_class (tree type)
*** 5652,5662 ****
        || TREE_CODE (type) == NAMESPACE_DECL
        || ! IS_AGGR_TYPE (type)
        || TREE_CODE (type) == TEMPLATE_TYPE_PARM
        || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
      return;
!   
    context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
  
    if (context && CLASS_TYPE_P (context))
      push_nested_class (context);
    pushclass (type);
--- 5651,5661 ----
        || TREE_CODE (type) == NAMESPACE_DECL
        || ! IS_AGGR_TYPE (type)
        || TREE_CODE (type) == TEMPLATE_TYPE_PARM
        || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
      return;
! 
    context = DECL_CONTEXT (TYPE_MAIN_DECL (type));
  
    if (context && CLASS_TYPE_P (context))
      push_nested_class (context);
    pushclass (type);
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.998
diff -c -5 -p -r1.998 cp-tree.h
*** cp/cp-tree.h	8 Jul 2004 04:32:27 -0000	1.998
--- cp/cp-tree.h	11 Jul 2004 20:34:06 -0000
*************** extern GTY(()) tree cp_global_trees[CPTI
*** 628,638 ****
  
  /* Global state.  */
  
  struct saved_scope GTY(())
  {
!   cxx_saved_binding *old_bindings;
    tree old_namespace;
    tree decl_ns_list;
    tree class_name;
    tree class_type;
    tree access_specifier;
--- 628,638 ----
  
  /* Global state.  */
  
  struct saved_scope GTY(())
  {
!   VEC(cxx_saved_binding) *old_bindings;
    tree old_namespace;
    tree decl_ns_list;
    tree class_name;
    tree class_type;
    tree access_specifier;
*************** extern int look_for_overrides			(tree, t
*** 4014,4024 ****
  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 unuse_fields			(tree);
  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);
--- 4014,4023 ----
Index: cp/name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.67
diff -c -5 -p -r1.67 name-lookup.c
*** cp/name-lookup.c	8 Jul 2004 04:32:27 -0000	1.67
--- cp/name-lookup.c	11 Jul 2004 20:34:06 -0000
*************** pushtag (tree name, tree type, int globa
*** 4807,4879 ****
        TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b);
      }
    timevar_pop (TV_NAME_LOOKUP);
  }
  
- /* Allocate storage for saving a C++ binding.  */
- #define cxx_saved_binding_make() \
-   (ggc_alloc (sizeof (cxx_saved_binding)))
- 
- struct cxx_saved_binding GTY(())
- {
-   /* Link that chains saved C++ bindings for a given name into a stack.  */
-   cxx_saved_binding *previous;
-   /* The name of the current binding.  */
-   tree identifier;
-   /* The binding we're saving.  */
-   cxx_binding *binding;
-   tree class_value;
-   tree real_type_value;
- };
- 
  /* Subroutines for reverting temporarily to top-level for instantiation
     of templates and such.  We actually need to clear out the class- and
     local-value slots of all identifiers, so that only the global values
     are at all visible.  Simply setting current_binding_level to the global
     scope isn't enough, because more binding levels may be pushed.  */
  struct saved_scope *scope_chain;
  
! /* If ID is not already in the SEARCH_BINDINGS, prepend its binding
!    information to OLD_BINDINGS.  Returns the new OLD_BINDINGS
!    list.  */
! 
! static cxx_saved_binding *
! store_binding (tree id,
! 	       cxx_saved_binding *old_bindings,
! 	       cxx_saved_binding *search_bindings)
  {
    cxx_saved_binding *saved;
-   cxx_saved_binding *t1;
  
    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 old_bindings;
  
!   for (t1 = search_bindings; t1; t1 = t1->previous)
!     if (t1->identifier == id)
!      return old_bindings;
! 
!   my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
!   saved = cxx_saved_binding_make ();
!   saved->previous = old_bindings;
    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;
-   return saved;
  }
  
! static cxx_saved_binding *
! store_bindings (tree names, cxx_saved_binding *old_bindings)
  {
    tree t;
-   cxx_saved_binding *search_bindings = old_bindings;
  
    timevar_push (TV_NAME_LOOKUP);
    for (t = names; t; t = TREE_CHAIN (t))
      {
        tree id;
--- 4807,4856 ----
        TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b);
      }
    timevar_pop (TV_NAME_LOOKUP);
  }
  
  /* Subroutines for reverting temporarily to top-level for instantiation
     of templates and such.  We actually need to clear out the class- and
     local-value slots of all identifiers, so that only the global values
     are at all visible.  Simply setting current_binding_level to the global
     scope isn't enough, because more binding levels may be pushed.  */
  struct saved_scope *scope_chain;
  
! /* If ID has not already been marked, add an appropriate binding to
!    *OLD_BINDINGS.  */
! 
! 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)
  {
    tree t;
  
    timevar_push (TV_NAME_LOOKUP);
    for (t = names; t; t = TREE_CHAIN (t))
      {
        tree id;
*************** store_bindings (tree names, cxx_saved_bi
*** 4881,4922 ****
        if (TREE_CODE (t) == TREE_LIST)
  	id = TREE_PURPOSE (t);
        else
  	id = DECL_NAME (t);
  
!       old_bindings 
! 	= store_binding (id, old_bindings, search_bindings);
      }
!   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old_bindings);
  }
  
  /* Like store_bindings, but NAMES is a vector of cp_class_binding
     objects, rather than a TREE_LIST.  */
  
! static cxx_saved_binding *
  store_class_bindings (VEC(cp_class_binding) *names, 
! 		      cxx_saved_binding *old_bindings)
  {
    size_t i;
    cp_class_binding *cb;
-   cxx_saved_binding *search_bindings = old_bindings;
  
    timevar_push (TV_NAME_LOOKUP);
    for (i = 0; 
         (cb = VEC_iterate(cp_class_binding, names, i));
         ++i)
!     old_bindings 
!       = store_binding (cb->identifier, old_bindings, search_bindings);
!   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old_bindings);
  }
  
  void
  push_to_top_level (void)
  {
    struct saved_scope *s;
    struct cp_binding_level *b;
!   cxx_saved_binding *old_bindings;
    int need_pop;
  
    timevar_push (TV_NAME_LOOKUP);
    s = ggc_alloc_cleared (sizeof (struct saved_scope));
  
--- 4858,4897 ----
        if (TREE_CODE (t) == TREE_LIST)
  	id = TREE_PURPOSE (t);
        else
  	id = DECL_NAME (t);
  
!       store_binding (id, old_bindings);
      }
!   timevar_pop (TV_NAME_LOOKUP);
  }
  
  /* Like store_bindings, but NAMES is a vector of cp_class_binding
     objects, rather than a TREE_LIST.  */
  
! static void
  store_class_bindings (VEC(cp_class_binding) *names, 
! 		      VEC(cxx_saved_binding) **old_bindings)
  {
    size_t i;
    cp_class_binding *cb;
  
    timevar_push (TV_NAME_LOOKUP);
    for (i = 0; 
         (cb = VEC_iterate(cp_class_binding, names, i));
         ++i)
!     store_binding (cb->identifier, old_bindings);
!   timevar_pop (TV_NAME_LOOKUP);
  }
  
  void
  push_to_top_level (void)
  {
    struct saved_scope *s;
    struct cp_binding_level *b;
!   cxx_saved_binding *sb;
!   size_t i;
    int need_pop;
  
    timevar_push (TV_NAME_LOOKUP);
    s = ggc_alloc_cleared (sizeof (struct saved_scope));
  
*************** push_to_top_level (void)
*** 4929,4942 ****
        push_function_context_to (NULL_TREE);
      }
    else
      need_pop = 0;
  
-   old_bindings = NULL;
    if (scope_chain && previous_class_level)
!     old_bindings = store_class_bindings (previous_class_level->class_shadowed,
! 					 old_bindings);
  
    /* Have to include the global scope, because class-scope decls
       aren't listed anywhere useful.  */
    for (; b; b = b->level_chain)
      {
--- 4904,4916 ----
        push_function_context_to (NULL_TREE);
      }
    else
      need_pop = 0;
  
    if (scope_chain && previous_class_level)
!     store_class_bindings (previous_class_level->class_shadowed,
! 			  &s->old_bindings);
  
    /* Have to include the global scope, because class-scope decls
       aren't listed anywhere useful.  */
    for (; b; b = b->level_chain)
      {
*************** push_to_top_level (void)
*** 4947,4968 ****
  	 when doing pending instantiations. Therefore, don't stop at
  	 namespace level, but continue until :: .  */
        if (global_scope_p (b))
  	break;
  
!       old_bindings = store_bindings (b->names, old_bindings);
        /* We also need to check class_shadowed to save class-level type
  	 bindings, since pushclass doesn't fill in b->names.  */
        if (b->kind == sk_class)
! 	old_bindings = store_class_bindings (b->class_shadowed, old_bindings);
  
        /* Unwind type-value slots back to top level.  */
        for (t = b->type_shadowed; t; t = TREE_CHAIN (t))
  	SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (t), TREE_VALUE (t));
      }
    s->prev = scope_chain;
-   s->old_bindings = old_bindings;
    s->bindings = b;
    s->need_pop_function_context = need_pop;
    s->function_decl = current_function_decl;
  
    scope_chain = s;
--- 4921,4947 ----
  	 when doing pending instantiations. Therefore, don't stop at
  	 namespace level, but continue until :: .  */
        if (global_scope_p (b))
  	break;
  
!       store_bindings (b->names, &s->old_bindings);
        /* We also need to check class_shadowed to save class-level type
  	 bindings, since pushclass doesn't fill in b->names.  */
        if (b->kind == sk_class)
! 	store_class_bindings (b->class_shadowed, &s->old_bindings);
  
        /* Unwind type-value slots back to top level.  */
        for (t = b->type_shadowed; t; t = TREE_CHAIN (t))
  	SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (t), TREE_VALUE (t));
      }
+ 
+   for (i = 0;
+        (sb = VEC_iterate (cxx_saved_binding, s->old_bindings, i));
+        ++i)
+     IDENTIFIER_MARKED (sb->identifier) = 0;
+ 
    s->prev = scope_chain;
    s->bindings = b;
    s->need_pop_function_context = need_pop;
    s->function_decl = current_function_decl;
  
    scope_chain = s;
*************** push_to_top_level (void)
*** 4976,4995 ****
  void
  pop_from_top_level (void)
  {
    struct saved_scope *s = scope_chain;
    cxx_saved_binding *saved;
  
    timevar_push (TV_NAME_LOOKUP); 
    /* Clear out class-level bindings cache.  */
    if (previous_class_level)
      invalidate_class_lookup_cache ();
  
    current_lang_base = 0;
  
    scope_chain = s->prev;
!   for (saved = s->old_bindings; saved; saved = saved->previous)
      {
        tree id = saved->identifier;
  
        IDENTIFIER_BINDING (id) = saved->binding;
        IDENTIFIER_CLASS_VALUE (id) = saved->class_value;
--- 4955,4977 ----
  void
  pop_from_top_level (void)
  {
    struct saved_scope *s = scope_chain;
    cxx_saved_binding *saved;
+   size_t i;
  
    timevar_push (TV_NAME_LOOKUP); 
    /* Clear out class-level bindings cache.  */
    if (previous_class_level)
      invalidate_class_lookup_cache ();
  
    current_lang_base = 0;
  
    scope_chain = s->prev;
!   for (i = 0; 
!        (saved = VEC_iterate (cxx_saved_binding, s->old_bindings, i));
!        ++i)
      {
        tree id = saved->identifier;
  
        IDENTIFIER_BINDING (id) = saved->binding;
        IDENTIFIER_CLASS_VALUE (id) = saved->class_value;
Index: cp/name-lookup.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.h,v
retrieving revision 1.23
diff -c -5 -p -r1.23 name-lookup.h
*** cp/name-lookup.h	8 Jul 2004 14:53:42 -0000	1.23
--- cp/name-lookup.h	11 Jul 2004 20:34:06 -0000
*************** struct binding_entry_s GTY(())
*** 49,62 ****
  extern void binding_table_remove_anonymous_types (binding_table);
  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);
  
- /* Datatype used to temporarily save C++ bindings (for implicit
-    instantiations purposes and like).  Implemented in decl.c.  */
- typedef struct cxx_saved_binding cxx_saved_binding;
- 
  /* Datatype that represents binding established by a declaration between
     a name and a C++ entity.  */
  typedef struct cxx_binding cxx_binding;
  
  /* The datatype used to implement C++ scope.  */
--- 49,58 ----
*************** struct cxx_binding GTY(())
*** 82,91 ****
--- 78,101 ----
    cxx_scope *scope;
    unsigned value_is_inherited : 1;
    unsigned is_local : 1;
  };
  
+ /* Datatype used to temporarily save C++ bindings (for implicit
+    instantiations purposes and like).  Implemented in decl.c.  */
+ typedef struct cxx_saved_binding GTY(())
+ {
+   /* 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);
Index: cp/optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/optimize.c,v
retrieving revision 1.110
diff -c -5 -p -r1.110 optimize.c
*** cp/optimize.c	22 Jun 2004 07:18:37 -0000	1.110
--- cp/optimize.c	11 Jul 2004 20:34:06 -0000
*************** maybe_clone_body (tree fn)
*** 86,95 ****
--- 86,96 ----
    /* Emit the DWARF1 abstract instance.  */
    (*debug_hooks->deferred_inline_function) (fn);
  
    /* We know that any clones immediately follow FN in the TYPE_METHODS
       list.  */
+   push_to_top_level ();
    for (clone = TREE_CHAIN (fn);
         clone && DECL_CLONED_FUNCTION_P (clone);
         clone = TREE_CHAIN (clone))
      {
        tree parm;
*************** maybe_clone_body (tree fn)
*** 129,139 ****
  	   parm = TREE_CHAIN (parm), clone_parm = TREE_CHAIN (clone_parm))
  	/* Update this parameter.  */
  	update_cloned_parm (parm, clone_parm);
  
        /* Start processing the function.  */
-       push_to_top_level ();
        start_preparsed_function (clone, NULL_TREE, SF_PRE_PARSED);
  
        /* Remap the parameters.  */
        decl_map = splay_tree_new (splay_tree_compare_pointers, NULL, NULL);
        for (parmno = 0,
--- 130,139 ----
*************** maybe_clone_body (tree fn)
*** 196,206 ****
  
        /* Now, expand this function into RTL, if appropriate.  */
        finish_function (0);
        BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
        expand_or_defer_fn (clone);
-       pop_from_top_level ();
      }
  
    /* We don't need to process the original function any further.  */
    return 1;
  }
--- 196,206 ----
  
        /* Now, expand this function into RTL, if appropriate.  */
        finish_function (0);
        BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
        expand_or_defer_fn (clone);
      }
+   pop_from_top_level ();
  
    /* We don't need to process the original function any further.  */
    return 1;
  }
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.223
diff -c -5 -p -r1.223 parser.c
*** cp/parser.c	30 Jun 2004 18:23:34 -0000	1.223
--- cp/parser.c	11 Jul 2004 20:34:06 -0000
*************** cp_parser_class_specifier (cp_parser* pa
*** 12384,12393 ****
--- 12384,12395 ----
       there is no need to delay the parsing of `A::B::f'.  */
    if (--parser->num_classes_being_defined == 0)
      {
        tree queue_entry;
        tree fn;
+       tree class_type;
+       bool pop_p;
  
        /* In a first pass, parse default arguments to the functions.
  	 Then, in a second pass, parse the bodies of the functions.
  	 This two-phased approach handles cases like:
  
*************** cp_parser_class_specifier (cp_parser* pa
*** 12395,12419 ****
                void f() { g(); }
                void g(int i = 3);
              };
  
           */
        for (TREE_PURPOSE (parser->unparsed_functions_queues)
  	     = nreverse (TREE_PURPOSE (parser->unparsed_functions_queues));
  	   (queue_entry = TREE_PURPOSE (parser->unparsed_functions_queues));
  	   TREE_PURPOSE (parser->unparsed_functions_queues)
  	     = TREE_CHAIN (TREE_PURPOSE (parser->unparsed_functions_queues)))
  	{
  	  fn = TREE_VALUE (queue_entry);
- 	  /* Make sure that any template parameters are in scope.  */
- 	  maybe_begin_member_template_processing (fn);
  	  /* If there are default arguments that have not yet been processed,
  	     take care of them now.  */
  	  cp_parser_late_parsing_default_args (parser, fn);
  	  /* Remove any template parameters from the symbol table.  */
  	  maybe_end_member_template_processing ();
  	}
        /* Now parse the body of the functions.  */
        for (TREE_VALUE (parser->unparsed_functions_queues)
  	     = nreverse (TREE_VALUE (parser->unparsed_functions_queues));
  	   (queue_entry = TREE_VALUE (parser->unparsed_functions_queues));
  	   TREE_VALUE (parser->unparsed_functions_queues)
--- 12397,12433 ----
                void f() { g(); }
                void g(int i = 3);
              };
  
           */
+       class_type = NULL_TREE;
+       pop_p = false;
        for (TREE_PURPOSE (parser->unparsed_functions_queues)
  	     = nreverse (TREE_PURPOSE (parser->unparsed_functions_queues));
  	   (queue_entry = TREE_PURPOSE (parser->unparsed_functions_queues));
  	   TREE_PURPOSE (parser->unparsed_functions_queues)
  	     = TREE_CHAIN (TREE_PURPOSE (parser->unparsed_functions_queues)))
  	{
  	  fn = TREE_VALUE (queue_entry);
  	  /* If there are default arguments that have not yet been processed,
  	     take care of them now.  */
+ 	  if (class_type != TREE_PURPOSE (queue_entry))
+ 	    {
+ 	      if (pop_p)
+ 		pop_scope (class_type);
+ 	      class_type = TREE_PURPOSE (queue_entry);
+ 	      pop_p = push_scope (class_type);
+ 	    }
+ 	  /* Make sure that any template parameters are in scope.  */
+ 	  maybe_begin_member_template_processing (fn);
+ 	  /* Parse the default argument expressions.  */
  	  cp_parser_late_parsing_default_args (parser, fn);
  	  /* Remove any template parameters from the symbol table.  */
  	  maybe_end_member_template_processing ();
  	}
+       if (pop_p)
+ 	pop_scope (class_type);
        /* Now parse the body of the functions.  */
        for (TREE_VALUE (parser->unparsed_functions_queues)
  	     = nreverse (TREE_VALUE (parser->unparsed_functions_queues));
  	   (queue_entry = TREE_VALUE (parser->unparsed_functions_queues));
  	   TREE_VALUE (parser->unparsed_functions_queues)
*************** cp_parser_class_specifier (cp_parser* pa
*** 12427,12437 ****
  
  	  /* Parse the function.  */
  	  cp_parser_late_parsing_for_member (parser, fn);
  	  function_depth--;
  	}
- 
      }
  
    /* Put back any saved access checks.  */
    pop_deferring_access_checks ();
  
--- 12441,12450 ----
*************** cp_parser_save_default_args (cp_parser* 
*** 15238,15256 ****
         probe;
         probe = TREE_CHAIN (probe))
      if (TREE_PURPOSE (probe))
        {
  	TREE_PURPOSE (parser->unparsed_functions_queues)
! 	  = tree_cons (NULL_TREE, decl,
  		       TREE_PURPOSE (parser->unparsed_functions_queues));
  	break;
        }
    return;
  }
  
  /* FN is a FUNCTION_DECL which may contains a parameter with an
!    unparsed DEFAULT_ARG.  Parse the default args now.  */
  
  static void
  cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
  {
    cp_lexer *saved_lexer;
--- 15251,15271 ----
         probe;
         probe = TREE_CHAIN (probe))
      if (TREE_PURPOSE (probe))
        {
  	TREE_PURPOSE (parser->unparsed_functions_queues)
! 	  = tree_cons (current_class_type, decl,
  		       TREE_PURPOSE (parser->unparsed_functions_queues));
  	break;
        }
    return;
  }
  
  /* FN is a FUNCTION_DECL which may contains a parameter with an
!    unparsed DEFAULT_ARG.  Parse the default args now.  This function
!    assumes that the current scope is the scope in which the default
!    argument should be processed.  */
  
  static void
  cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
  {
    cp_lexer *saved_lexer;
*************** cp_parser_late_parsing_default_args (cp_
*** 15286,15300 ****
         /* Local variable names (and the `this' keyword) may not appear
       	  in a default argument.  */
        saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
        parser->local_variables_forbidden_p = true;
         /* Parse the assignment-expression.  */
-       if (DECL_CLASS_SCOPE_P (fn))
- 	push_nested_class (DECL_CONTEXT (fn));
        TREE_PURPOSE (parameters) = cp_parser_assignment_expression (parser);
-       if (DECL_CLASS_SCOPE_P (fn))
- 	pop_nested_class ();
  
        /* If the token stream has not been completely used up, then
  	 there was extra junk after the end of the default
  	 argument.  */
        if (!cp_lexer_next_token_is (parser->lexer, CPP_EOF))
--- 15301,15311 ----
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.296
diff -c -5 -p -r1.296 search.c
*** cp/search.c	7 Jul 2004 10:20:41 -0000	1.296
--- cp/search.c	11 Jul 2004 20:34:06 -0000
*************** static tree marked_pushdecls_p (tree, in
*** 86,96 ****
  static tree unmarked_pushdecls_p (tree, int, void *);
  static tree dfs_debug_unmarkedp (tree, int, void *);
  static tree dfs_debug_mark (tree, void *);
  static tree dfs_push_type_decls (tree, void *);
  static tree dfs_push_decls (tree, void *);
- static tree dfs_unuse_fields (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 *);
--- 86,95 ----
*************** push_class_decls (tree type)
*** 2245,2293 ****
  
    /* Enter non-type declarations and unmark.  */
    dfs_walk (TYPE_BINFO (type), dfs_push_decls, marked_pushdecls_p, 0);
  }
  
- /* Here's a subroutine we need because C lacks lambdas.  */
- 
- static tree
- dfs_unuse_fields (tree binfo, void *data ATTRIBUTE_UNUSED)
- {
-   tree type = TREE_TYPE (binfo);
-   tree fields;
- 
-   if (TREE_CODE (type) == TYPENAME_TYPE)
-     fields = TYPENAME_TYPE_FULLNAME (type);
-   else if (TREE_CODE (type) == TYPEOF_TYPE)
-     fields = TYPEOF_TYPE_EXPR (type);
-   else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
- 	   || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
- 	   || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
-     fields = TEMPLATE_TYPE_PARM_INDEX (type);
-   else
-     fields = TYPE_FIELDS (type);
- 
-   for (; fields; fields = TREE_CHAIN (fields))
-     {
-       if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
- 	continue;
- 
-       TREE_USED (fields) = 0;
-       if (DECL_NAME (fields) == NULL_TREE
- 	  && ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
- 	unuse_fields (TREE_TYPE (fields));
-     }
- 
-   return NULL_TREE;
- }
- 
- void
- unuse_fields (tree type)
- {
-   dfs_walk (TYPE_BINFO (type), dfs_unuse_fields, unmarkedp, 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.  */
--- 2244,2253 ----
Index: testsuite/g++.dg/parse/defarg8.C
===================================================================
RCS file: testsuite/g++.dg/parse/defarg8.C
diff -N testsuite/g++.dg/parse/defarg8.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/defarg8.C	11 Jul 2004 20:34:06 -0000
***************
*** 0 ****
--- 1,10 ----
+ struct A {
+   static void g(int);
+ };
+ 
+ struct S {
+   static int i;
+ 
+   friend void f(int = i);
+   friend void A::g(int = i);
+ };


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