aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2004-07-11 21:02:31 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2004-07-11 21:02:31 +0000
commitf44b0c8ec5fdc1fc12508a40cd6d4da209279ab6 (patch)
treeb47ca1ae95a6c5cdd74d9e1827122aa0590299ed /gcc
parent4dcf7d66acad759f4c62caaa39d8b981ced74892 (diff)
downloadgcc-f44b0c8ec5fdc1fc12508a40cd6d4da209279ab6.zip
gcc-f44b0c8ec5fdc1fc12508a40cd6d4da209279ab6.tar.gz
gcc-f44b0c8ec5fdc1fc12508a40cd6d4da209279ab6.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog24
-rw-r--r--gcc/cp/class.c1
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/name-lookup.c86
-rw-r--r--gcc/cp/name-lookup.h18
-rw-r--r--gcc/cp/optimize.c4
-rw-r--r--gcc/cp/parser.c29
-rw-r--r--gcc/cp/search.c40
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/parse/defarg8.C10
10 files changed, 109 insertions, 110 deletions
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 <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,
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 <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
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);
+};