Commit f44b0c8e by Mark Mitchell Committed by Mark Mitchell

cp-tree.h (saved_scope): Make old_bindings a vector.

	* 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
parent 4dcf7d66
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,
......
......@@ -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));
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
......@@ -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
......
......@@ -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)
{
......
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
......
struct A {
static void g(int);
};
struct S {
static int i;
friend void f(int = i);
friend void A::g(int = i);
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment