From 93c149df04baceb7006fd44481e180ffb6824b16 Mon Sep 17 00:00:00 2001 From: mmitchel Date: Sun, 11 Jul 2004 21:02:31 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@84530 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 24 ++++++++++ gcc/cp/class.c | 1 - gcc/cp/cp-tree.h | 3 +- gcc/cp/name-lookup.c | 86 ++++++++++++++---------------------- gcc/cp/name-lookup.h | 18 ++++++-- gcc/cp/optimize.c | 4 +- gcc/cp/parser.c | 29 ++++++++---- gcc/cp/search.c | 40 ----------------- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/g++.dg/parse/defarg8.C | 10 +++++ 10 files changed, 109 insertions(+), 110 deletions(-) create mode 100644 gcc/testsuite/g++.dg/parse/defarg8.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0c0219a..ea3b13f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,27 @@ +2004-07-11 Mark Mitchell + + * 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 * cp-lang.c (LANG_HOOKS_MAYBE_BUILD_CLEANUP, LANG_HOOKS_PUSHLEVEL, diff --git a/gcc/cp/class.c b/gcc/cp/class.c index f9c3b70..f13ccac 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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)); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 415553c..6cfe280 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index b070800..c47c6be 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -4809,22 +4809,6 @@ pushtag (tree name, tree type, int globalize) 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 @@ -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; diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index e4fd03c..b7e59e8 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -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); -/* 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); diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index 448a0b3..8a3ebe6 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -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; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index e3b9736..fc5e8a5 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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 diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 0c9188d..da9a7cf 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -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) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0a53cbf..fe9a065 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2004-07-11 Mark Mitchell + + * g++.dg/parse/defarg8.C: New test. + 2004-07-11 Tobias Schlueter 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 index 0000000..1f1f078 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/defarg8.C @@ -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); +}; -- 2.7.4