* 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
+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,
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));
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;
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);
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
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))
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
{
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);
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. */
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;
{
struct saved_scope *s = scope_chain;
cxx_saved_binding *saved;
+ size_t i;
timevar_push (TV_NAME_LOOKUP);
/* Clear out class-level bindings cache. */
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;
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;
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);
/* 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))
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. */
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;
{
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.
};
*/
+ 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_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));
cp_parser_late_parsing_for_member (parser, fn);
function_depth--;
}
-
}
/* Put back any saved access checks. */
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;
}
}
/* 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)
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
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 *,
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)
{
+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
--- /dev/null
+struct A {
+ static void g(int);
+};
+
+struct S {
+ static int i;
+
+ friend void f(int = i);
+ friend void A::g(int = i);
+};