summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>1998-12-13 14:46:07 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>1998-12-13 14:46:07 +0000
commit53137e6a27e6f962d95e7f31d58b07ab7c36f9d9 (patch)
tree807c2e0544168b2313fcea1dce6434567e6f8339
parentcd8e3defda7dc4d8aa8d6e026b007db17f001540 (diff)
downloadgcc-53137e6a27e6f962d95e7f31d58b07ab7c36f9d9.tar.gz
* cp-tree.def (CPLUS_BINDING): Update documentation.
* cp-tree.h (LOCAL_BINDING_P): New macro. (lang_identifier): Rename local_value to bindings. (tree_binding): Make `scope' of type `void*', not `tree'. (BINDING_SCOPE): Update documentation. (IDENTIFIER_LOCAL_VALUE): Remove. (IDENTIFIER_CLASS_VALUE): Document. (IDENTIFIER_BINDING): New macro. (IDENTIFIER_VALUE): Likewise. (TIME_IDENTIFIER_TIME): Likewise. (TIME_IDENTIFIER_FILEINFO): Likewise. (IMPLICIT_TYPENAME_P): Likewise. (set_identifier_local_value): Remove. (push_local_binding): New function. (push_class_binding): Likewise. * class.c (pushclass): Update comments; use push_class_binding. * decl.c (set_identifier_local_value_with_scope): Remove. (set_identifier_local_value): Likewise. (push_binding): New function. (pop_binding): Likewise. (binding_level): Update documentation. Remove shadowed. (BINDING_LEVEL): New macro. (free_binding_nodes): New variable. (poplevel): Adjust for new name-lookup scheme. Don't mess up BLOCK_VARs when doing for-scope extension. Remove effectively dead code. (pushlevel_class): Tweak formatting. (poplevel_class): Adjust for new name-lookup scheme. (print_binding_level): Likewise. (store_bindings): Likewise. (pushdecl): Likewise. (pushdecl_class_level): Likewise. (push_class_level_binding): Likewise. (push_overloaded_decl): Update comments. Adjust for new name-lookup scheme. (lookup_name_real): Likewise. (lookup_name_current_level): Likewise. (cp_finish_decl): Likewise. (require_complete_types_for_parms): Likewise. Remove misleading #if 0'd code. (grok_parms): Likewise. Don't call require_complete_types_for_parms here. (grok_ctor_properties): Don't treat templates as copy constructors. (grop_op_properties): Or as assignment operators. (start_function): Document. Adjust for new name-lookup scheme. (finish_function): Likewise. * decl2.c (do_local_using_decl): Use push_local_binding. * lex.c (begin_definition_of_inclass_inline): New function, split out from ... (do_pending_inlines): Here, and ... (process_next_inline): Here. (get_time_identifier): Use TIME_IDENTIFIER_* macros. (init_filename_times): Likewise. (extract_interface_info): Likewise. (ste_typedecl_interface_info): Likewise. (check_newline): Likewise. (dump_time_statistics): Likewise. (handle_cp_pragma): Likewise. (do_identifier): Adjust for new name-lookup scheme. * parse.y (function_try_block): Return ctor_initializer_opt value. (fndef): Use it. (fn.defpen): Pass appropriate values to start_function. (pending_inline): Use functor_try_block value, and pass appropriate values to finish_function. * pt.c (is_member_template): Update documentation; remove handling of FUNCTION_DECLs. As per name, this function should deal only in TEMPLATE_DECLs. (decl_template_parm_p): Change name of olddecl parameter to decl. (check_template_shadow): Adjust for new name-lookup scheme. (lookup_template_class): Likewise. (tsubst_decl): Tweak so as not to confuse member templates with copy constructors and assignment operators. (unify): Handle UNION_TYPEs. * ptree.c (print_lang_identifier): Adjust for new name-lookup scheme. (lang_print_xnode): Adjust for new name-lookup scheme. * typeck.c (mark_addressable): Likewise. (c_expand_return): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@24296 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog81
-rw-r--r--gcc/cp/class.c9
-rw-r--r--gcc/cp/cp-tree.def6
-rw-r--r--gcc/cp/cp-tree.h68
-rw-r--r--gcc/cp/decl.c995
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/cp/lex.c139
-rw-r--r--gcc/cp/parse.y23
-rw-r--r--gcc/cp/pt.c103
-rw-r--r--gcc/cp/ptree.c5
-rw-r--r--gcc/cp/typeck.c15
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900511_02.C6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900511_03.C6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/for1.C41
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/lookup6.C25
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/overload9.C31
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/copy1.C29
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/friend34.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/union1.C18
19 files changed, 988 insertions, 616 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1c3bd37b841..84cc28fa1b7 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,84 @@
+1998-12-13 Mark Mitchell <mark@markmitchell.com>
+
+ * cp-tree.def (CPLUS_BINDING): Update documentation.
+ * cp-tree.h (LOCAL_BINDING_P): New macro.
+ (lang_identifier): Rename local_value to bindings.
+ (tree_binding): Make `scope' of type `void*', not `tree'.
+ (BINDING_SCOPE): Update documentation.
+ (IDENTIFIER_LOCAL_VALUE): Remove.
+ (IDENTIFIER_CLASS_VALUE): Document.
+ (IDENTIFIER_BINDING): New macro.
+ (IDENTIFIER_VALUE): Likewise.
+ (TIME_IDENTIFIER_TIME): Likewise.
+ (TIME_IDENTIFIER_FILEINFO): Likewise.
+ (IMPLICIT_TYPENAME_P): Likewise.
+ (set_identifier_local_value): Remove.
+ (push_local_binding): New function.
+ (push_class_binding): Likewise.
+ * class.c (pushclass): Update comments; use push_class_binding.
+ * decl.c (set_identifier_local_value_with_scope): Remove.
+ (set_identifier_local_value): Likewise.
+ (push_binding): New function.
+ (pop_binding): Likewise.
+ (binding_level): Update documentation. Remove shadowed.
+ (BINDING_LEVEL): New macro.
+ (free_binding_nodes): New variable.
+ (poplevel): Adjust for new name-lookup scheme. Don't mess up
+ BLOCK_VARs when doing for-scope extension. Remove effectively
+ dead code.
+ (pushlevel_class): Tweak formatting.
+ (poplevel_class): Adjust for new name-lookup scheme.
+ (print_binding_level): Likewise.
+ (store_bindings): Likewise.
+ (pushdecl): Likewise.
+ (pushdecl_class_level): Likewise.
+ (push_class_level_binding): Likewise.
+ (push_overloaded_decl): Update comments. Adjust for new
+ name-lookup scheme.
+ (lookup_name_real): Likewise.
+ (lookup_name_current_level): Likewise.
+ (cp_finish_decl): Likewise.
+ (require_complete_types_for_parms): Likewise. Remove misleading
+ #if 0'd code.
+ (grok_parms): Likewise. Don't call
+ require_complete_types_for_parms here.
+ (grok_ctor_properties): Don't treat templates as copy
+ constructors.
+ (grop_op_properties): Or as assignment operators.
+ (start_function): Document. Adjust for new name-lookup scheme.
+ (finish_function): Likewise.
+ * decl2.c (do_local_using_decl): Use push_local_binding.
+ * lex.c (begin_definition_of_inclass_inline): New function, split
+ out from ...
+ (do_pending_inlines): Here, and ...
+ (process_next_inline): Here.
+ (get_time_identifier): Use TIME_IDENTIFIER_* macros.
+ (init_filename_times): Likewise.
+ (extract_interface_info): Likewise.
+ (ste_typedecl_interface_info): Likewise.
+ (check_newline): Likewise.
+ (dump_time_statistics): Likewise.
+ (handle_cp_pragma): Likewise.
+ (do_identifier): Adjust for new name-lookup scheme.
+ * parse.y (function_try_block): Return ctor_initializer_opt value.
+ (fndef): Use it.
+ (fn.defpen): Pass appropriate values to start_function.
+ (pending_inline): Use functor_try_block value, and pass
+ appropriate values to finish_function.
+ * pt.c (is_member_template): Update documentation; remove handling
+ of FUNCTION_DECLs. As per name, this function should deal only in
+ TEMPLATE_DECLs.
+ (decl_template_parm_p): Change name of olddecl parameter to decl.
+ (check_template_shadow): Adjust for new name-lookup scheme.
+ (lookup_template_class): Likewise.
+ (tsubst_decl): Tweak so as not to confuse member templates with
+ copy constructors and assignment operators.
+ (unify): Handle UNION_TYPEs.
+ * ptree.c (print_lang_identifier): Adjust for new name-lookup scheme.
+ (lang_print_xnode): Adjust for new name-lookup scheme.
+ * typeck.c (mark_addressable): Likewise.
+ (c_expand_return): Likewise.
+
1998-12-08 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (grokdeclarator): Allow field with same name as class
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index a73605a96e5..5031b556917 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4780,15 +4780,18 @@ pushclass (type, modify)
{
tree item;
- /* Hooray, we successfully cached; let's just install the
- cached class_shadowed list, and walk through it to get the
- IDENTIFIER_TYPE_VALUEs correct. */
+ /* We are re-entering the same class we just left, so we
+ don't have to search the whole inheritance matrix to find
+ all the decls to bind again. Instead, we install the
+ cached class_shadowed list, and walk through it binding
+ names and setting up IDENTIFIER_TYPE_VALUEs. */
set_class_shadows (previous_class_values);
for (item = previous_class_values; item; item = TREE_CHAIN (item))
{
tree id = TREE_PURPOSE (item);
tree decl = IDENTIFIER_CLASS_VALUE (id);
+ push_class_binding (id, decl);
if (TREE_CODE (decl) == TYPE_DECL)
set_identifier_type_value (id, TREE_TYPE (decl));
}
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index 3c50e8fe299..37c444687fa 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -178,9 +178,9 @@ DEFTREECODE (DEFAULT_ARG, "default_arg", 'c', 2)
the template may be an IDENTIFIER_NODE. */
DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", 'e', 2)
-/* An association between namespace and entity. Parameters are the
- scope and the (non-type) value.
- TREE_TYPE indicates the type bound to the name. */
+/* An association between name and entity. Parameters are the scope
+ and the (non-type) value. TREE_TYPE indicates the type bound to
+ the name. */
DEFTREECODE (CPLUS_BINDING, "binding", 'x', 2)
/* A list-like node for chaining overloading candidates. TREE_TYPE is
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 119efdd9888..395b24a2b40 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA. */
LOOKUP_EXPR_GLOBAL (in LOOKUP_EXPR).
TREE_NEGATED_INT (in INTEGER_CST).
IDENTIFIER_MARKED (used by search routines).
+ LOCAL_BINDING_P (in CPLUS_BINDING)
1: IDENTIFIER_VIRTUAL_P.
TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE.
@@ -92,7 +93,8 @@ Boston, MA 02111-1307, USA. */
struct lang_identifier
{
struct tree_identifier ignore;
- tree namespace_bindings, local_value;
+ tree namespace_bindings;
+ tree bindings;
tree class_value;
tree class_template_info;
struct lang_id2 *x;
@@ -127,15 +129,24 @@ typedef struct ptrmem_cst
tree member;
}* ptrmem_cst_t;
-/* For a binding between a name and an entity, defines the scope
- where the binding is declared. Currently always points to a
- namespace declaration. */
-#define BINDING_SCOPE(NODE) (((struct tree_binding*)NODE)->scope)
+/* Nonzero if this binding is for a local scope, as opposed to a class
+ or namespace scope. */
+#define LOCAL_BINDING_P(NODE) TREE_LANG_FLAG_0(NODE)
+
+/* For a binding between a name and an entity at a non-local scope,
+ defines the scope where the binding is declared. (Either a class
+ _TYPE node, or a NAMESPACE_DECL.) This macro should be used only
+ for namespace-level bindings; on the IDENTIFIER_BINDING list
+ BINDING_LEVEL is used instead. */
+#define BINDING_SCOPE(NODE) ((tree) ((struct tree_binding*)NODE)->scope)
+
/* This is the declaration bound to the name. Possible values:
variable, overloaded function, namespace, template, enumerator. */
#define BINDING_VALUE(NODE) (((struct tree_binding*)NODE)->value)
+
/* If name is bound to a type, this is the type (struct, union, enum). */
#define BINDING_TYPE(NODE) TREE_TYPE(NODE)
+
#define IDENTIFIER_GLOBAL_VALUE(NODE) \
namespace_binding (NODE, global_namespace)
#define SET_IDENTIFIER_GLOBAL_VALUE(NODE, VAL) \
@@ -148,7 +159,7 @@ typedef struct ptrmem_cst
struct tree_binding
{
char common[sizeof (struct tree_common)];
- tree scope;
+ void* scope;
tree value;
};
@@ -200,13 +211,43 @@ struct tree_srcloc
#define IDENTIFIER_NAMESPACE_BINDINGS(NODE) \
(((struct lang_identifier *)(NODE))->namespace_bindings)
-#define IDENTIFIER_CLASS_VALUE(NODE) \
- (((struct lang_identifier *)(NODE))->class_value)
-#define IDENTIFIER_LOCAL_VALUE(NODE) \
- (((struct lang_identifier *)(NODE))->local_value)
#define IDENTIFIER_TEMPLATE(NODE) \
(((struct lang_identifier *)(NODE))->class_template_info)
+/* The IDENTIFIER_BINDING is the innermost CPLUS_BINDING for the
+ identifier. It's TREE_CHAIN is the next outermost binding. Each
+ BINDING_VALUE is a DECL for the associated declaration. Thus,
+ name lookup consists simply of pulling off the node at the front
+ of the list (modulo oddities for looking up the names of types,
+ and such.) You can use BINDING_SCOPE or BINDING_LEVEL to
+ determine the scope that bound the name. */
+#define IDENTIFIER_BINDING(NODE) \
+ (((struct lang_identifier*) (NODE))->bindings)
+
+/* The IDENTIFIER_VALUE is the value of the IDENTIFIER_BINDING, or
+ NULL_TREE if there is no binding. */
+#define IDENTIFIER_VALUE(NODE) \
+ (IDENTIFIER_BINDING (NODE) \
+ ? BINDING_VALUE (IDENTIFIER_BINDING (NODE)) \
+ : NULL_TREE)
+
+/* If we are currently in class scope, then IDENTIFIER_CLASS_VALUE
+ indicates the class-scoped binding of NODE. This is just a pointer
+ to the BINDING_VALUE of one of the bindings in the
+ IDENTIFIER_BINDINGs list, so any time that this is set so is
+ IDENTIFIER_BINDING. */
+#define IDENTIFIER_CLASS_VALUE(NODE) \
+ (((struct lang_identifier *) (NODE))->class_value)
+
+/* The amount of time used by the file whose special "time identifier"
+ is NODE, represented as an INTEGER_CST. See get_time_identifier. */
+#define TIME_IDENTIFIER_TIME(NODE) IDENTIFIER_BINDING(NODE)
+
+/* For a "time identifier" this is a INTEGER_CST. The
+ TREE_INT_CST_LOW is 1 if the corresponding file is "interface only".
+ The TRE_INT_CST_HIGH is 1 if it is "interface unknown". */
+#define TIME_IDENTIFIER_FILEINFO(NODE) IDENTIFIER_CLASS_VALUE (NODE)
+
/* TREE_TYPE only indicates on local and class scope the current
type. For namespace scope, the presence of a type in any namespace
is indicated with global_type_node, and the real type behind must
@@ -1444,6 +1485,10 @@ struct lang_decl
TEMPLATE_ID_EXPR if we had something like `typename X::Y<T>'. */
#define TYPENAME_TYPE_FULLNAME(NODE) TYPE_BINFO (NODE)
+/* Nonzero if NODE is an implicit typename. */
+#define IMPLICIT_TYPENAME_P(NODE) \
+ (TREE_CODE (NODE) == TYPENAME_TYPE && TREE_TYPE (NODE))
+
/* Nonzero in INTEGER_CST means that this int is negative by dint of
using a twos-complement negated operand. */
#define TREE_NEGATED_INT(NODE) (TREE_LANG_FLAG_0 (NODE))
@@ -2665,7 +2710,6 @@ extern void push_to_top_level PROTO((void));
extern void pop_from_top_level PROTO((void));
extern tree identifier_type_value PROTO((tree));
extern void set_identifier_type_value PROTO((tree, tree));
-extern void set_identifier_local_value PROTO((tree, tree));
extern void pop_everything PROTO((void));
extern void pushtag PROTO((tree, tree, int));
extern tree make_anon_name PROTO((void));
@@ -2761,6 +2805,8 @@ extern void revert_static_member_fn PROTO((tree*, tree*, tree*));
extern void cat_namespace_levels PROTO((void));
extern void fixup_anonymous_union PROTO((tree));
extern int check_static_variable_definition PROTO((tree, tree));
+extern void push_local_binding PROTO((tree, tree));
+extern void push_class_binding PROTO((tree, tree));
/* in decl2.c */
extern int check_java_method PROTO((tree));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index c2afcb7d0fc..7c9a518e161 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -169,8 +169,6 @@ static tree lookup_tag PROTO((enum tree_code, tree,
struct binding_level *, int));
static void set_identifier_type_value_with_scope
PROTO((tree, tree, struct binding_level *));
-static void set_identifier_local_value_with_scope
- PROTO((tree, tree, struct binding_level *));
static void record_builtin_type PROTO((enum rid, char *, tree));
static void record_unknown_type PROTO((tree, char *));
static int member_function_or_else PROTO((tree, tree, char *));
@@ -181,6 +179,8 @@ static tree maybe_process_template_type_declaration PROTO((tree, int, struct bin
static void check_for_uninitialized_const_var PROTO((tree));
static unsigned long typename_hash PROTO((hash_table_key));
static boolean typename_compare PROTO((hash_table_key, hash_table_key));
+static void push_binding PROTO((tree, tree, struct binding_level*));
+static void pop_binding PROTO((tree));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PROTO((void));
@@ -611,7 +611,8 @@ struct binding_level
{
/* A chain of _DECL nodes for all variables, constants, functions,
and typedef types. These are in the reverse of the order
- supplied. */
+ supplied. There may be OVERLOADs on this list, too, but they
+ are wrapped in TREE_LISTs; the TREE_VALUE is the OVERLOAD. */
tree names;
/* A list of structure, union and enum definitions, for looking up
@@ -631,16 +632,16 @@ struct binding_level
VALUE the common ancestor with this binding_level's namespace. */
tree using_directives;
- /* For each level, a list of shadowed outer-level local definitions
- to be restored when this level is popped.
- Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
- whose TREE_VALUE is its old definition (a kind of ..._DECL node). */
- tree shadowed;
-
- /* Same, for IDENTIFIER_CLASS_VALUE. */
+ /* If this binding level is the binding level for a class, then
+ class_shadowed is a TREE_LIST. The TREE_PURPOSE of each node
+ is the name of an entity bound in the class; the TREE_VALUE is
+ the IDENTIFIER_CLASS_VALUE before we entered the class. Thus,
+ when leaving class scope, we can restore the
+ IDENTIFIER_CLASS_VALUE by walking this list. */
tree class_shadowed;
- /* Same, for IDENTIFIER_TYPE_VALUE. */
+ /* Similar to class_shadowed, but for IDENTIFIER_TYPE_VALUE, and
+ is used for all binding levels. */
tree type_shadowed;
/* For each level (except not the global one),
@@ -661,7 +662,8 @@ struct binding_level
/* List of VAR_DECLS saved from a previous for statement.
These would be dead in ANSI-conforming code, but might
- be referenced in ARM-era code. */
+ be referenced in ARM-era code. These are stored in a
+ TREE_LIST; the TREE_VALUE is the actual declaration. */
tree dead_vars_from_for;
/* 1 for the level that holds the parameters of a function.
@@ -1030,6 +1032,112 @@ pushlevel_temporary (tag_transparent)
expand_start_bindings (0);
}
+/* For a binding between a name and an entity at a block scope,
+ this is the `struct binding_level' for the block. */
+#define BINDING_LEVEL(NODE) \
+ ((struct binding_level*) ((struct tree_binding*)NODE)->scope)
+
+/* These are currently unused, but permanent, CPLUS_BINDING nodes.
+ They are kept here because they are allocated from the permanent
+ obstack and cannot be easily freed. */
+static tree free_binding_nodes;
+
+/* Make DECL the innermost binding for ID. The LEVEL is the binding
+ level at which this declaration is being bound. */
+
+static void
+push_binding (id, decl, level)
+ tree id;
+ tree decl;
+ struct binding_level* level;
+{
+ tree binding;
+
+ if (!free_binding_nodes)
+ {
+ /* There are no free nodes, so we must build one here. */
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+ binding = make_node (CPLUS_BINDING);
+ pop_obstacks ();
+ }
+ else
+ {
+ /* There are nodes on the free list. Grab the first one. */
+ binding = free_binding_nodes;
+
+ /* And update the free list. */
+ free_binding_nodes = TREE_CHAIN (free_binding_nodes);
+ }
+
+ /* Now, fill in the binding information. */
+ BINDING_VALUE (binding) = decl;
+ BINDING_LEVEL (binding) = level;
+ LOCAL_BINDING_P (binding) = (level != class_binding_level);
+
+ /* And put it on the front of the ilst of bindings for ID. */
+ TREE_CHAIN (binding) = IDENTIFIER_BINDING (id);
+ IDENTIFIER_BINDING (id) = binding;
+}
+
+/* Bind DECL to ID in the current_binding_level. */
+
+void
+push_local_binding (id, decl)
+ tree id;
+ tree decl;
+{
+ tree d = decl;;
+
+ if (TREE_CODE (decl) == OVERLOAD)
+ /* We must put the OVERLOAD into a TREE_LIST since the
+ TREE_CHAIN of an OVERLOAD is already used. */
+ decl = build_tree_list (NULL_TREE, decl);
+
+ /* Create a binding, hanging off of ID. */
+ push_binding (id, d, current_binding_level);
+
+ /* And put DECL on the list of things declared by the current
+ binding level. */
+ TREE_CHAIN (decl) = current_binding_level->names;
+ current_binding_level->names = decl;
+}
+
+/* Bind DECL to ID in the class_binding_level. */
+
+void
+push_class_binding (id, decl)
+ tree id;
+ tree decl;
+{
+ push_binding (id, decl, class_binding_level);
+}
+
+/* Remove the innermost binding for ID; it has gone out of scope. */
+
+static void
+pop_binding (id)
+ tree id;
+{
+ tree binding;
+
+ if (id == NULL_TREE)
+ /* It's easiest to write the loops that call this function without
+ checking whether or not the entities involved have names. We
+ get here for such an entity. */
+ return;
+
+ my_friendly_assert (IDENTIFIER_BINDING (id) != NULL_TREE, 0);
+
+ /* Unhook the innermost binding from the list of bindings. */
+ binding = IDENTIFIER_BINDING (id);
+ IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
+
+ /* And place this list node on the free list. */
+ TREE_CHAIN (binding) = free_binding_nodes;
+ free_binding_nodes = binding;
+}
+
/* Exit a binding level.
Pop the level off, and restore the state of the identifier-decl mappings
that were in effect when this level was entered.
@@ -1063,6 +1171,13 @@ poplevel (keep, reverse, functionbody)
tree block = NULL_TREE;
tree decl;
int block_previously_created;
+ int leaving_for_scope;
+
+ if (current_binding_level->parm_flag == 2
+ || current_binding_level->class_shadowed)
+ /* We should not be using poplevel to pop a class binding level.
+ Use poplevel_class instead. */
+ my_friendly_abort (0);
/* We used to use KEEP == 2 to indicate that the new block should go
at the beginning of the list of blocks at this binding level,
@@ -1127,9 +1242,8 @@ poplevel (keep, reverse, functionbody)
if (decls || tags || subblocks)
{
if (BLOCK_VARS (block) || BLOCK_TYPE_TAGS (block))
- {
- warning ("internal compiler error: debugging info corrupted");
- }
+ warning ("internal compiler error: debugging info corrupted");
+
BLOCK_VARS (block) = decls;
BLOCK_TYPE_TAGS (block) = tags;
@@ -1148,7 +1262,8 @@ poplevel (keep, reverse, functionbody)
BLOCK_VARS (block) = decls;
BLOCK_TYPE_TAGS (block) = tags;
BLOCK_SUBBLOCKS (block) = subblocks;
- /* Otherwise, for a new block, install a new BLOCK_END_NOTE value. */
+ /* Otherwise, for a new block, install a new BLOCK_END_NOTE
+ value. */
remember_end_note (block);
}
}
@@ -1159,92 +1274,116 @@ poplevel (keep, reverse, functionbody)
for (link = subblocks; link; link = TREE_CHAIN (link))
BLOCK_SUPERCONTEXT (link) = block;
- /* Clear out the meanings of the local variables of this level. */
-
- if (current_binding_level->is_for_scope && flag_new_for_scope == 1)
- {
- struct binding_level *outer = current_binding_level->level_chain;
- for (link = decls; link; link = TREE_CHAIN (link))
- {
- if (TREE_CODE (link) == VAR_DECL)
- DECL_DEAD_FOR_LOCAL (link) = 1;
+ /* We still support the old for-scope rules, whereby the variables
+ in a for-init statement were in scope after the for-statement
+ ended. We only use the new rules in flag_new_for_scope is
+ nonzero. */
+ leaving_for_scope
+ = current_binding_level->is_for_scope && flag_new_for_scope == 1;
+
+ /* Remove declarations for all the DECLs in this level. */
+ for (link = decls; link; link = TREE_CHAIN (link))
+ {
+ if (leaving_for_scope && TREE_CODE (link) == VAR_DECL)
+ {
+ tree outer_binding
+ = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (link)));
+ tree ns_binding;
+
+ if (!outer_binding)
+ ns_binding = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (link));
+
+ if (outer_binding
+ && (BINDING_LEVEL (outer_binding)
+ == current_binding_level->level_chain))
+ /* We have something like:
+
+ int i;
+ for (int i; ;);
+
+ and we are leaving the `for' scope. There's no reason to
+ keep the binding of the inner `i' in this case. */
+ pop_binding (DECL_NAME (link));
+ else if ((outer_binding
+ && (TREE_CODE (BINDING_VALUE (outer_binding))
+ == TYPE_DECL))
+ || (ns_binding
+ && TREE_CODE (ns_binding) == TYPE_DECL))
+ /* Here, we have something like:
+
+ typedef int I;
+
+ void f () {
+ for (int I; ;);
+ }
+
+ We must pop the for-scope binding so we know what's a
+ type and what isn't. */
+ pop_binding (DECL_NAME (link));
else
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE;
- }
-
- /* Save declarations made in a 'for' statement so we can support pre-ANSI
- 'for' scoping semantics. */
-
- for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
- {
- tree id = TREE_PURPOSE (link);
- tree decl = IDENTIFIER_LOCAL_VALUE (id);
-
- if (decl && DECL_DEAD_FOR_LOCAL (decl))
{
- /* In this case keep the dead for-decl visible,
- but remember what (if anything) it shadowed. */
- DECL_SHADOWED_FOR_VAR (decl) = TREE_VALUE (link);
- TREE_CHAIN (decl) = outer->dead_vars_from_for;
- outer->dead_vars_from_for = decl;
+ /* Mark this VAR_DECL as dead so that we can tell we left it
+ there only for backward compatibility. */
+ DECL_DEAD_FOR_LOCAL (link) = 1;
+
+ /* Keep track of what should of have happenned when we
+ popped the binding. */
+ if (outer_binding && BINDING_VALUE (outer_binding))
+ DECL_SHADOWED_FOR_VAR (link)
+ = BINDING_VALUE (outer_binding);
+
+ /* Add it to the list of dead variables in the next
+ outermost binding to that we can remove these when we
+ leave that binding. */
+ current_binding_level->level_chain->dead_vars_from_for
+ = tree_cons (NULL_TREE, link,
+ current_binding_level->level_chain->
+ dead_vars_from_for);
+
+ /* Although we don't pop the CPLUS_BINDING, we do clear
+ its BINDING_LEVEL since the level is going away now. */
+ BINDING_LEVEL (IDENTIFIER_BINDING (DECL_NAME (link)))
+ = 0;
}
- else
- IDENTIFIER_LOCAL_VALUE (id) = TREE_VALUE (link);
}
- }
- else /* Not special for scope. */
- {
- for (link = decls; link; link = TREE_CHAIN (link))
+ else
{
- if (DECL_NAME (link) != NULL_TREE)
- {
- /* If the ident. was used or addressed via a local extern decl,
- don't forget that fact. */
- if (DECL_EXTERNAL (link))
- {
- if (TREE_USED (link))
- TREE_USED (DECL_ASSEMBLER_NAME (link)) = 1;
- if (TREE_ADDRESSABLE (link))
- TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
- }
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE;
- }
+ /* Remove the binding. */
+ if (TREE_CODE_CLASS (TREE_CODE (link)) == 'd')
+ pop_binding (DECL_NAME (link));
+ else if (TREE_CODE (link) == TREE_LIST)
+ pop_binding (DECL_NAME (OVL_FUNCTION (TREE_VALUE (link))));
+ else
+ my_friendly_abort (0);
}
+ }
- /* Restore all name-meanings of the outer levels
- that were shadowed by this level. */
-
- for (link = current_binding_level->shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
-
- /* We first restore the regular decls and *then* the dead_vars_from_for
- to handle this case:
-
- int i; // i#1
- {
- for (int i; ; ) { ...} // i#2
- int i; // i#3
- } // we are here
-
- In this case, we want remove the binding for i#3, restoring
- that of i#2. Then we want to remove the binding for i#2,
- and restore that of i#1. */
+ /* Remove declarations for any `for' variables from inner scopes
+ that we kept around. */
+ for (link = current_binding_level->dead_vars_from_for;
+ link; link = TREE_CHAIN (link))
+ pop_binding (DECL_NAME (TREE_VALUE (link)));
- link = current_binding_level->dead_vars_from_for;
- for (; link != NULL_TREE; link = TREE_CHAIN (link))
- {
- tree id = DECL_NAME (link);
- if (IDENTIFIER_LOCAL_VALUE (id) == link)
- IDENTIFIER_LOCAL_VALUE (id) = DECL_SHADOWED_FOR_VAR (link);
- }
+ /* Restore the IDENTIFIER_TYPE_VALUEs. */
+ for (link = current_binding_level->type_shadowed;
+ link; link = TREE_CHAIN (link))
+ SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
+
+ /* There may be OVERLOADs (wrapped in TREE_LISTs) on the BLOCK_VARs
+ list if a `using' declaration put them there. The debugging
+ back-ends won't understand OVERLOAD, so we remove them here.
+ Because the BLOCK_VARS are (temporarily) shared with
+ CURRENT_BINDING_LEVEL->NAMES we must do this fixup after we have
+ popped all the bindings. */
+ if (block)
+ {
+ tree* d;
- for (link = current_binding_level->class_shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->type_shadowed;
- link; link = TREE_CHAIN (link))
- SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
+ for (d = &BLOCK_VARS (block);
+ *d;
+ d = *d ? &TREE_CHAIN (*d) : d)
+ if (TREE_CODE (*d) == TREE_LIST)
+ *d = TREE_CHAIN (*d);
}
/* If the level being exited is the top level of a function,
@@ -1407,9 +1546,7 @@ pushlevel_class ()
free_binding_level = free_binding_level->level_chain;
}
else
- {
- newlevel = make_binding_level ();
- }
+ newlevel = make_binding_level ();
#if defined(DEBUG_CP_BINDING_LEVELS)
is_class_level = 1;
@@ -1444,8 +1581,6 @@ poplevel_class (force)
my_friendly_assert (level != 0, 354);
decl_stack = pop_stack_level (decl_stack);
- for (shadowed = level->shadowed; shadowed; shadowed = TREE_CHAIN (shadowed))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed);
/* If we're leaving a toplevel class, don't bother to do the setting
of IDENTIFIER_CLASS_VALUE to NULL_TREE, since first of all this slot
shouldn't even be used when current_class_type isn't set, and second,
@@ -1468,6 +1603,12 @@ poplevel_class (force)
shadowed = TREE_CHAIN (shadowed))
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed), TREE_VALUE (shadowed));
+ /* Remove the bindings for all of the class-level declarations. */
+ for (shadowed = level->class_shadowed;
+ shadowed;
+ shadowed = TREE_CHAIN (shadowed))
+ pop_binding (TREE_PURPOSE (shadowed));
+
GNU_xref_end_scope ((HOST_WIDE_INT) class_binding_level,
(HOST_WIDE_INT) class_binding_level->level_chain,
class_binding_level->parm_flag,
@@ -1574,15 +1715,6 @@ print_binding_level (lvl)
if (i)
fprintf (stderr, "\n");
}
- if (lvl->shadowed)
- {
- fprintf (stderr, " shadowed:");
- for (t = lvl->shadowed; t; t = TREE_CHAIN (t))
- {
- fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t)));
- }
- fprintf (stderr, "\n");
- }
if (lvl->class_shadowed)
{
fprintf (stderr, " class-shadowed:");
@@ -1932,9 +2064,11 @@ store_bindings (names, old_bindings)
else
id = DECL_NAME (t);
- if (!id
- || (!IDENTIFIER_LOCAL_VALUE (id)
- && !IDENTIFIER_CLASS_VALUE (id)))
+ 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)))
continue;
for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1))
@@ -1954,9 +2088,9 @@ store_bindings (names, old_bindings)
my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
TREE_VEC_ELT (binding, 0) = id;
TREE_VEC_ELT (binding, 1) = REAL_IDENTIFIER_TYPE_VALUE (id);
- TREE_VEC_ELT (binding, 2) = IDENTIFIER_LOCAL_VALUE (id);
+ TREE_VEC_ELT (binding, 2) = IDENTIFIER_BINDING (id);
TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
- IDENTIFIER_LOCAL_VALUE (id) = NULL_TREE;
+ IDENTIFIER_BINDING (id) = NULL_TREE;
IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
}
TREE_CHAIN (binding) = old_bindings;
@@ -2085,7 +2219,7 @@ pop_from_top_level ()
if (id)
{
SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1));
- IDENTIFIER_LOCAL_VALUE (id) = TREE_VEC_ELT (t, 2);
+ IDENTIFIER_BINDING (id) = TREE_VEC_ELT (t, 2);
IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
}
t = TREE_CHAIN (t);
@@ -2169,26 +2303,6 @@ set_identifier_type_value (id, type)
set_identifier_type_value_with_scope (id, type, inner_binding_level);
}
-static void
-set_identifier_local_value_with_scope (id, val, b)
- tree id, val;
- struct binding_level *b;
-{
- tree oldlocal;
- my_friendly_assert (! b->namespace_p, 980716);
-
- oldlocal = IDENTIFIER_LOCAL_VALUE (id);
- b->shadowed = tree_cons (id, oldlocal, b->shadowed);
- IDENTIFIER_LOCAL_VALUE (id) = val;
-}
-
-void
-set_identifier_local_value (id, val)
- tree id, val;
-{
- set_identifier_local_value_with_scope (id, val, current_binding_level);
-}
-
/* Return the type associated with id. */
tree
@@ -3322,14 +3436,14 @@ pushdecl (x)
{
register tree t;
register tree name = DECL_ASSEMBLER_NAME (x);
- register struct binding_level *b = current_binding_level;
+ int need_new_binding = 1;
if (current_function_decl && x != current_function_decl
/* A local declaration for a function doesn't constitute nesting. */
&& (TREE_CODE (x) != FUNCTION_DECL || DECL_INITIAL (x))
/* Don't change DECL_CONTEXT of virtual methods. */
&& (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x))
- && ! DECL_CONTEXT (x))
+ && !DECL_CONTEXT (x))
DECL_CONTEXT (x) = current_function_decl;
if (!DECL_CONTEXT (x))
DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace);
@@ -3459,6 +3573,11 @@ pushdecl (x)
t = push_overloaded_decl (x, 1);
if (t != x || DECL_LANGUAGE (x) == lang_c)
return t;
+ if (!namespace_bindings_p ())
+ /* We do not need to create a binding for this name;
+ push_overloaded_decl will have already done so if
+ necessary. */
+ need_new_binding = 0;
}
else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x))
return push_overloaded_decl (x, 0);
@@ -3495,7 +3614,15 @@ pushdecl (x)
if (type != error_mark_node
&& TYPE_NAME (type)
&& TYPE_IDENTIFIER (type))
- set_identifier_type_value_with_scope (DECL_NAME (x), type, b);
+ set_identifier_type_value_with_scope (DECL_NAME (x), type,
+ current_binding_level);
+
+ if (TREE_CODE (x) == TYPE_DECL
+ && DECL_ARTIFICIAL (x)
+ && t != NULL_TREE)
+ /* We don't want an artificial TYPE_DECL is we already
+ have another DECL with the same name. */
+ need_new_binding = 0;
}
/* Multiple external decls of the same identifier ought to match.
@@ -3536,11 +3663,7 @@ pushdecl (x)
if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
TREE_PUBLIC (name) = 1;
- /* Don't install an artificial TYPE_DECL if we already have
- another _DECL with that name. */
- if (TREE_CODE (x) != TYPE_DECL
- || t == NULL_TREE
- || ! DECL_ARTIFICIAL (x))
+ if (need_new_binding)
{
if (TREE_CODE (x) == FUNCTION_DECL)
my_friendly_assert
@@ -3575,25 +3698,29 @@ pushdecl (x)
else
{
/* Here to install a non-global value. */
- tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
+ tree oldlocal = IDENTIFIER_VALUE (name);
tree oldglobal = IDENTIFIER_NAMESPACE_VALUE (name);
- /* Don't install an artificial TYPE_DECL if we already have
- another _DECL with that name. */
- if (TREE_CODE (x) != TYPE_DECL
- || t == NULL_TREE
- || ! DECL_ARTIFICIAL (x))
- set_identifier_local_value_with_scope (name, x, b);
+ if (need_new_binding)
+ {
+ push_local_binding (name, x);
+ /* Because push_local_binding will hook X on to the
+ current_binding_level's name list, we don't want to
+ do that again below. */
+ need_new_binding = 0;
+ }
/* If this is a TYPE_DECL, push it into the type value slot. */
if (TREE_CODE (x) == TYPE_DECL)
- set_identifier_type_value_with_scope (name, TREE_TYPE (x), b);
+ set_identifier_type_value_with_scope (name, TREE_TYPE (x),
+ current_binding_level);
/* Clear out any TYPE_DECL shadowed by a namespace so that
we won't think this is a type. The C struct hack doesn't
go through namespaces. */
if (TREE_CODE (x) == NAMESPACE_DECL)
- set_identifier_type_value_with_scope (name, NULL_TREE, b);
+ set_identifier_type_value_with_scope (name, NULL_TREE,
+ current_binding_level);
/* If this is an extern function declaration, see if we
have a global definition or declaration for the function. */
@@ -3619,9 +3746,7 @@ pushdecl (x)
&& oldglobal == NULL_TREE
&& DECL_EXTERNAL (x)
&& TREE_PUBLIC (x))
- {
- TREE_PUBLIC (name) = 1;
- }
+ TREE_PUBLIC (name) = 1;
if (DECL_FROM_INLINE (x))
/* Inline decls shadow nothing. */;
@@ -3642,7 +3767,8 @@ pushdecl (x)
if (b->parm_flag == 1)
cp_error ("declaration of `%#D' shadows a parameter", name);
}
- else if (warn_shadow && oldlocal != NULL_TREE && b->is_for_scope
+ else if (warn_shadow && oldlocal != NULL_TREE
+ && current_binding_level->is_for_scope
&& !DECL_DEAD_FOR_LOCAL (oldlocal))
{
warning ("variable `%s' shadows local",
@@ -3686,15 +3812,20 @@ pushdecl (x)
/* RTTI TD entries are created while defining the type_info. */
|| (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
&& TYPE_BEING_DEFINED (TREE_TYPE (x)))))
- b->incomplete = tree_cons (NULL_TREE, x, b->incomplete);
+ current_binding_level->incomplete
+ = tree_cons (NULL_TREE, x, current_binding_level->incomplete);
}
- /* Put decls on list in reverse order.
- We will reverse them later if necessary. */
- TREE_CHAIN (x) = b->names;
- b->names = x;
- if (! (b != global_binding_level || TREE_PERMANENT (x)))
- my_friendly_abort (124);
+ if (need_new_binding)
+ {
+ /* Put decls on list in reverse order.
+ We will reverse them later if necessary. */
+ TREE_CHAIN (x) = current_binding_level->names;
+ current_binding_level->names = x;
+ if (! (current_binding_level != global_binding_level
+ || TREE_PERMANENT (x)))
+ my_friendly_abort (124);
+ }
return x;
}
@@ -3828,9 +3959,7 @@ pushdecl_class_level (x)
push_class_level_binding (name, x);
if (TREE_CODE (x) == TYPE_DECL)
- {
- set_identifier_type_value (name, TREE_TYPE (x));
- }
+ set_identifier_type_value (name, TREE_TYPE (x));
}
}
@@ -3874,12 +4003,20 @@ push_class_level_binding (name, x)
&& purpose_member (name, class_binding_level->class_shadowed))
return;
+ /* If this declaration shadows a declaration from an enclosing
+ class, then we will need to restore IDENTIFIER_CLASS_VALUE when
+ we leave this class. Record the shadowed declaration here. */
maybe_push_cache_obstack ();
class_binding_level->class_shadowed
= tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
class_binding_level->class_shadowed);
pop_obstacks ();
+
+ /* Put the binding on the stack of bindings for the identifier, and
+ update IDENTIFIER_CLASS_VALUE. */
+ push_class_binding (name, x);
IDENTIFIER_CLASS_VALUE (name) = x;
+
obstack_ptr_grow (&decl_obstack, x);
}
@@ -3934,11 +4071,11 @@ push_using_directive (used)
return ud;
}
-/* DECL is a FUNCTION_DECL which may have other definitions already in
- place. We get around this by making the value of the identifier point
- to a list of all the things that want to be referenced by that name. It
- is then up to the users of that name to decide what to do with that
- list.
+/* DECL is a FUNCTION_DECL for a non-member function, which may have
+ other definitions already in place. We get around this by making
+ the value of the identifier point to a list of all the things that
+ want to be referenced by that name. It is then up to the users of
+ that name to decide what to do with that list.
DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its DECL_RESULT
slot. It is dealt with the same way.
@@ -3952,13 +4089,14 @@ push_overloaded_decl (decl, forgettable)
tree decl;
int forgettable;
{
- tree orig_name = DECL_NAME (decl);
+ tree name = DECL_NAME (decl);
tree old;
+ tree new_binding;
int doing_global = (namespace_bindings_p () || ! forgettable);
if (doing_global)
{
- old = namespace_binding (orig_name, DECL_CONTEXT (decl));
+ old = namespace_binding (name, DECL_CONTEXT (decl));
if (old && TREE_CODE (old) == FUNCTION_DECL
&& DECL_ARTIFICIAL (old)
&& (DECL_BUILT_IN (old) || DECL_BUILT_IN_NONANSI (old)))
@@ -3969,16 +4107,7 @@ push_overloaded_decl (decl, forgettable)
}
}
else
- {
- old = IDENTIFIER_LOCAL_VALUE (orig_name);
-
- if (! purpose_member (orig_name, current_binding_level->shadowed))
- {
- current_binding_level->shadowed
- = tree_cons (orig_name, old, current_binding_level->shadowed);
- old = NULL_TREE;
- }
- }
+ old = lookup_name_current_level (name);
if (old)
{
@@ -4011,17 +4140,44 @@ push_overloaded_decl (decl, forgettable)
if (old || TREE_CODE (decl) == TEMPLATE_DECL)
{
if (old && TREE_CODE (old) != OVERLOAD)
- old = ovl_cons (old, NULL_TREE);
- old = ovl_cons (decl, old);
+ new_binding = ovl_cons (decl, ovl_cons (old, NULL_TREE));
+ else
+ new_binding = ovl_cons (decl, old);
}
else
- /* orig_name is not ambiguous. */
- old = decl;
+ /* NAME is not ambiguous. */
+ new_binding = decl;
if (doing_global)
- set_namespace_binding (orig_name, current_namespace, old);
+ set_namespace_binding (name, current_namespace, new_binding);
else
- IDENTIFIER_LOCAL_VALUE (orig_name) = old;
+ {
+ /* We only create an OVERLOAD if there was a previous binding at
+ this level. In that case, we need to remove the old binding
+ and replace it with the new binding. We must also run
+ through the NAMES on the current binding level to update the
+ chain. */
+ if (TREE_CODE (new_binding) == OVERLOAD)
+ {
+ tree *d;
+
+ for (d = &BINDING_LEVEL (IDENTIFIER_BINDING (name))->names;
+ *d;
+ d = &TREE_CHAIN (*d))
+ if (*d == old
+ || (TREE_CODE (*d) == TREE_LIST
+ && TREE_VALUE (*d) == old))
+ {
+ *d = TREE_CHAIN (*d);
+ break;
+ }
+
+ pop_binding (name);
+ }
+
+ /* Install the new binding. */
+ push_local_binding (name, new_binding);
+ }
return decl;
}
@@ -5073,7 +5229,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
register tree val;
int yylex = 0;
tree from_obj = NULL_TREE;
- tree locval, classval;
int flags;
/* Hack: copy flag set by parser, if set. */
@@ -5166,140 +5321,86 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
else
flags = lookup_flags (prefer_type, namespaces_only);
- locval = classval = NULL_TREE;
-
- if (! namespace_bindings_p () && IDENTIFIER_LOCAL_VALUE (name))
- {
- locval = qualify_lookup (IDENTIFIER_LOCAL_VALUE (name), flags);
+ /* First, look in a non-global scope, carefully avoiding any
+ class-scope bindings if required. */
+ val = IDENTIFIER_BINDING (name);
+ while (val && nonclass && !LOCAL_BINDING_P (val))
+ val = TREE_CHAIN (val);
- /* Kludge kludge kludge */
- if (locval == NULL_TREE && prefer_type)
- {
- locval = REAL_IDENTIFIER_TYPE_VALUE (name);
- if (locval && locval != global_type_node
- && TYPE_NAME (locval)
- && DECL_FUNCTION_SCOPE_P (TYPE_NAME (locval)))
- locval = TYPE_NAME (locval);
- else
- locval = NULL_TREE;
- }
- }
-
- /* In C++ class fields are between local and global scope,
- just before the global scope. */
- if (current_class_type && ! nonclass)
- {
- classval = IDENTIFIER_CLASS_VALUE (name);
- if (classval == NULL_TREE && TYPE_BEING_DEFINED (current_class_type))
- /* Try to find values from base classes if we are presently
- defining a type. We are primarily interested in
- TYPE_DECLs or constants. */
- classval = lookup_field (current_class_type, name, 0, prefer_type);
-
- /* Add implicit 'typename' to types from template bases. lookup_field
- will do this for us. If classval is actually from an enclosing
- scope, lookup_nested_field will get it for us. */
- else if (processing_template_decl
- && classval && TREE_CODE (classval) == TYPE_DECL
- && ! currently_open_class (DECL_CONTEXT (classval))
- && uses_template_parms (current_class_type))
- classval = lookup_field (current_class_type, name, 0, 1);
-
- /* yylex() calls this with -2, since we should never start digging for
- the nested name at the point where we haven't even, for example,
- created the COMPONENT_REF or anything like that. */
- if (classval == NULL_TREE)
- classval = lookup_nested_field (name, ! yylex);
-
- classval = qualify_lookup (classval, flags);
+ /* Get the DECL actually bound. */
+ if (val)
+ val = BINDING_VALUE (val);
+
+ /* If VAL is a type from a dependent base, we're not really supposed
+ to be able to see it; the fact that we can is the "implicit
+ typename" extension. We call lookup_field here to turn VAL into
+ a TYPE_DECL for a TYPENAME_TYPE. */
+ if (processing_template_decl && val
+ && val == IDENTIFIER_CLASS_VALUE (name)
+ && TREE_CODE (val) == TYPE_DECL
+ && !currently_open_class (DECL_CONTEXT (val))
+ && uses_template_parms (current_class_type))
+ val = lookup_field (current_class_type, name, 0, 1);
+
+ /* Make sure that this binding is the sort of thing we're looking
+ for. */
+ val = qualify_lookup (val, flags);
+
+ /* We don't put names from baseclasses onto the IDENTIFIER_BINDING
+ list when we're defining a type. It would probably be simpler to
+ do this, but we don't. So, we must lookup names from base
+ classes explicitly. */
+ if (!val && !nonclass
+ && current_class_type && TYPE_BEING_DEFINED (current_class_type))
+ {
+ val = qualify_lookup (lookup_field (current_class_type, name, 0, 0),
+ flags);
+ if (!val)
+ val = qualify_lookup (lookup_nested_field (name, !yylex),
+ flags);
}
-
- if (locval && classval)
+
+ /* If we found a type from a dependent base class (using the
+ implicit typename extension), turn it into the TYPE_DECL for a
+ TYPENAME_TYPE here. */
+ if (val && TREE_CODE (val) == TYPE_DECL
+ && IMPLICIT_TYPENAME_P (TREE_TYPE (val)))
{
- /* We have both a local binding and a class-level binding. This
- can happen in two ways:
+ tree global_val;
- o We are in a member function of a class.
- o We are in a local class within a function.
+ /* Any other name takes precedence over an implicit typename. Warn the
+ user about this potentially confusing lookup. */
+ global_val = unqualified_namespace_lookup (name, flags);
- We need to determine which one of these situations is
- occuring, and give the innermost binding. One tricky bit is
- that with member templates we can be in the first case
- without CURRENT_FUNCTION_DECL being set. Consider
-
- struct A { template <class A> void f(A); };
-
- Here, when we look at the `A' in the parameter declaration
- for `f' we have a local binding (the template parameter) and
- a class-level binding (the TYPE_DECL for the class).
- Fortunately, if LOCVAL is a template parameter it is safe to
- take it; nothing within the scope of the template parameter
- is allowed to have the same name. */
-
- if (decl_template_parm_p (locval))
- val = locval;
- else if (current_scope () == current_function_decl
- && ! hack_decl_function_context (current_function_decl))
- /* Not in a nested function. */
- val = locval;
- else
- {
- /* This is incredibly horrible. The whole concept of
- IDENTIFIER_LOCAL_VALUE / IDENTIFIER_CLASS_VALUE /
- IDENTIFIER_GLOBAL_VALUE needs to be scrapped for local
- classes. */
- tree lctx = hack_decl_function_context (locval);
- tree cctx = hack_decl_function_context (classval);
-
- if (lctx == current_scope ())
- val = locval;
- else if (lctx == cctx)
- val = classval;
- else
- /* I don't know which is right; let's just guess for now. */
- val = locval;
- }
- }
- else if (locval)
- val = locval;
- else if (classval)
- val = classval;
- else
- val = unqualified_namespace_lookup (name, flags);
-
- /* Any other name takes precedence over an implicit typename. Warn the
- user about this potentially confusing lookup. */
- if (classval && TREE_CODE (val) == TYPE_DECL
- && TREE_CODE (TREE_TYPE (val)) == TYPENAME_TYPE
- && TREE_TYPE (TREE_TYPE (val)))
- {
- if (locval == NULL_TREE)
- locval = unqualified_namespace_lookup (name, flags);
-
- if (locval && val != locval)
+ if (global_val)
{
tree subtype;
- val = locval;
-
/* Only warn when not lexing; we don't want to warn if they
use this name as a declarator. */
- subtype = TREE_TYPE (TREE_TYPE (classval));
+ subtype = TREE_TYPE (TREE_TYPE (val));
if (! yylex
- && ! (TREE_CODE (locval) == TEMPLATE_DECL
+ && ! (TREE_CODE (global_val) == TEMPLATE_DECL
&& CLASSTYPE_TEMPLATE_INFO (subtype)
- && CLASSTYPE_TI_TEMPLATE (subtype) == locval)
- && ! (TREE_CODE (locval) == TYPE_DECL
- && same_type_p (TREE_TYPE (locval), subtype)))
+ && CLASSTYPE_TI_TEMPLATE (subtype) == global_val)
+ && ! (TREE_CODE (global_val) == TYPE_DECL
+ && same_type_p (TREE_TYPE (global_val), subtype)))
{
- cp_warning ("lookup of `%D' finds `%#D'", name, locval);
+ cp_warning ("lookup of `%D' finds `%#D'", name, global_val);
cp_warning (" instead of `%D' from dependent base class",
- classval);
+ val);
cp_warning (" (use `typename %T::%D' if that's what you meant)",
constructor_name (current_class_type), name);
}
+
+ /* Use the global value instead of the implicit typename. */
+ val = global_val;
}
}
+ else if (!val)
+ /* No local, or class-scoped binding. Look for a namespace-scope
+ declaration. */
+ val = unqualified_namespace_lookup (name, flags);
done:
if (val)
@@ -5381,13 +5482,16 @@ lookup_name_current_level (name)
if (t != NULL_TREE && TREE_CODE (t) == TREE_LIST)
t = TREE_VALUE (t);
}
- else if (IDENTIFIER_LOCAL_VALUE (name) != NULL_TREE)
+ else if (IDENTIFIER_BINDING (name)
+ && LOCAL_BINDING_P (IDENTIFIER_BINDING (name)))
{
struct binding_level *b = current_binding_level;
+
while (1)
{
- if (purpose_member (name, b->shadowed))
- return IDENTIFIER_LOCAL_VALUE (name);
+ if (BINDING_LEVEL (IDENTIFIER_BINDING (name)) == b)
+ return IDENTIFIER_VALUE (name);
+
if (b->keep == 2)
b = b->level_chain;
else
@@ -7681,7 +7785,8 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
if (current_binding_level->is_for_scope)
{
- struct binding_level *outer = current_binding_level->level_chain;
+ struct binding_level *outer
+ = current_binding_level->level_chain;
/* Check to see if the same name is already bound at
the outer level, either because it was directly declared,
@@ -7693,36 +7798,20 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
Otherwise, we need to preserve the temp slot for decl
to last into the outer binding level. */
- int handling_dead_for_vars = 0;
- tree link = outer->names;
- for (; ; link = TREE_CHAIN (link))
+ tree outer_binding
+ = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (decl)));
+
+ if (outer_binding && BINDING_LEVEL (outer_binding) == outer
+ && (TREE_CODE (BINDING_VALUE (outer_binding))
+ == VAR_DECL)
+ && DECL_DEAD_FOR_LOCAL (BINDING_VALUE (outer_binding)))
{
- if (link == NULL && handling_dead_for_vars == 0)
- {
- link = outer->dead_vars_from_for;
- handling_dead_for_vars = 1;
- }
- if (link == NULL)
- {
- if (DECL_IN_MEMORY_P (decl))
- preserve_temp_slots (DECL_RTL (decl));
- break;
- }
- if (DECL_NAME (link) == DECL_NAME (decl))
- {
- if (handling_dead_for_vars)
- {
- tree shadowing
- = purpose_member (DECL_NAME (decl),
- current_binding_level->shadowed);
- if (shadowing && TREE_VALUE (shadowing) == link)
- TREE_VALUE (shadowing)
- = DECL_SHADOWED_FOR_VAR (link);
- }
- current_binding_level->is_for_scope = 0;
- break;
- }
+ BINDING_VALUE (outer_binding)
+ = DECL_SHADOWED_FOR_VAR (BINDING_VALUE (outer_binding));
+ current_binding_level->is_for_scope = 0;
}
+ else if (DECL_IN_MEMORY_P (decl))
+ preserve_temp_slots (DECL_RTL (decl));
}
expand_start_target_temps ();
@@ -11032,18 +11121,14 @@ parmlist_is_exprlist (exprs)
return 1;
}
-/* Subroutine of `grokparms'. In a fcn definition, arg types must
- be complete.
-
- C++: also subroutine of `start_function'. */
+/* Subroutine of start_function. Ensure that each of the parameter
+ types (as listed in PARMS) is complete, as is required for a
+ function definition. */
static void
require_complete_types_for_parms (parms)
tree parms;
{
- if (processing_template_decl)
- return;
-
while (parms)
{
tree type = TREE_TYPE (parms);
@@ -11058,31 +11143,7 @@ require_complete_types_for_parms (parms)
}
else
layout_decl (parms, 0);
-#if 0
- /* If the arg types are incomplete in a declaration,
- they must include undefined tags.
- These tags can never be defined in the scope of the declaration,
- so the types can never be completed,
- and no call can be compiled successfully. */
- /* This is not the right behavior for C++, but not having
- it is also probably wrong. */
- else
- {
- /* Now warn if is a pointer to an incomplete type. */
- while (TREE_CODE (type) == POINTER_TYPE
- || TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
- type = TYPE_MAIN_VARIANT (type);
- if (TYPE_SIZE (type) == NULL_TREE)
- {
- if (DECL_NAME (parm) != NULL_TREE)
- warning ("parameter `%s' points to incomplete type",
- IDENTIFIER_POINTER (DECL_NAME (parm)));
- else
- warning ("parameter points to incomplete type");
- }
- }
-#endif
+
parms = TREE_CHAIN (parms);
}
}
@@ -11276,16 +11337,20 @@ grokparms (first_parm, funcdef_flag)
/* Unparsed default arg from in-class decl. */
else if (TREE_CODE (init) == DEFAULT_ARG)
;
- else if (TREE_CODE (init) == VAR_DECL
- || TREE_CODE (init) == PARM_DECL)
+ else if (TREE_CODE (init) == PARM_DECL
+ || TREE_CODE (init) == VAR_DECL)
{
- if (IDENTIFIER_LOCAL_VALUE (DECL_NAME (init)))
+ if (TREE_CODE (init) == VAR_DECL
+ && (IDENTIFIER_VALUE (DECL_NAME (init))
+ == init)
+ && LOCAL_BINDING_P
+ (IDENTIFIER_BINDING (DECL_NAME
+ (init))))
{
- /* ``Local variables may not be used in default
- argument expressions.'' dpANSI C++ 8.2.6 */
- /* If extern int i; within a function is not
- considered a local variable, then this code is
- wrong. */
+ /* ``Local variables may not be used in
+ default argument expressions.''
+ dpANSI C++ 8.2.6 */
+
cp_error ("local variable `%D' may not be used as a default argument", init);
any_error = 1;
}
@@ -11349,10 +11414,6 @@ grokparms (first_parm, funcdef_flag)
last_function_parms = decls;
- /* In a fcn definition, arg types must be complete. */
- if (funcdef_flag > 0)
- require_complete_types_for_parms (last_function_parms);
-
return result;
}
@@ -11417,20 +11478,45 @@ grok_ctor_properties (ctype, decl)
parmtype = TREE_VALUE (parmtypes);
}
+ /* [class.copy]
+
+ A non-template constructor for class X is a copy constructor if
+ its first parameter is of type X&, const X&, volatile X& or const
+ volatile X&, and either there are no other parameters or else all
+ other parameters have default arguments. */
if (TREE_CODE (parmtype) == REFERENCE_TYPE
&& TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype
&& (TREE_CHAIN (parmtypes) == NULL_TREE
|| TREE_CHAIN (parmtypes) == void_list_node
- || TREE_PURPOSE (TREE_CHAIN (parmtypes))))
+ || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
+ && !(DECL_TEMPLATE_INSTANTIATION (decl)
+ && is_member_template (DECL_TI_TEMPLATE (decl))))
{
TYPE_HAS_INIT_REF (ctype) = 1;
if (CP_TYPE_CONST_P (TREE_TYPE (parmtype)))
TYPE_HAS_CONST_INIT_REF (ctype) = 1;
}
+ /* [class.copy]
+
+ A declaration of a constructor for a class X is ill-formed if its
+ first parameter is of type (optionally cv-qualified) X and either
+ there are no other parameters or else all other parameters have
+ default arguments.
+
+ We *don't* complain about member template instantiations that
+ have this form, though; they can occur as we try to decide what
+ constructor to use during overload resolution. Since overload
+ resolution will never prefer such a constructor to the
+ non-template copy constructor (which is either explicitly or
+ implicitly defined), there's no need to worry about their
+ existence. Theoretically, they should never even be
+ instantiated, but that's hard to forestall. */
else if (TYPE_MAIN_VARIANT (parmtype) == ctype
&& (TREE_CHAIN (parmtypes) == NULL_TREE
|| TREE_CHAIN (parmtypes) == void_list_node
- || TREE_PURPOSE (TREE_CHAIN (parmtypes))))
+ || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
+ && !(DECL_TEMPLATE_INSTANTIATION (decl)
+ && is_member_template (DECL_TI_TEMPLATE (decl))))
{
cp_error ("invalid constructor; you probably meant `%T (const %T&)'",
ctype, ctype);
@@ -11486,7 +11572,15 @@ grok_op_properties (decl, virtualp, friendp)
if (! friendp)
{
- if (name == ansi_opname[(int) MODIFY_EXPR])
+ /* [class.copy]
+
+ A user-declared copy assignment operator X::operator= is a
+ non-static non-template member function of class X with
+ exactly one parameter of type X, X&, const X&, volatile X& or
+ const volatile X&. */
+ if (name == ansi_opname[(int) MODIFY_EXPR]
+ && !(DECL_TEMPLATE_INSTANTIATION (decl)
+ && is_member_template (DECL_TI_TEMPLATE (decl))))
TYPE_HAS_ASSIGNMENT (current_class_type) = 1;
else if (name == ansi_opname[(int) CALL_EXPR])
TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
@@ -12477,6 +12571,15 @@ static int function_depth;
they describe the function's name and the type it returns,
but twisted together in a fashion that parallels the syntax of C.
+ If PRE_PARSED_P is non-zero then DECLARATOR is really the DECL for
+ the function we are about to process; DECLSPECS are ignored. For
+ example, we set PRE_PARSED_P when processing the definition of
+ inline function that was defined in-class; the definition is
+ actually processed when the class is complete. In this case,
+ PRE_PARSED_P is 2. We also set PRE_PARSED_P when instanting the
+ body of a template function, and when constructing thunk functions
+ and such; in these cases PRE_PARSED_P is 1.
+
This function creates a binding context for the function body
as well as setting up the FUNCTION_DECL in current_function_decl.
@@ -12577,17 +12680,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
doing_friend = 1;
}
- /* In a fcn definition, arg types must be complete. */
- require_complete_types_for_parms (DECL_ARGUMENTS (decl1));
-
- /* In case some arg types were completed since the declaration was
- parsed, fix up the decls. */
- {
- tree t = DECL_ARGUMENTS (decl1);
- for (; t; t = TREE_CHAIN (t))
- layout_decl (t, 0);
- }
-
last_function_parms = DECL_ARGUMENTS (decl1);
last_function_parm_tags = NULL_TREE;
}
@@ -12636,16 +12728,37 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
&& IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE)
cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)));
+ announce_function (decl1);
+
+ /* Set up current_class_type, and enter the scope of the class, if
+ appropriate. */
+ if (ctype)
+ push_nested_class (ctype, 1);
+ else if (DECL_STATIC_FUNCTION_P (decl1))
+ push_nested_class (DECL_CONTEXT (decl1), 2);
+
+ /* Now that we have entered the scope of the class, we must restore
+ the bindings for any template parameters surrounding DECL1, if it
+ is an inline member template. (Order is important; consider the
+ case where a template parameter has the same name as a field of
+ the class.) It is not until after this point that
+ PROCESSING_TEMPLATE_DECL is guaranteed to be set up correctly. */
+ if (pre_parsed_p == 2)
+ maybe_begin_member_template_processing (decl1);
+
+ /* We are now in the scope of the function being defined. */
current_function_decl = decl1;
+
/* Save the parm names or decls from this function's declarator
where store_parm_decls will find them. */
current_function_parms = last_function_parms;
current_function_parm_tags = last_function_parm_tags;
- announce_function (decl1);
-
if (! processing_template_decl)
{
+ /* In a fcn definition, arg types must be complete. */
+ require_complete_types_for_parms (DECL_ARGUMENTS (decl1));
+
if (TYPE_SIZE (complete_type (TREE_TYPE (fntype))) == NULL_TREE)
{
cp_error ("return-type `%#T' is an incomplete type",
@@ -12695,13 +12808,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
- /* Set up current_class_type, and enter the scope of the class, if
- appropriate. */
- if (ctype)
- push_nested_class (ctype, 1);
- else if (DECL_STATIC_FUNCTION_P (decl1))
- push_nested_class (DECL_CONTEXT (decl1), 2);
-
/* We must call push_template_decl after current_class_type is set
up. (If we are processing inline definitions after exiting a
class scope, current_class_type will be NULL_TREE until set above
@@ -12937,9 +13043,6 @@ store_parm_decls ()
/* Initialize RTL machinery. */
init_function_start (fndecl, input_filename, lineno);
- /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
- declare_function_name ();
-
/* Create a binding level for the parms. */
expand_start_bindings (0);
@@ -13025,6 +13128,9 @@ store_parm_decls ()
storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
+ /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
+ declare_function_name ();
+
/* Initialize the RTL code for the function. */
DECL_SAVED_INSNS (fndecl) = NULL_RTX;
if (! processing_template_decl)
@@ -13135,18 +13241,23 @@ store_return_init (return_id, init)
This is called after parsing the body of the function definition.
LINENO is the current line number.
- C++: CALL_POPLEVEL is non-zero if an extra call to poplevel
- (and expand_end_bindings) must be made to take care of the binding
- contour for the base initializers. This is only relevant for
- constructors.
+ FLAGS is a bitwise or of the following values:
+ 1 - CALL_POPLEVEL
+ An extra call to poplevel (and expand_end_bindings) must be
+ made to take care of the binding contour for the base
+ initializers. This is only relevant for constructors.
+ 2 - INCLASS_INLINE
+ We just finished processing the body of an in-class inline
+ function definition. (This processing will have taken place
+ after the class definition is complete.)
NESTED is nonzero if we were in the middle of compiling another function
when we started on this one. */
void
-finish_function (lineno, call_poplevel, nested)
+finish_function (lineno, flags, nested)
int lineno;
- int call_poplevel;
+ int flags;
int nested;
{
register tree fndecl = current_function_decl;
@@ -13155,6 +13266,9 @@ finish_function (lineno, call_poplevel, nested)
/* Label to use if this function is supposed to return a value. */
tree no_return_label = NULL_TREE;
tree decls = NULL_TREE;
+ int call_poplevel = (flags & 1) != 0;
+ int inclass_inline = (flags & 2) != 0;
+ int in_template;
/* When we get some parse errors, we can end up without a
current_function_decl, so cope. */
@@ -13560,6 +13674,27 @@ finish_function (lineno, call_poplevel, nested)
/* Generate rtl for function exit. */
expand_function_end (input_filename, lineno, 1);
}
+
+ /* Must mark the RESULT_DECL as being in this function. */
+ DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
+
+ /* Set the BLOCK_SUPERCONTEXT of the outermost function scope to point
+ to the FUNCTION_DECL node itself. */
+ BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
+
+ /* If we're processing a template, squirrel away the definition
+ until we do an instantiation. */
+ if (processing_template_decl)
+ {
+ --minimal_parse_mode;
+ DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl));
+ /* We have to save this value here in case
+ maybe_end_member_template_processing decides to pop all the
+ template parameters. */
+ in_template = 1;
+ }
+ else
+ in_template = 0;
/* This must come after expand_function_end because cleanups might
have declarations (from inline functions) that need to go into
@@ -13568,6 +13703,13 @@ finish_function (lineno, call_poplevel, nested)
my_friendly_abort (122);
poplevel (1, 0, 1);
+ /* If this is a in-class inline definition, we may have to pop the
+ bindings for the template parameters that we added in
+ maybe_begin_member_template_processing when start_function was
+ called. */
+ if (inclass_inline)
+ maybe_end_member_template_processing ();
+
/* Reset scope for C++: if we were in the scope of a class,
then when we finish this function, we are not longer so.
This cannot be done until we know for sure that no more
@@ -13579,14 +13721,7 @@ finish_function (lineno, call_poplevel, nested)
pop_nested_class (1);
}
- /* Must mark the RESULT_DECL as being in this function. */
- DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
-
- /* Set the BLOCK_SUPERCONTEXT of the outermost function scope to point
- to the FUNCTION_DECL node itself. */
- BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
-
- if (! processing_template_decl)
+ if (!in_template)
{
int saved_flag_keep_inline_functions =
flag_keep_inline_functions;
@@ -13670,12 +13805,6 @@ finish_function (lineno, call_poplevel, nested)
/* Free all the tree nodes making up this function. */
/* Switch back to allocating nodes permanently
until we start another function. */
- if (processing_template_decl)
- {
- --minimal_parse_mode;
- DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl));
- }
-
if (! nested)
permanent_allocation (1);
@@ -13710,8 +13839,6 @@ finish_function (lineno, call_poplevel, nested)
}
/* Create the FUNCTION_DECL for a function definition.
- LINE1 is the line number that the definition absolutely begins on.
- LINE2 is the line number that the name of the function appears on.
DECLSPECS and DECLARATOR are the parts of the declaration;
they describe the return type and the name of the function,
but twisted together in a fashion that parallels the syntax of C.
@@ -13849,23 +13976,11 @@ finish_method (decl)
for (link = current_binding_level->names; link; link = TREE_CHAIN (link))
{
if (DECL_NAME (link) != NULL_TREE)
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
+ pop_binding (DECL_NAME (link));
my_friendly_assert (TREE_CODE (link) != FUNCTION_DECL, 163);
DECL_CONTEXT (link) = NULL_TREE;
}
- /* Restore all name-meanings of the outer levels
- that were shadowed by this level. */
-
- for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
- IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->class_shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- for (link = current_binding_level->type_shadowed;
- link; link = TREE_CHAIN (link))
- SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
-
GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
(HOST_WIDE_INT) current_binding_level->level_chain,
current_binding_level->parm_flag,
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 570d2929ef2..630e262183f 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4829,7 +4829,7 @@ do_local_using_decl (decl)
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
if (newval)
- set_identifier_local_value (name, newval);
+ push_local_binding (name, newval);
if (newtype)
set_identifier_type_value (name, newtype);
}
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 45d3d41c3c9..e6dd29fe31a 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -84,6 +84,7 @@ static int reduce_cmp PROTO((int *, int *));
static int token_cmp PROTO((int *, int *));
#endif
#endif
+static void begin_definition_of_inclass_inline PROTO((struct pending_inline*));
/* Given a file name X, return the nondirectory portion.
Keep in mind that X can be computed more than once. */
@@ -322,12 +323,13 @@ get_time_identifier (name)
bcopy (name, buf+5, len);
buf[len+5] = '\0';
time_identifier = get_identifier (buf);
- if (IDENTIFIER_LOCAL_VALUE (time_identifier) == NULL_TREE)
+ if (TIME_IDENTIFIER_TIME (time_identifier) == NULL_TREE)
{
push_obstacks_nochange ();
end_temporary_allocation ();
- IDENTIFIER_LOCAL_VALUE (time_identifier) = build_int_2 (0, 0);
- IDENTIFIER_CLASS_VALUE (time_identifier) = build_int_2 (0, 1);
+ TIME_IDENTIFIER_TIME (time_identifier) = build_int_2 (0, 0);
+ TIME_IDENTIFIER_FILEINFO (time_identifier)
+ = build_int_2 (0, 1);
SET_IDENTIFIER_GLOBAL_VALUE (time_identifier, filename_times);
filename_times = time_identifier;
pop_obstacks ();
@@ -435,7 +437,8 @@ init_filename_times ()
{
header_time = 0;
body_time = my_get_run_time ();
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time)) = body_time;
+ TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
+ = body_time;
}
}
@@ -1145,7 +1148,7 @@ extract_interface_info ()
}
if (!fileinfo)
fileinfo = get_time_identifier (input_filename);
- fileinfo = IDENTIFIER_CLASS_VALUE (fileinfo);
+ fileinfo = TIME_IDENTIFIER_FILEINFO (fileinfo);
interface_only = TREE_INT_CST_LOW (fileinfo);
interface_unknown = TREE_INT_CST_HIGH (fileinfo);
}
@@ -1196,7 +1199,7 @@ set_typedecl_interface_info (prev, vars)
tree prev ATTRIBUTE_UNUSED, vars;
{
tree id = get_time_identifier (DECL_SOURCE_FILE (vars));
- tree fileinfo = IDENTIFIER_CLASS_VALUE (id);
+ tree fileinfo = TIME_IDENTIFIER_FILEINFO (id);
tree type = TREE_TYPE (vars);
CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo)
@@ -1222,6 +1225,37 @@ set_vardecl_interface_info (prev, vars)
return 0;
}
+/* Set up the state required to correctly handle the definition of the
+ inline function whose preparsed state has been saved in PI. */
+
+static void
+begin_definition_of_inclass_inline (pi)
+ struct pending_inline* pi;
+{
+ tree context;
+
+ if (!pi->fndecl)
+ return;
+
+ /* If this is an inline function in a local class, we must make sure
+ that we save all pertinent information about the function
+ surrounding the local class. */
+ context = hack_decl_function_context (pi->fndecl);
+ if (context)
+ push_cp_function_context (context);
+
+ feed_input (pi->buf, pi->len);
+ lineno = pi->lineno;
+ input_filename = pi->filename;
+ yychar = PRE_PARSED_FUNCTION_DECL;
+ yylval.ttype = build_tree_list ((tree) pi, pi->fndecl);
+ /* Pass back a handle to the rest of the inline functions, so that they
+ can be processed later. */
+ DECL_PENDING_INLINE_INFO (pi->fndecl) = 0;
+ interface_unknown = pi->interface == 1;
+ interface_only = pi->interface == 0;
+}
+
/* Called from the top level: if there are any pending inlines to
do, set up to process them now. This function sets up the first function
to be parsed; after it has been, the rule for fndef in parse.y will
@@ -1231,7 +1265,6 @@ void
do_pending_inlines ()
{
struct pending_inline *t;
- tree context;
/* Oops, we're still dealing with the last batch. */
if (yychar == PRE_PARSED_FUNCTION_DECL)
@@ -1258,32 +1291,7 @@ do_pending_inlines ()
return;
/* Now start processing the first inline function. */
- context = hack_decl_function_context (t->fndecl);
- if (context)
- push_cp_function_context (context);
- maybe_begin_member_template_processing (t->fndecl);
- if (t->len > 0)
- {
- feed_input (t->buf, t->len);
- lineno = t->lineno;
-#if 0
- if (input_filename != t->filename)
- {
- input_filename = t->filename;
- /* Get interface/implementation back in sync. */
- extract_interface_info ();
- }
-#else
- input_filename = t->filename;
- interface_unknown = t->interface == 1;
- interface_only = t->interface == 0;
-#endif
- yychar = PRE_PARSED_FUNCTION_DECL;
- }
- /* Pass back a handle on the rest of the inline functions, so that they
- can be processed later. */
- yylval.ttype = build_tree_list ((tree) t, t->fndecl);
- DECL_PENDING_INLINE_INFO (t->fndecl) = 0;
+ begin_definition_of_inclass_inline (t);
}
static int nextchar = -1;
@@ -1299,7 +1307,6 @@ process_next_inline (t)
tree context;
struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
context = hack_decl_function_context (i->fndecl);
- maybe_end_member_template_processing ();
if (context)
pop_cp_function_context (context);
i = i->next;
@@ -1317,24 +1324,8 @@ process_next_inline (t)
}
yychar = YYEMPTY;
end_input ();
- if (i && i->fndecl != NULL_TREE)
- {
- context = hack_decl_function_context (i->fndecl);
- if (context)
- push_cp_function_context (context);
- maybe_begin_member_template_processing (i->fndecl);
- feed_input (i->buf, i->len);
- lineno = i->lineno;
- input_filename = i->filename;
- yychar = PRE_PARSED_FUNCTION_DECL;
- yylval.ttype = build_tree_list ((tree) i, i->fndecl);
- DECL_PENDING_INLINE_INFO (i->fndecl) = 0;
- }
if (i)
- {
- interface_unknown = i->interface == 1;
- interface_only = i->interface == 0;
- }
+ begin_definition_of_inclass_inline (i);
else
extract_interface_info ();
}
@@ -2507,7 +2498,7 @@ linenum:
int this_time = my_get_run_time ();
tree time_identifier = get_time_identifier (TREE_STRING_POINTER (yylval.ttype));
header_time += this_time - body_time;
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
+ TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
+= this_time - body_time;
this_filename_time = time_identifier;
body_time = this_time;
@@ -2943,11 +2934,9 @@ do_identifier (token, parsing, args)
/* Do Koenig lookup if appropriate (inside templates we build lookup
expressions instead). */
if (args && !current_template_parms && (!id || is_global (id)))
- {
- /* If we have arguments and we only found global names,
- do Koenig lookup. */
- id = lookup_arg_dependent (token, id, args);
- }
+ /* If we have arguments and we only found global names, do Koenig
+ lookup. */
+ id = lookup_arg_dependent (token, id, args);
/* Remember that this name has been used in the class definition, as per
[class.scope0] */
@@ -3183,16 +3172,20 @@ identifier_typedecl_value (node)
type = IDENTIFIER_TYPE_VALUE (node);
if (type == NULL_TREE)
return NULL_TREE;
-#define do(X) \
- { \
- t = (X); \
- if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type) \
- return t; \
- }
- do (IDENTIFIER_LOCAL_VALUE (node));
- do (IDENTIFIER_CLASS_VALUE (node));
- do (IDENTIFIER_NAMESPACE_VALUE (node));
-#undef do
+
+ if (IDENTIFIER_BINDING (node))
+ {
+ t = IDENTIFIER_VALUE (node);
+ if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type)
+ return t;
+ }
+ if (IDENTIFIER_NAMESPACE_VALUE (node))
+ {
+ t = IDENTIFIER_NAMESPACE_VALUE (node);
+ if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type)
+ return t;
+ }
+
/* Will this one ever happen? */
if (TYPE_MAIN_DECL (type))
return TYPE_MAIN_DECL (type);
@@ -4737,7 +4730,7 @@ dump_time_statistics ()
{
register tree prev = 0, decl, next;
int this_time = my_get_run_time ();
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
+ TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
+= this_time - body_time;
fprintf (stderr, "\n******\n");
@@ -4756,7 +4749,7 @@ dump_time_statistics ()
for (decl = prev; decl; decl = IDENTIFIER_GLOBAL_VALUE (decl))
print_time (IDENTIFIER_POINTER (decl),
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (decl)));
+ TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (decl)));
}
void
@@ -4847,7 +4840,8 @@ handle_cp_pragma (pname)
}
else if (! strcmp (pname, "interface"))
{
- tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
+ tree fileinfo
+ = TIME_IDENTIFIER_FILEINFO (get_time_identifier (input_filename));
char *main_filename = input_filename;
main_filename = file_name_nondirectory (main_filename);
@@ -4882,7 +4876,7 @@ handle_cp_pragma (pname)
#ifdef AUTO_IMPLEMENT
filename = file_name_nondirectory (main_input_filename);
fi = get_time_identifier (filename);
- fi = IDENTIFIER_CLASS_VALUE (fi);
+ fi = TIME_IDENTIFIER_FILEINFO (fi);
TREE_INT_CST_LOW (fi) = 0;
TREE_INT_CST_HIGH (fi) = 1;
/* Get default. */
@@ -4902,7 +4896,8 @@ handle_cp_pragma (pname)
}
else if (! strcmp (pname, "implementation"))
{
- tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
+ tree fileinfo
+ = TIME_IDENTIFIER_FILEINFO (get_time_identifier (input_filename));
char *main_filename = main_input_filename ? main_input_filename : input_filename;
main_filename = file_name_nondirectory (main_filename);
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index 87ac736ea1e..4d4827c95e0 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -236,7 +236,7 @@ empty_parms ()
%token <ttype> PRE_PARSED_CLASS_DECL DEFARG DEFARG_MARKER
%type <ttype> component_constructor_declarator
%type <ttype> fn.def2 return_id fn.defpen constructor_declarator
-%type <itype> ctor_initializer_opt
+%type <itype> ctor_initializer_opt function_try_block
%type <ttype> named_class_head named_class_head_sans_basetype
%type <ttype> named_complex_class_head_sans_basetype
%type <ttype> unnamed_class_head
@@ -639,7 +639,11 @@ fndef:
fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error
{ finish_function (lineno, (int)$3, 0); }
| fn.def1 maybe_return_init function_try_block
- { }
+ {
+ int nested = (hack_decl_function_context
+ (current_function_decl) != NULL_TREE);
+ finish_function (lineno, (int)$3, nested);
+ }
| fn.def1 maybe_return_init error
{ }
;
@@ -2037,7 +2041,7 @@ initlist:
fn.defpen:
PRE_PARSED_FUNCTION_DECL
{ start_function (NULL_TREE, TREE_VALUE ($1),
- NULL_TREE, 1);
+ NULL_TREE, 2);
reinit_parse_for_function (); }
pending_inline:
@@ -2045,11 +2049,16 @@ pending_inline:
{
int nested = (hack_decl_function_context
(current_function_decl) != NULL_TREE);
- finish_function (lineno, (int)$3, nested);
+ finish_function (lineno, (int)$3 | 2, nested);
process_next_inline ($1);
}
| fn.defpen maybe_return_init function_try_block
- { process_next_inline ($1); }
+ {
+ int nested = (hack_decl_function_context
+ (current_function_decl) != NULL_TREE);
+ finish_function (lineno, (int)$3 | 2, nested);
+ process_next_inline ($1);
+ }
| fn.defpen maybe_return_init error
{ process_next_inline ($1); }
;
@@ -3339,10 +3348,8 @@ function_try_block:
}
handler_seq
{
- int nested = (hack_decl_function_context
- (current_function_decl) != NULL_TREE);
expand_end_all_catch ();
- finish_function (lineno, (int)$3, nested);
+ $$ = $3;
}
;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 50e44b5879b..bdf85dd760f 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -426,14 +426,14 @@ maybe_end_member_template_processing ()
template <class T> class C { template <class U> void f(U); }
then neither C<int>::f<char> nor C<T>::f<double> is considered
- to be a member template. */
+ to be a member template. But, `template <class U> void
+ C<int>::f(U)' is considered a member template. */
int
is_member_template (t)
tree t;
{
- if (TREE_CODE (t) != FUNCTION_DECL
- && !DECL_FUNCTION_TEMPLATE_P (t))
+ if (!DECL_FUNCTION_TEMPLATE_P (t))
/* Anything that isn't a function or a template function is
certainly not a member template. */
return 0;
@@ -442,31 +442,12 @@ is_member_template (t)
if (hack_decl_function_context (t))
return 0;
- if ((DECL_FUNCTION_MEMBER_P (t)
- && !DECL_TEMPLATE_SPECIALIZATION (t))
- || (TREE_CODE (t) == TEMPLATE_DECL
- && DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))))
- {
- tree tmpl;
-
- if (DECL_FUNCTION_TEMPLATE_P (t))
- tmpl = t;
- else if (DECL_TEMPLATE_INFO (t)
- && DECL_FUNCTION_TEMPLATE_P (DECL_TI_TEMPLATE (t)))
- tmpl = DECL_TI_TEMPLATE (t);
- else
- tmpl = NULL_TREE;
-
- if (tmpl
+ return (DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))
/* If there are more levels of template parameters than
there are template classes surrounding the declaration,
then we have a member template. */
- && (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)) >
- template_class_depth (DECL_CLASS_CONTEXT (t))))
- return 1;
- }
-
- return 0;
+ && (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) >
+ template_class_depth (DECL_CLASS_CONTEXT (t))));
}
#if 0 /* UNUSED */
@@ -1487,28 +1468,27 @@ int comp_template_parms (parms1, parms2)
}
-/* Returns 1 iff old_id is a template parameter. OLD_DECL is the decl
- from IDENTIFIER_LOCAL_VALUE (new identifier). */
+/* Returns 1 iff DECL is a template parameter. */
-int decl_template_parm_p (old_decl)
- tree old_decl;
+int decl_template_parm_p (decl)
+ tree decl;
{
/* For template template parms. */
- if (TREE_CODE (old_decl) == TEMPLATE_DECL
- && TREE_TYPE (old_decl)
- && TREE_CODE (TREE_TYPE (old_decl)) == TEMPLATE_TEMPLATE_PARM)
+ if (TREE_CODE (decl) == TEMPLATE_DECL
+ && TREE_TYPE (decl)
+ && TREE_CODE (TREE_TYPE (decl)) == TEMPLATE_TEMPLATE_PARM)
return 1;
/* For template type parms. */
- if (TREE_CODE (old_decl) == TYPE_DECL
- && TREE_TYPE (old_decl)
- && TREE_CODE (TREE_TYPE (old_decl)) == TEMPLATE_TYPE_PARM)
+ if (TREE_CODE (decl) == TYPE_DECL
+ && TREE_TYPE (decl)
+ && TREE_CODE (TREE_TYPE (decl)) == TEMPLATE_TYPE_PARM)
return 1;
/* For template non-type parms. */
- if (TREE_CODE (old_decl) == CONST_DECL
- && DECL_INITIAL (old_decl)
- && TREE_CODE (DECL_INITIAL (old_decl)) == TEMPLATE_PARM_INDEX)
+ if (TREE_CODE (decl) == CONST_DECL
+ && DECL_INITIAL (decl)
+ && TREE_CODE (DECL_INITIAL (decl)) == TEMPLATE_PARM_INDEX)
return 1;
return 0;
@@ -1523,11 +1503,10 @@ void
check_template_shadow (decl)
tree decl;
{
- if (current_template_parms
- && IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl)))
- {
- tree olddecl = IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl));
+ tree olddecl = IDENTIFIER_VALUE (DECL_NAME (decl));
+ if (current_template_parms && olddecl)
+ {
/* We check for decl != olddecl to avoid bogus errors for using a
name inside a class. We check TPFI to avoid duplicate errors for
inline member templates. */
@@ -3423,9 +3402,9 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
if (TREE_CODE (d1) == IDENTIFIER_NODE)
{
- if (IDENTIFIER_LOCAL_VALUE (d1)
- && DECL_TEMPLATE_TEMPLATE_PARM_P (IDENTIFIER_LOCAL_VALUE (d1)))
- template = IDENTIFIER_LOCAL_VALUE (d1);
+ if (IDENTIFIER_VALUE (d1)
+ && DECL_TEMPLATE_TEMPLATE_PARM_P (IDENTIFIER_VALUE (d1)))
+ template = IDENTIFIER_VALUE (d1);
else
{
if (context)
@@ -3468,9 +3447,10 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
my_friendly_abort (272);
/* With something like `template <class T> class X class X { ... };'
- we could end up with D1 having nothing but an IDENTIFIER_LOCAL_VALUE.
- We don't want to do that, but we have to deal with the situation, so
- let's give them some syntax errors to chew on instead of a crash. */
+ we could end up with D1 having nothing but an IDENTIFIER_VALUE.
+ We don't want to do that, but we have to deal with the situation,
+ so let's give them some syntax errors to chew on instead of a
+ crash. */
if (! template)
{
cp_error ("`%T' is not a template", d1);
@@ -5434,11 +5414,9 @@ tsubst_decl (t, args, type, in_decl)
if (member && !strncmp (OPERATOR_TYPENAME_FORMAT,
IDENTIFIER_POINTER (DECL_NAME (r)),
sizeof (OPERATOR_TYPENAME_FORMAT) - 1))
- {
- /* Type-conversion operator. Reconstruct the name, in
- case it's the name of one of the template's parameters. */
- DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
- }
+ /* Type-conversion operator. Reconstruct the name, in
+ case it's the name of one of the template's parameters. */
+ DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, t);
DECL_MAIN_VARIANT (r) = r;
@@ -5453,14 +5431,6 @@ tsubst_decl (t, args, type, in_decl)
DECL_PENDING_INLINE_INFO (r) = 0;
TREE_USED (r) = 0;
- if (DECL_CONSTRUCTOR_P (r))
- {
- maybe_retrofit_in_chrg (r);
- grok_ctor_properties (ctx, r);
- }
- if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
- grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
-
/* Set up the DECL_TEMPLATE_INFO for R and compute its mangled
name. There's no need to do this in the special friend
case mentioned above where GEN_TMPL is NULL. */
@@ -5507,6 +5477,14 @@ tsubst_decl (t, args, type, in_decl)
== NULL_TREE))
SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
}
+
+ if (DECL_CONSTRUCTOR_P (r))
+ {
+ maybe_retrofit_in_chrg (r);
+ grok_ctor_properties (ctx, r);
+ }
+ if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
+ grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
}
break;
@@ -7688,11 +7666,12 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
}
case RECORD_TYPE:
+ case UNION_TYPE:
if (TYPE_PTRMEMFUNC_FLAG (parm))
return unify (tparms, targs, TYPE_PTRMEMFUNC_FN_TYPE (parm),
arg, strict, explicit_mask);
- if (TREE_CODE (arg) != RECORD_TYPE)
+ if (TREE_CODE (arg) != TREE_CODE (parm))
return 1;
if (CLASSTYPE_TEMPLATE_INFO (parm) && uses_template_parms (parm))
diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c
index eddc2e47303..4fb0413b9c0 100644
--- a/gcc/cp/ptree.c
+++ b/gcc/cp/ptree.c
@@ -152,7 +152,7 @@ print_lang_identifier (file, node, indent)
{
print_node (file, "bindings", IDENTIFIER_NAMESPACE_BINDINGS (node), indent + 4);
print_node (file, "class", IDENTIFIER_CLASS_VALUE (node), indent + 4);
- print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
+ print_node (file, "local bindings", IDENTIFIER_BINDING (node), indent + 4);
print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4);
print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
@@ -168,7 +168,8 @@ lang_print_xnode (file, node, indent)
switch (TREE_CODE (node))
{
case CPLUS_BINDING:
- print_node (file, "scope", BINDING_SCOPE (node), indent+4);
+ fprintf (file, " scope ");
+ fprintf (file, HOST_PTR_PRINTF, BINDING_SCOPE (node));
print_node (file, "value", BINDING_VALUE (node), indent+4);
print_node (file, "chain", TREE_CHAIN (node), indent+4);
break;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 58f42d2ffa5..fddc9998070 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4849,7 +4849,8 @@ mark_addressable (exp)
TREE_ASM_WRITTEN (x) = 0;
DECL_RTL (x) = 0;
- rest_of_decl_compilation (x, 0, IDENTIFIER_LOCAL_VALUE (x) == 0,
+ rest_of_decl_compilation (x, 0,
+ !DECL_FUNCTION_SCOPE_P (x),
0);
TREE_ADDRESSABLE (x) = 1;
@@ -7235,9 +7236,9 @@ c_expand_return (retval)
if (TEMP_NAME_P (DECL_NAME (whats_returned)))
warning ("reference to non-lvalue returned");
else if (TREE_CODE (TREE_TYPE (whats_returned)) != REFERENCE_TYPE
- && ! TREE_STATIC (whats_returned)
- && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
- && !TREE_PUBLIC (whats_returned))
+ && DECL_FUNCTION_SCOPE_P (whats_returned)
+ && !(TREE_STATIC (whats_returned)
+ || TREE_PUBLIC (whats_returned)))
cp_warning_at ("reference to local variable `%D' returned", whats_returned);
}
}
@@ -7247,9 +7248,9 @@ c_expand_return (retval)
if (TREE_CODE (whats_returned) == VAR_DECL
&& DECL_NAME (whats_returned)
- && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
- && !TREE_STATIC (whats_returned)
- && !TREE_PUBLIC (whats_returned))
+ && DECL_FUNCTION_SCOPE_P (whats_returned)
+ && !(TREE_STATIC (whats_returned)
+ || TREE_PUBLIC (whats_returned)))
cp_warning_at ("address of local variable `%D' returned", whats_returned);
}
}
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900511_02.C b/gcc/testsuite/g++.old-deja/g++.bugs/900511_02.C
index 0154bfe4140..dcd35681bde 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900511_02.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900511_02.C
@@ -8,11 +8,11 @@
// cfront 2.0 passes this test.
-enum enum0 { enum0_value_0 }; // ERROR -
+enum enum0 { enum0_value_0 };
struct struct0 {
- int enum0; // ERROR -
- void member_function (enum0 e);
+ int enum0;
+ void member_function (enum0 e); // ERROR -
};
void class0::member_function (enum0 e) { // ERROR -
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900511_03.C b/gcc/testsuite/g++.old-deja/g++.bugs/900511_03.C
index d8a549aa82c..d3cf47c575e 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900511_03.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900511_03.C
@@ -6,11 +6,11 @@
// keywords: typedef names, shadowing, scope, formal parameter list
-class class0; // ERROR -
+class class0;
struct struct1 {
- int class0; // ERROR -
- void member_function (class0 *);
+ int class0;
+ void member_function (class0 *); // ERROR -
};
void class1::member_function (class0 *p) { // ERROR -
diff --git a/gcc/testsuite/g++.old-deja/g++.other/for1.C b/gcc/testsuite/g++.old-deja/g++.other/for1.C
new file mode 100644
index 00000000000..31cd741a366
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/for1.C
@@ -0,0 +1,41 @@
+// Build don't link:
+
+int i;
+int j;
+
+struct S {
+ int operator()(int)
+ {
+ i = 1;
+ }
+
+ typedef int I;
+
+ void f() {
+ for (S I; false; )
+ ;
+ int k = I(3);
+ }
+};
+
+typedef int J;
+
+struct T {
+ int operator()(int)
+ {
+ j = 1;
+ }
+
+ void f() {
+ for (T J; false; )
+ ;
+ int k = J(3);
+ }
+};
+
+int main()
+{
+ S s;
+ s.f();
+ return 2 * i + j;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/lookup6.C b/gcc/testsuite/g++.old-deja/g++.other/lookup6.C
new file mode 100644
index 00000000000..08f5ac521ed
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/lookup6.C
@@ -0,0 +1,25 @@
+int f(int i)
+{
+ struct C {
+ int i;
+ C () : i(1) {}
+ int f() {
+ struct D {
+ int i;
+ D () : i(2) {}
+ int g() { return i; }
+ } d;
+
+ return d.g();
+ }
+ } c;
+
+ return c.f();
+}
+
+
+int main()
+{
+ if (f(0) != 2)
+ return 1;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/overload9.C b/gcc/testsuite/g++.old-deja/g++.other/overload9.C
new file mode 100644
index 00000000000..521f4bd4d06
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/overload9.C
@@ -0,0 +1,31 @@
+struct T { ~T() {}; };
+
+int g ()
+{
+ foo:
+ T t;
+ int f(int);
+ bar:
+ T t2;
+ int f(double);
+ return f(3);
+}
+
+
+int f(int)
+{
+ return 0;
+}
+
+
+int f(double)
+{
+ return 1;
+}
+
+
+int main()
+{
+ return g();
+}
+
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/copy1.C b/gcc/testsuite/g++.old-deja/g++.pt/copy1.C
new file mode 100644
index 00000000000..7981530f697
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/copy1.C
@@ -0,0 +1,29 @@
+int i = 0;
+
+template <class T>
+class F
+{
+public:
+ F() {}
+
+ template <class T2> F(F<T2>)
+ {
+ i = 1;
+ }
+};
+
+
+F<int>
+foo()
+{
+ F<int> f1;
+ F<int> f2(f1);
+ return f1;
+}
+
+int
+main()
+{
+ return i;
+}
+
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend34.C b/gcc/testsuite/g++.old-deja/g++.pt/friend34.C
index 8ba2c739d30..56eb80a5056 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/friend34.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/friend34.C
@@ -1,5 +1,5 @@
// Build don't link:
-// excess errors test - XFAIL *-*-*
+// excess errors test
// This testcase won't fail if class ::foo is forward-declared in the
// global namespace, nor if class bar is not a template class.
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/union1.C b/gcc/testsuite/g++.old-deja/g++.pt/union1.C
new file mode 100644
index 00000000000..a1da446e570
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/union1.C
@@ -0,0 +1,18 @@
+// Build don't link:
+
+union Un {int i;};
+
+template<class T1, class T2> struct St1 {};
+template<class T> struct St1<Un,T> {};
+
+template<class T> struct St2 {};
+template<> struct St2<Un> {};
+
+template<class T1, class T2> struct St3 {};
+template<> struct St3<Un,int> {};
+
+void f() {
+ St1<int,int> s1;
+ St2<int> s2;
+ St3<int,int> s3;
+}