cp-tree.h (saved_scope): Make old_bindings a vector.
authorMark Mitchell <mark@codesourcery.com>
Sun, 11 Jul 2004 21:02:31 +0000 (21:02 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sun, 11 Jul 2004 21:02:31 +0000 (21:02 +0000)
* 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.

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

From-SVN: r84530

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/name-lookup.c
gcc/cp/name-lookup.h
gcc/cp/optimize.c
gcc/cp/parser.c
gcc/cp/search.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/defarg8.C [new file with mode: 0644]

index 0c0219adab7ab2bda0cb82f3579a476df5440c10..ea3b13ff532793d064eea6c14c96ea374776e48c 100644 (file)
@@ -1,3 +1,27 @@
+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  Joseph S. Myers  <jsm@polyomino.org.uk>
 
        * cp-lang.c (LANG_HOOKS_MAYBE_BUILD_CLEANUP, LANG_HOOKS_PUSHLEVEL,
index f9c3b706592eca96fff8d3c66607b1d86f38b23b..f13ccac378bc9eaba1dd5f49a574c05930f55d84 100644 (file)
@@ -5569,7 +5569,6 @@ pushclass (tree 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));
index 415553c0630d0888b2219cb2e11cde66196ae720..6cfe2805caa3f8fab51f04605eaf345cc75ead77 100644 (file)
@@ -630,7 +630,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
 
 struct saved_scope GTY(())
 {
-  cxx_saved_binding *old_bindings;
+  VEC(cxx_saved_binding) *old_bindings;
   tree old_namespace;
   tree decl_ns_list;
   tree class_name;
@@ -4015,7 +4015,6 @@ 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);
index b0708002ae7541ab84cd0c8d48000fade9de2f6c..c47c6beae72763a3b5642dfc3813ed1cee4ea7e4 100644 (file)
@@ -4809,22 +4809,6 @@ pushtag (tree name, tree type, int globalize)
   timevar_pop (TV_NAME_LOOKUP);
 }
 \f
-/* 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
@@ -4832,46 +4816,39 @@ struct cxx_saved_binding GTY(())
    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.  */
+/* If ID has not already been marked, add an appropriate binding to
+   *OLD_BINDINGS.  */
 
-static cxx_saved_binding *
-store_binding (tree id,
-              cxx_saved_binding *old_bindings,
-              cxx_saved_binding *search_bindings)
+static void
+store_binding (tree id, VEC(cxx_saved_binding) **old_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;
+    return;
 
-  for (t1 = search_bindings; t1; t1 = t1->previous)
-    if (t1->identifier == id)
-     return old_bindings;
+  if (IDENTIFIER_MARKED (id))
+    return;
+  
+  IDENTIFIER_MARKED (id) = 1;
 
-  my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
-  saved = cxx_saved_binding_make ();
-  saved->previous = old_bindings;
+  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;
-  return saved;
 }
 
-static cxx_saved_binding *
-store_bindings (tree names, cxx_saved_binding *old_bindings)
+static void
+store_bindings (tree names, VEC(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))
@@ -4883,30 +4860,27 @@ store_bindings (tree names, cxx_saved_binding *old_bindings)
       else
        id = DECL_NAME (t);
 
-      old_bindings 
-       = store_binding (id, old_bindings, search_bindings);
+      store_binding (id, old_bindings);
     }
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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 cxx_saved_binding *
+static void
 store_class_bindings (VEC(cp_class_binding) *names, 
-                     cxx_saved_binding *old_bindings)
+                     VEC(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);
+    store_binding (cb->identifier, old_bindings);
+  timevar_pop (TV_NAME_LOOKUP);
 }
 
 void
@@ -4914,7 +4888,8 @@ push_to_top_level (void)
 {
   struct saved_scope *s;
   struct cp_binding_level *b;
-  cxx_saved_binding *old_bindings;
+  cxx_saved_binding *sb;
+  size_t i;
   int need_pop;
 
   timevar_push (TV_NAME_LOOKUP);
@@ -4931,10 +4906,9 @@ push_to_top_level (void)
   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);
+    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.  */
@@ -4949,18 +4923,23 @@ push_to_top_level (void)
       if (global_scope_p (b))
        break;
 
-      old_bindings = store_bindings (b->names, old_bindings);
+      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)
-       old_bindings = store_class_bindings (b->class_shadowed, old_bindings);
+       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->old_bindings = old_bindings;
   s->bindings = b;
   s->need_pop_function_context = need_pop;
   s->function_decl = current_function_decl;
@@ -4978,6 +4957,7 @@ 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.  */
@@ -4987,7 +4967,9 @@ pop_from_top_level (void)
   current_lang_base = 0;
 
   scope_chain = s->prev;
-  for (saved = s->old_bindings; saved; saved = saved->previous)
+  for (i = 0; 
+       (saved = VEC_iterate (cxx_saved_binding, s->old_bindings, i));
+       ++i)
     {
       tree id = saved->identifier;
 
index e4fd03ce5491f9f50bf3f498e2b90fb86d58785b..b7e59e8536b4c2500feb8e050d5572b605d3fa7e 100644 (file)
@@ -51,10 +51,6 @@ 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);
 \f
-/* 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;
@@ -84,6 +80,20 @@ struct cxx_binding GTY(())
   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);
index 448a0b376a900cc1c91194574701872631d6140a..8a3ebe6ebbeb012c9162bc187aadd49eec4d88d4 100644 (file)
@@ -88,6 +88,7 @@ maybe_clone_body (tree 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))
@@ -131,7 +132,6 @@ maybe_clone_body (tree fn)
        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.  */
@@ -198,8 +198,8 @@ maybe_clone_body (tree fn)
       finish_function (0);
       BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn);
       expand_or_defer_fn (clone);
-      pop_from_top_level ();
     }
+  pop_from_top_level ();
 
   /* We don't need to process the original function any further.  */
   return 1;
index e3b97369cfd17844ef01c1bb15aae12c64f6c698..fc5e8a57bcdb7396d78005b1366796433cbc47fd 100644 (file)
@@ -12386,6 +12386,8 @@ cp_parser_class_specifier (cp_parser* parser)
     {
       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.
@@ -12397,6 +12399,8 @@ cp_parser_class_specifier (cp_parser* parser)
             };
 
          */
+      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));
@@ -12404,14 +12408,24 @@ cp_parser_class_specifier (cp_parser* parser)
             = 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.  */
+         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));
@@ -12429,7 +12443,6 @@ cp_parser_class_specifier (cp_parser* parser)
          cp_parser_late_parsing_for_member (parser, fn);
          function_depth--;
        }
-
     }
 
   /* Put back any saved access checks.  */
@@ -15240,7 +15253,7 @@ cp_parser_save_default_args (cp_parser* parser, tree decl)
     if (TREE_PURPOSE (probe))
       {
        TREE_PURPOSE (parser->unparsed_functions_queues)
-         = tree_cons (NULL_TREE, decl,
+         = tree_cons (current_class_type, decl,
                       TREE_PURPOSE (parser->unparsed_functions_queues));
        break;
       }
@@ -15248,7 +15261,9 @@ cp_parser_save_default_args (cp_parser* parser, tree decl)
 }
 
 /* FN is a FUNCTION_DECL which may contains a parameter with an
-   unparsed DEFAULT_ARG.  Parse the default args now.  */
+   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)
@@ -15288,11 +15303,7 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
       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
index 0c9188dfa225bdfcbf077a80b0ed14feaa6ecaac..da9a7cfdc7fdd4c93f6185c3244509b0ad3085b1 100644 (file)
@@ -88,7 +88,6 @@ 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 *,
@@ -2247,45 +2246,6 @@ push_class_decls (tree type)
   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)
 {
index 0a53cbf12209916d2077b9a4fc306dcbc5813d74..fe9a0655fb77fec4bde64b834b02b21b85c29f85 100644 (file)
@@ -1,3 +1,7 @@
+2004-07-11  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/parse/defarg8.C: New test.
+
 2004-07-11  Tobias Schlueter  <tobias.schlueter@physik.uni-muenchen.de>
 
        PR fortran/16433
diff --git a/gcc/testsuite/g++.dg/parse/defarg8.C b/gcc/testsuite/g++.dg/parse/defarg8.C
new file mode 100644 (file)
index 0000000..1f1f078
--- /dev/null
@@ -0,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);
+};