Commit f181d4ae by Mark Mitchell Committed by Mark Mitchell

cp-tree.def (CPLUS_BINDING): Update documentation.

	* 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.

From-SVN: r24296
parent 92c068d1
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> 1998-12-08 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (grokdeclarator): Allow field with same name as class * decl.c (grokdeclarator): Allow field with same name as class
......
...@@ -4780,15 +4780,18 @@ pushclass (type, modify) ...@@ -4780,15 +4780,18 @@ pushclass (type, modify)
{ {
tree item; tree item;
/* Hooray, we successfully cached; let's just install the /* We are re-entering the same class we just left, so we
cached class_shadowed list, and walk through it to get the don't have to search the whole inheritance matrix to find
IDENTIFIER_TYPE_VALUEs correct. */ 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); set_class_shadows (previous_class_values);
for (item = previous_class_values; item; item = TREE_CHAIN (item)) for (item = previous_class_values; item; item = TREE_CHAIN (item))
{ {
tree id = TREE_PURPOSE (item); tree id = TREE_PURPOSE (item);
tree decl = IDENTIFIER_CLASS_VALUE (id); tree decl = IDENTIFIER_CLASS_VALUE (id);
push_class_binding (id, decl);
if (TREE_CODE (decl) == TYPE_DECL) if (TREE_CODE (decl) == TYPE_DECL)
set_identifier_type_value (id, TREE_TYPE (decl)); set_identifier_type_value (id, TREE_TYPE (decl));
} }
......
...@@ -178,9 +178,9 @@ DEFTREECODE (DEFAULT_ARG, "default_arg", 'c', 2) ...@@ -178,9 +178,9 @@ DEFTREECODE (DEFAULT_ARG, "default_arg", 'c', 2)
the template may be an IDENTIFIER_NODE. */ the template may be an IDENTIFIER_NODE. */
DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", 'e', 2) DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", 'e', 2)
/* An association between namespace and entity. Parameters are the /* An association between name and entity. Parameters are the scope
scope and the (non-type) value. and the (non-type) value. TREE_TYPE indicates the type bound to
TREE_TYPE indicates the type bound to the name. */ the name. */
DEFTREECODE (CPLUS_BINDING, "binding", 'x', 2) DEFTREECODE (CPLUS_BINDING, "binding", 'x', 2)
/* A list-like node for chaining overloading candidates. TREE_TYPE is /* A list-like node for chaining overloading candidates. TREE_TYPE is
......
...@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA. */
LOOKUP_EXPR_GLOBAL (in LOOKUP_EXPR). LOOKUP_EXPR_GLOBAL (in LOOKUP_EXPR).
TREE_NEGATED_INT (in INTEGER_CST). TREE_NEGATED_INT (in INTEGER_CST).
IDENTIFIER_MARKED (used by search routines). IDENTIFIER_MARKED (used by search routines).
LOCAL_BINDING_P (in CPLUS_BINDING)
1: IDENTIFIER_VIRTUAL_P. 1: IDENTIFIER_VIRTUAL_P.
TI_PENDING_TEMPLATE_FLAG. TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE. TEMPLATE_PARMS_FOR_INLINE.
...@@ -92,7 +93,8 @@ Boston, MA 02111-1307, USA. */ ...@@ -92,7 +93,8 @@ Boston, MA 02111-1307, USA. */
struct lang_identifier struct lang_identifier
{ {
struct tree_identifier ignore; struct tree_identifier ignore;
tree namespace_bindings, local_value; tree namespace_bindings;
tree bindings;
tree class_value; tree class_value;
tree class_template_info; tree class_template_info;
struct lang_id2 *x; struct lang_id2 *x;
...@@ -127,15 +129,24 @@ typedef struct ptrmem_cst ...@@ -127,15 +129,24 @@ typedef struct ptrmem_cst
tree member; tree member;
}* ptrmem_cst_t; }* ptrmem_cst_t;
/* For a binding between a name and an entity, defines the scope /* Nonzero if this binding is for a local scope, as opposed to a class
where the binding is declared. Currently always points to a or namespace scope. */
namespace declaration. */ #define LOCAL_BINDING_P(NODE) TREE_LANG_FLAG_0(NODE)
#define BINDING_SCOPE(NODE) (((struct tree_binding*)NODE)->scope)
/* 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: /* This is the declaration bound to the name. Possible values:
variable, overloaded function, namespace, template, enumerator. */ variable, overloaded function, namespace, template, enumerator. */
#define BINDING_VALUE(NODE) (((struct tree_binding*)NODE)->value) #define BINDING_VALUE(NODE) (((struct tree_binding*)NODE)->value)
/* If name is bound to a type, this is the type (struct, union, enum). */ /* If name is bound to a type, this is the type (struct, union, enum). */
#define BINDING_TYPE(NODE) TREE_TYPE(NODE) #define BINDING_TYPE(NODE) TREE_TYPE(NODE)
#define IDENTIFIER_GLOBAL_VALUE(NODE) \ #define IDENTIFIER_GLOBAL_VALUE(NODE) \
namespace_binding (NODE, global_namespace) namespace_binding (NODE, global_namespace)
#define SET_IDENTIFIER_GLOBAL_VALUE(NODE, VAL) \ #define SET_IDENTIFIER_GLOBAL_VALUE(NODE, VAL) \
...@@ -148,7 +159,7 @@ typedef struct ptrmem_cst ...@@ -148,7 +159,7 @@ typedef struct ptrmem_cst
struct tree_binding struct tree_binding
{ {
char common[sizeof (struct tree_common)]; char common[sizeof (struct tree_common)];
tree scope; void* scope;
tree value; tree value;
}; };
...@@ -200,13 +211,43 @@ struct tree_srcloc ...@@ -200,13 +211,43 @@ struct tree_srcloc
#define IDENTIFIER_NAMESPACE_BINDINGS(NODE) \ #define IDENTIFIER_NAMESPACE_BINDINGS(NODE) \
(((struct lang_identifier *)(NODE))->namespace_bindings) (((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) \ #define IDENTIFIER_TEMPLATE(NODE) \
(((struct lang_identifier *)(NODE))->class_template_info) (((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 /* TREE_TYPE only indicates on local and class scope the current
type. For namespace scope, the presence of a type in any namespace type. For namespace scope, the presence of a type in any namespace
is indicated with global_type_node, and the real type behind must is indicated with global_type_node, and the real type behind must
...@@ -1444,6 +1485,10 @@ struct lang_decl ...@@ -1444,6 +1485,10 @@ struct lang_decl
TEMPLATE_ID_EXPR if we had something like `typename X::Y<T>'. */ TEMPLATE_ID_EXPR if we had something like `typename X::Y<T>'. */
#define TYPENAME_TYPE_FULLNAME(NODE) TYPE_BINFO (NODE) #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 /* Nonzero in INTEGER_CST means that this int is negative by dint of
using a twos-complement negated operand. */ using a twos-complement negated operand. */
#define TREE_NEGATED_INT(NODE) (TREE_LANG_FLAG_0 (NODE)) #define TREE_NEGATED_INT(NODE) (TREE_LANG_FLAG_0 (NODE))
...@@ -2665,7 +2710,6 @@ extern void push_to_top_level PROTO((void)); ...@@ -2665,7 +2710,6 @@ extern void push_to_top_level PROTO((void));
extern void pop_from_top_level PROTO((void)); extern void pop_from_top_level PROTO((void));
extern tree identifier_type_value PROTO((tree)); extern tree identifier_type_value PROTO((tree));
extern void set_identifier_type_value PROTO((tree, 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 pop_everything PROTO((void));
extern void pushtag PROTO((tree, tree, int)); extern void pushtag PROTO((tree, tree, int));
extern tree make_anon_name PROTO((void)); extern tree make_anon_name PROTO((void));
...@@ -2761,6 +2805,8 @@ extern void revert_static_member_fn PROTO((tree*, tree*, tree*)); ...@@ -2761,6 +2805,8 @@ extern void revert_static_member_fn PROTO((tree*, tree*, tree*));
extern void cat_namespace_levels PROTO((void)); extern void cat_namespace_levels PROTO((void));
extern void fixup_anonymous_union PROTO((tree)); extern void fixup_anonymous_union PROTO((tree));
extern int check_static_variable_definition PROTO((tree, 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 */ /* in decl2.c */
extern int check_java_method PROTO((tree)); extern int check_java_method PROTO((tree));
......
...@@ -169,8 +169,6 @@ static tree lookup_tag PROTO((enum tree_code, tree, ...@@ -169,8 +169,6 @@ static tree lookup_tag PROTO((enum tree_code, tree,
struct binding_level *, int)); struct binding_level *, int));
static void set_identifier_type_value_with_scope static void set_identifier_type_value_with_scope
PROTO((tree, tree, struct binding_level *)); 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_builtin_type PROTO((enum rid, char *, tree));
static void record_unknown_type PROTO((tree, char *)); static void record_unknown_type PROTO((tree, char *));
static int member_function_or_else PROTO((tree, 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 ...@@ -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 void check_for_uninitialized_const_var PROTO((tree));
static unsigned long typename_hash PROTO((hash_table_key)); static unsigned long typename_hash PROTO((hash_table_key));
static boolean typename_compare PROTO((hash_table_key, 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) #if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PROTO((void)); static void indent PROTO((void));
...@@ -611,7 +611,8 @@ struct binding_level ...@@ -611,7 +611,8 @@ struct binding_level
{ {
/* A chain of _DECL nodes for all variables, constants, functions, /* A chain of _DECL nodes for all variables, constants, functions,
and typedef types. These are in the reverse of the order 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; tree names;
/* A list of structure, union and enum definitions, for looking up /* A list of structure, union and enum definitions, for looking up
...@@ -631,16 +632,16 @@ struct binding_level ...@@ -631,16 +632,16 @@ struct binding_level
VALUE the common ancestor with this binding_level's namespace. */ VALUE the common ancestor with this binding_level's namespace. */
tree using_directives; tree using_directives;
/* For each level, a list of shadowed outer-level local definitions /* If this binding level is the binding level for a class, then
to be restored when this level is popped. class_shadowed is a TREE_LIST. The TREE_PURPOSE of each node
Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and is the name of an entity bound in the class; the TREE_VALUE is
whose TREE_VALUE is its old definition (a kind of ..._DECL node). */ the IDENTIFIER_CLASS_VALUE before we entered the class. Thus,
tree shadowed; when leaving class scope, we can restore the
IDENTIFIER_CLASS_VALUE by walking this list. */
/* Same, for IDENTIFIER_CLASS_VALUE. */
tree class_shadowed; 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; tree type_shadowed;
/* For each level (except not the global one), /* For each level (except not the global one),
...@@ -661,7 +662,8 @@ struct binding_level ...@@ -661,7 +662,8 @@ struct binding_level
/* List of VAR_DECLS saved from a previous for statement. /* List of VAR_DECLS saved from a previous for statement.
These would be dead in ANSI-conforming code, but might 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; tree dead_vars_from_for;
/* 1 for the level that holds the parameters of a function. /* 1 for the level that holds the parameters of a function.
...@@ -1030,6 +1032,112 @@ pushlevel_temporary (tag_transparent) ...@@ -1030,6 +1032,112 @@ pushlevel_temporary (tag_transparent)
expand_start_bindings (0); 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. /* Exit a binding level.
Pop the level off, and restore the state of the identifier-decl mappings Pop the level off, and restore the state of the identifier-decl mappings
that were in effect when this level was entered. that were in effect when this level was entered.
...@@ -1063,6 +1171,13 @@ poplevel (keep, reverse, functionbody) ...@@ -1063,6 +1171,13 @@ poplevel (keep, reverse, functionbody)
tree block = NULL_TREE; tree block = NULL_TREE;
tree decl; tree decl;
int block_previously_created; 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 /* 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, at the beginning of the list of blocks at this binding level,
...@@ -1127,9 +1242,8 @@ poplevel (keep, reverse, functionbody) ...@@ -1127,9 +1242,8 @@ poplevel (keep, reverse, functionbody)
if (decls || tags || subblocks) if (decls || tags || subblocks)
{ {
if (BLOCK_VARS (block) || BLOCK_TYPE_TAGS (block)) 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_VARS (block) = decls;
BLOCK_TYPE_TAGS (block) = tags; BLOCK_TYPE_TAGS (block) = tags;
...@@ -1148,7 +1262,8 @@ poplevel (keep, reverse, functionbody) ...@@ -1148,7 +1262,8 @@ poplevel (keep, reverse, functionbody)
BLOCK_VARS (block) = decls; BLOCK_VARS (block) = decls;
BLOCK_TYPE_TAGS (block) = tags; BLOCK_TYPE_TAGS (block) = tags;
BLOCK_SUBBLOCKS (block) = subblocks; 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); remember_end_note (block);
} }
} }
...@@ -1159,92 +1274,116 @@ poplevel (keep, reverse, functionbody) ...@@ -1159,92 +1274,116 @@ poplevel (keep, reverse, functionbody)
for (link = subblocks; link; link = TREE_CHAIN (link)) for (link = subblocks; link; link = TREE_CHAIN (link))
BLOCK_SUPERCONTEXT (link) = block; BLOCK_SUPERCONTEXT (link) = block;
/* Clear out the meanings of the local variables of this level. */ /* We still support the old for-scope rules, whereby the variables
in a for-init statement were in scope after the for-statement
if (current_binding_level->is_for_scope && flag_new_for_scope == 1) ended. We only use the new rules in flag_new_for_scope is
{ nonzero. */
struct binding_level *outer = current_binding_level->level_chain; leaving_for_scope
for (link = decls; link; link = TREE_CHAIN (link)) = current_binding_level->is_for_scope && flag_new_for_scope == 1;
{
if (TREE_CODE (link) == VAR_DECL) /* Remove declarations for all the DECLs in this level. */
DECL_DEAD_FOR_LOCAL (link) = 1; 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 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, /* Mark this VAR_DECL as dead so that we can tell we left it
but remember what (if anything) it shadowed. */ there only for backward compatibility. */
DECL_SHADOWED_FOR_VAR (decl) = TREE_VALUE (link); DECL_DEAD_FOR_LOCAL (link) = 1;
TREE_CHAIN (decl) = outer->dead_vars_from_for;
outer->dead_vars_from_for = decl; /* 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
else /* Not special for scope. */
{
for (link = decls; link; link = TREE_CHAIN (link))
{ {
if (DECL_NAME (link) != NULL_TREE) /* Remove the binding. */
{ if (TREE_CODE_CLASS (TREE_CODE (link)) == 'd')
/* If the ident. was used or addressed via a local extern decl, pop_binding (DECL_NAME (link));
don't forget that fact. */ else if (TREE_CODE (link) == TREE_LIST)
if (DECL_EXTERNAL (link)) pop_binding (DECL_NAME (OVL_FUNCTION (TREE_VALUE (link))));
{ else
if (TREE_USED (link)) my_friendly_abort (0);
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;
}
} }
}
/* Restore all name-meanings of the outer levels /* Remove declarations for any `for' variables from inner scopes
that were shadowed by this level. */ that we kept around. */
for (link = current_binding_level->dead_vars_from_for;
for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
link; link = TREE_CHAIN (link)) pop_binding (DECL_NAME (TREE_VALUE (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. */
link = current_binding_level->dead_vars_from_for; /* Restore the IDENTIFIER_TYPE_VALUEs. */
for (; link != NULL_TREE; link = TREE_CHAIN (link)) for (link = current_binding_level->type_shadowed;
{ link; link = TREE_CHAIN (link))
tree id = DECL_NAME (link); SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
if (IDENTIFIER_LOCAL_VALUE (id) == link)
IDENTIFIER_LOCAL_VALUE (id) = DECL_SHADOWED_FOR_VAR (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; for (d = &BLOCK_VARS (block);
link; link = TREE_CHAIN (link)) *d;
IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); d = *d ? &TREE_CHAIN (*d) : d)
for (link = current_binding_level->type_shadowed; if (TREE_CODE (*d) == TREE_LIST)
link; link = TREE_CHAIN (link)) *d = TREE_CHAIN (*d);
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
} }
/* If the level being exited is the top level of a function, /* If the level being exited is the top level of a function,
...@@ -1407,9 +1546,7 @@ pushlevel_class () ...@@ -1407,9 +1546,7 @@ pushlevel_class ()
free_binding_level = free_binding_level->level_chain; free_binding_level = free_binding_level->level_chain;
} }
else else
{ newlevel = make_binding_level ();
newlevel = make_binding_level ();
}
#if defined(DEBUG_CP_BINDING_LEVELS) #if defined(DEBUG_CP_BINDING_LEVELS)
is_class_level = 1; is_class_level = 1;
...@@ -1444,8 +1581,6 @@ poplevel_class (force) ...@@ -1444,8 +1581,6 @@ poplevel_class (force)
my_friendly_assert (level != 0, 354); my_friendly_assert (level != 0, 354);
decl_stack = pop_stack_level (decl_stack); 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 /* 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 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, shouldn't even be used when current_class_type isn't set, and second,
...@@ -1468,6 +1603,12 @@ poplevel_class (force) ...@@ -1468,6 +1603,12 @@ poplevel_class (force)
shadowed = TREE_CHAIN (shadowed)) shadowed = TREE_CHAIN (shadowed))
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed), TREE_VALUE (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, GNU_xref_end_scope ((HOST_WIDE_INT) class_binding_level,
(HOST_WIDE_INT) class_binding_level->level_chain, (HOST_WIDE_INT) class_binding_level->level_chain,
class_binding_level->parm_flag, class_binding_level->parm_flag,
...@@ -1574,15 +1715,6 @@ print_binding_level (lvl) ...@@ -1574,15 +1715,6 @@ print_binding_level (lvl)
if (i) if (i)
fprintf (stderr, "\n"); 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) if (lvl->class_shadowed)
{ {
fprintf (stderr, " class-shadowed:"); fprintf (stderr, " class-shadowed:");
...@@ -1932,9 +2064,11 @@ store_bindings (names, old_bindings) ...@@ -1932,9 +2064,11 @@ store_bindings (names, old_bindings)
else else
id = DECL_NAME (t); id = DECL_NAME (t);
if (!id if (!id
|| (!IDENTIFIER_LOCAL_VALUE (id) /* Note that we may have an IDENTIFIER_CLASS_VALUE even when
&& !IDENTIFIER_CLASS_VALUE (id))) 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; continue;
for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1)) for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1))
...@@ -1954,9 +2088,9 @@ store_bindings (names, old_bindings) ...@@ -1954,9 +2088,9 @@ store_bindings (names, old_bindings)
my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135); my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
TREE_VEC_ELT (binding, 0) = id; TREE_VEC_ELT (binding, 0) = id;
TREE_VEC_ELT (binding, 1) = REAL_IDENTIFIER_TYPE_VALUE (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); 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; IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
} }
TREE_CHAIN (binding) = old_bindings; TREE_CHAIN (binding) = old_bindings;
...@@ -2085,7 +2219,7 @@ pop_from_top_level () ...@@ -2085,7 +2219,7 @@ pop_from_top_level ()
if (id) if (id)
{ {
SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1)); 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); IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
} }
t = TREE_CHAIN (t); t = TREE_CHAIN (t);
...@@ -2169,26 +2303,6 @@ set_identifier_type_value (id, type) ...@@ -2169,26 +2303,6 @@ set_identifier_type_value (id, type)
set_identifier_type_value_with_scope (id, type, inner_binding_level); 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. */ /* Return the type associated with id. */
tree tree
...@@ -3322,14 +3436,14 @@ pushdecl (x) ...@@ -3322,14 +3436,14 @@ pushdecl (x)
{ {
register tree t; register tree t;
register tree name = DECL_ASSEMBLER_NAME (x); 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 if (current_function_decl && x != current_function_decl
/* A local declaration for a function doesn't constitute nesting. */ /* A local declaration for a function doesn't constitute nesting. */
&& (TREE_CODE (x) != FUNCTION_DECL || DECL_INITIAL (x)) && (TREE_CODE (x) != FUNCTION_DECL || DECL_INITIAL (x))
/* Don't change DECL_CONTEXT of virtual methods. */ /* Don't change DECL_CONTEXT of virtual methods. */
&& (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x)) && (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x))
&& ! DECL_CONTEXT (x)) && !DECL_CONTEXT (x))
DECL_CONTEXT (x) = current_function_decl; DECL_CONTEXT (x) = current_function_decl;
if (!DECL_CONTEXT (x)) if (!DECL_CONTEXT (x))
DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace); DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace);
...@@ -3459,6 +3573,11 @@ pushdecl (x) ...@@ -3459,6 +3573,11 @@ pushdecl (x)
t = push_overloaded_decl (x, 1); t = push_overloaded_decl (x, 1);
if (t != x || DECL_LANGUAGE (x) == lang_c) if (t != x || DECL_LANGUAGE (x) == lang_c)
return t; 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)) else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x))
return push_overloaded_decl (x, 0); return push_overloaded_decl (x, 0);
...@@ -3495,7 +3614,15 @@ pushdecl (x) ...@@ -3495,7 +3614,15 @@ pushdecl (x)
if (type != error_mark_node if (type != error_mark_node
&& TYPE_NAME (type) && TYPE_NAME (type)
&& TYPE_IDENTIFIER (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. /* Multiple external decls of the same identifier ought to match.
...@@ -3536,11 +3663,7 @@ pushdecl (x) ...@@ -3536,11 +3663,7 @@ pushdecl (x)
if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x)) if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
TREE_PUBLIC (name) = 1; TREE_PUBLIC (name) = 1;
/* Don't install an artificial TYPE_DECL if we already have if (need_new_binding)
another _DECL with that name. */
if (TREE_CODE (x) != TYPE_DECL
|| t == NULL_TREE
|| ! DECL_ARTIFICIAL (x))
{ {
if (TREE_CODE (x) == FUNCTION_DECL) if (TREE_CODE (x) == FUNCTION_DECL)
my_friendly_assert my_friendly_assert
...@@ -3575,25 +3698,29 @@ pushdecl (x) ...@@ -3575,25 +3698,29 @@ pushdecl (x)
else else
{ {
/* Here to install a non-global value. */ /* Here to install a non-global value. */
tree oldlocal = IDENTIFIER_LOCAL_VALUE (name); tree oldlocal = IDENTIFIER_VALUE (name);
tree oldglobal = IDENTIFIER_NAMESPACE_VALUE (name); tree oldglobal = IDENTIFIER_NAMESPACE_VALUE (name);
/* Don't install an artificial TYPE_DECL if we already have if (need_new_binding)
another _DECL with that name. */ {
if (TREE_CODE (x) != TYPE_DECL push_local_binding (name, x);
|| t == NULL_TREE /* Because push_local_binding will hook X on to the
|| ! DECL_ARTIFICIAL (x)) current_binding_level's name list, we don't want to
set_identifier_local_value_with_scope (name, x, b); do that again below. */
need_new_binding = 0;
}
/* If this is a TYPE_DECL, push it into the type value slot. */ /* If this is a TYPE_DECL, push it into the type value slot. */
if (TREE_CODE (x) == TYPE_DECL) 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 /* 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 we won't think this is a type. The C struct hack doesn't
go through namespaces. */ go through namespaces. */
if (TREE_CODE (x) == NAMESPACE_DECL) 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 /* If this is an extern function declaration, see if we
have a global definition or declaration for the function. */ have a global definition or declaration for the function. */
...@@ -3619,9 +3746,7 @@ pushdecl (x) ...@@ -3619,9 +3746,7 @@ pushdecl (x)
&& oldglobal == NULL_TREE && oldglobal == NULL_TREE
&& DECL_EXTERNAL (x) && DECL_EXTERNAL (x)
&& TREE_PUBLIC (x)) && TREE_PUBLIC (x))
{ TREE_PUBLIC (name) = 1;
TREE_PUBLIC (name) = 1;
}
if (DECL_FROM_INLINE (x)) if (DECL_FROM_INLINE (x))
/* Inline decls shadow nothing. */; /* Inline decls shadow nothing. */;
...@@ -3642,7 +3767,8 @@ pushdecl (x) ...@@ -3642,7 +3767,8 @@ pushdecl (x)
if (b->parm_flag == 1) if (b->parm_flag == 1)
cp_error ("declaration of `%#D' shadows a parameter", name); 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)) && !DECL_DEAD_FOR_LOCAL (oldlocal))
{ {
warning ("variable `%s' shadows local", warning ("variable `%s' shadows local",
...@@ -3686,15 +3812,20 @@ pushdecl (x) ...@@ -3686,15 +3812,20 @@ pushdecl (x)
/* RTTI TD entries are created while defining the type_info. */ /* RTTI TD entries are created while defining the type_info. */
|| (TYPE_LANG_SPECIFIC (TREE_TYPE (x)) || (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
&& TYPE_BEING_DEFINED (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. if (need_new_binding)
We will reverse them later if necessary. */ {
TREE_CHAIN (x) = b->names; /* Put decls on list in reverse order.
b->names = x; We will reverse them later if necessary. */
if (! (b != global_binding_level || TREE_PERMANENT (x))) TREE_CHAIN (x) = current_binding_level->names;
my_friendly_abort (124); current_binding_level->names = x;
if (! (current_binding_level != global_binding_level
|| TREE_PERMANENT (x)))
my_friendly_abort (124);
}
return x; return x;
} }
...@@ -3828,9 +3959,7 @@ pushdecl_class_level (x) ...@@ -3828,9 +3959,7 @@ pushdecl_class_level (x)
push_class_level_binding (name, x); push_class_level_binding (name, x);
if (TREE_CODE (x) == TYPE_DECL) 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) ...@@ -3874,12 +4003,20 @@ push_class_level_binding (name, x)
&& purpose_member (name, class_binding_level->class_shadowed)) && purpose_member (name, class_binding_level->class_shadowed))
return; 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 (); maybe_push_cache_obstack ();
class_binding_level->class_shadowed class_binding_level->class_shadowed
= tree_cons (name, IDENTIFIER_CLASS_VALUE (name), = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
class_binding_level->class_shadowed); class_binding_level->class_shadowed);
pop_obstacks (); 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; IDENTIFIER_CLASS_VALUE (name) = x;
obstack_ptr_grow (&decl_obstack, x); obstack_ptr_grow (&decl_obstack, x);
} }
...@@ -3934,11 +4071,11 @@ push_using_directive (used) ...@@ -3934,11 +4071,11 @@ push_using_directive (used)
return ud; return ud;
} }
/* DECL is a FUNCTION_DECL which may have other definitions already in /* DECL is a FUNCTION_DECL for a non-member function, which may have
place. We get around this by making the value of the identifier point other definitions already in place. We get around this by making
to a list of all the things that want to be referenced by that name. It the value of the identifier point to a list of all the things that
is then up to the users of that name to decide what to do with that want to be referenced by that name. It is then up to the users of
list. 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 DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its DECL_RESULT
slot. It is dealt with the same way. slot. It is dealt with the same way.
...@@ -3952,13 +4089,14 @@ push_overloaded_decl (decl, forgettable) ...@@ -3952,13 +4089,14 @@ push_overloaded_decl (decl, forgettable)
tree decl; tree decl;
int forgettable; int forgettable;
{ {
tree orig_name = DECL_NAME (decl); tree name = DECL_NAME (decl);
tree old; tree old;
tree new_binding;
int doing_global = (namespace_bindings_p () || ! forgettable); int doing_global = (namespace_bindings_p () || ! forgettable);
if (doing_global) 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 if (old && TREE_CODE (old) == FUNCTION_DECL
&& DECL_ARTIFICIAL (old) && DECL_ARTIFICIAL (old)
&& (DECL_BUILT_IN (old) || DECL_BUILT_IN_NONANSI (old))) && (DECL_BUILT_IN (old) || DECL_BUILT_IN_NONANSI (old)))
...@@ -3969,16 +4107,7 @@ push_overloaded_decl (decl, forgettable) ...@@ -3969,16 +4107,7 @@ push_overloaded_decl (decl, forgettable)
} }
} }
else else
{ old = lookup_name_current_level (name);
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;
}
}
if (old) if (old)
{ {
...@@ -4011,17 +4140,44 @@ push_overloaded_decl (decl, forgettable) ...@@ -4011,17 +4140,44 @@ push_overloaded_decl (decl, forgettable)
if (old || TREE_CODE (decl) == TEMPLATE_DECL) if (old || TREE_CODE (decl) == TEMPLATE_DECL)
{ {
if (old && TREE_CODE (old) != OVERLOAD) if (old && TREE_CODE (old) != OVERLOAD)
old = ovl_cons (old, NULL_TREE); new_binding = ovl_cons (decl, ovl_cons (old, NULL_TREE));
old = ovl_cons (decl, old); else
new_binding = ovl_cons (decl, old);
} }
else else
/* orig_name is not ambiguous. */ /* NAME is not ambiguous. */
old = decl; new_binding = decl;
if (doing_global) if (doing_global)
set_namespace_binding (orig_name, current_namespace, old); set_namespace_binding (name, current_namespace, new_binding);
else 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; return decl;
} }
...@@ -5073,7 +5229,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only) ...@@ -5073,7 +5229,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
register tree val; register tree val;
int yylex = 0; int yylex = 0;
tree from_obj = NULL_TREE; tree from_obj = NULL_TREE;
tree locval, classval;
int flags; int flags;
/* Hack: copy flag set by parser, if set. */ /* Hack: copy flag set by parser, if set. */
...@@ -5166,140 +5321,86 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only) ...@@ -5166,140 +5321,86 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
else else
flags = lookup_flags (prefer_type, namespaces_only); flags = lookup_flags (prefer_type, namespaces_only);
locval = classval = NULL_TREE; /* First, look in a non-global scope, carefully avoiding any
class-scope bindings if required. */
if (! namespace_bindings_p () && IDENTIFIER_LOCAL_VALUE (name)) val = IDENTIFIER_BINDING (name);
{ while (val && nonclass && !LOCAL_BINDING_P (val))
locval = qualify_lookup (IDENTIFIER_LOCAL_VALUE (name), flags); val = TREE_CHAIN (val);
/* Kludge kludge kludge */ /* Get the DECL actually bound. */
if (locval == NULL_TREE && prefer_type) if (val)
{ val = BINDING_VALUE (val);
locval = REAL_IDENTIFIER_TYPE_VALUE (name);
if (locval && locval != global_type_node /* If VAL is a type from a dependent base, we're not really supposed
&& TYPE_NAME (locval) to be able to see it; the fact that we can is the "implicit
&& DECL_FUNCTION_SCOPE_P (TYPE_NAME (locval))) typename" extension. We call lookup_field here to turn VAL into
locval = TYPE_NAME (locval); a TYPE_DECL for a TYPENAME_TYPE. */
else if (processing_template_decl && val
locval = NULL_TREE; && val == IDENTIFIER_CLASS_VALUE (name)
} && TREE_CODE (val) == TYPE_DECL
} && !currently_open_class (DECL_CONTEXT (val))
&& uses_template_parms (current_class_type))
/* In C++ class fields are between local and global scope, val = lookup_field (current_class_type, name, 0, 1);
just before the global scope. */
if (current_class_type && ! nonclass) /* Make sure that this binding is the sort of thing we're looking
{ for. */
classval = IDENTIFIER_CLASS_VALUE (name); val = qualify_lookup (val, flags);
if (classval == NULL_TREE && TYPE_BEING_DEFINED (current_class_type))
/* Try to find values from base classes if we are presently /* We don't put names from baseclasses onto the IDENTIFIER_BINDING
defining a type. We are primarily interested in list when we're defining a type. It would probably be simpler to
TYPE_DECLs or constants. */ do this, but we don't. So, we must lookup names from base
classval = lookup_field (current_class_type, name, 0, prefer_type); classes explicitly. */
if (!val && !nonclass
/* Add implicit 'typename' to types from template bases. lookup_field && current_class_type && TYPE_BEING_DEFINED (current_class_type))
will do this for us. If classval is actually from an enclosing {
scope, lookup_nested_field will get it for us. */ val = qualify_lookup (lookup_field (current_class_type, name, 0, 0),
else if (processing_template_decl flags);
&& classval && TREE_CODE (classval) == TYPE_DECL if (!val)
&& ! currently_open_class (DECL_CONTEXT (classval)) val = qualify_lookup (lookup_nested_field (name, !yylex),
&& uses_template_parms (current_class_type)) flags);
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);
} }
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 tree global_val;
can happen in two ways:
o We are in a member function of a class. /* Any other name takes precedence over an implicit typename. Warn the
o We are in a local class within a function. user about this potentially confusing lookup. */
global_val = unqualified_namespace_lookup (name, flags);
We need to determine which one of these situations is if (global_val)
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)
{ {
tree subtype; tree subtype;
val = locval;
/* Only warn when not lexing; we don't want to warn if they /* Only warn when not lexing; we don't want to warn if they
use this name as a declarator. */ use this name as a declarator. */
subtype = TREE_TYPE (TREE_TYPE (classval)); subtype = TREE_TYPE (TREE_TYPE (val));
if (! yylex if (! yylex
&& ! (TREE_CODE (locval) == TEMPLATE_DECL && ! (TREE_CODE (global_val) == TEMPLATE_DECL
&& CLASSTYPE_TEMPLATE_INFO (subtype) && CLASSTYPE_TEMPLATE_INFO (subtype)
&& CLASSTYPE_TI_TEMPLATE (subtype) == locval) && CLASSTYPE_TI_TEMPLATE (subtype) == global_val)
&& ! (TREE_CODE (locval) == TYPE_DECL && ! (TREE_CODE (global_val) == TYPE_DECL
&& same_type_p (TREE_TYPE (locval), subtype))) && 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", cp_warning (" instead of `%D' from dependent base class",
classval); val);
cp_warning (" (use `typename %T::%D' if that's what you meant)", cp_warning (" (use `typename %T::%D' if that's what you meant)",
constructor_name (current_class_type), name); 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: done:
if (val) if (val)
...@@ -5381,13 +5482,16 @@ lookup_name_current_level (name) ...@@ -5381,13 +5482,16 @@ lookup_name_current_level (name)
if (t != NULL_TREE && TREE_CODE (t) == TREE_LIST) if (t != NULL_TREE && TREE_CODE (t) == TREE_LIST)
t = TREE_VALUE (t); 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; struct binding_level *b = current_binding_level;
while (1) while (1)
{ {
if (purpose_member (name, b->shadowed)) if (BINDING_LEVEL (IDENTIFIER_BINDING (name)) == b)
return IDENTIFIER_LOCAL_VALUE (name); return IDENTIFIER_VALUE (name);
if (b->keep == 2) if (b->keep == 2)
b = b->level_chain; b = b->level_chain;
else else
...@@ -7681,7 +7785,8 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) ...@@ -7681,7 +7785,8 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
if (current_binding_level->is_for_scope) 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 /* Check to see if the same name is already bound at
the outer level, either because it was directly declared, the outer level, either because it was directly declared,
...@@ -7693,36 +7798,20 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) ...@@ -7693,36 +7798,20 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
Otherwise, we need to preserve the temp slot for decl Otherwise, we need to preserve the temp slot for decl
to last into the outer binding level. */ to last into the outer binding level. */
int handling_dead_for_vars = 0; tree outer_binding
tree link = outer->names; = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (decl)));
for (; ; link = TREE_CHAIN (link))
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) BINDING_VALUE (outer_binding)
{ = DECL_SHADOWED_FOR_VAR (BINDING_VALUE (outer_binding));
link = outer->dead_vars_from_for; current_binding_level->is_for_scope = 0;
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;
}
} }
else if (DECL_IN_MEMORY_P (decl))
preserve_temp_slots (DECL_RTL (decl));
} }
expand_start_target_temps (); expand_start_target_temps ();
...@@ -11032,18 +11121,14 @@ parmlist_is_exprlist (exprs) ...@@ -11032,18 +11121,14 @@ parmlist_is_exprlist (exprs)
return 1; return 1;
} }
/* Subroutine of `grokparms'. In a fcn definition, arg types must /* Subroutine of start_function. Ensure that each of the parameter
be complete. types (as listed in PARMS) is complete, as is required for a
function definition. */
C++: also subroutine of `start_function'. */
static void static void
require_complete_types_for_parms (parms) require_complete_types_for_parms (parms)
tree parms; tree parms;
{ {
if (processing_template_decl)
return;
while (parms) while (parms)
{ {
tree type = TREE_TYPE (parms); tree type = TREE_TYPE (parms);
...@@ -11058,31 +11143,7 @@ require_complete_types_for_parms (parms) ...@@ -11058,31 +11143,7 @@ require_complete_types_for_parms (parms)
} }
else else
layout_decl (parms, 0); 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); parms = TREE_CHAIN (parms);
} }
} }
...@@ -11276,16 +11337,20 @@ grokparms (first_parm, funcdef_flag) ...@@ -11276,16 +11337,20 @@ grokparms (first_parm, funcdef_flag)
/* Unparsed default arg from in-class decl. */ /* Unparsed default arg from in-class decl. */
else if (TREE_CODE (init) == DEFAULT_ARG) else if (TREE_CODE (init) == DEFAULT_ARG)
; ;
else if (TREE_CODE (init) == VAR_DECL else if (TREE_CODE (init) == PARM_DECL
|| 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 /* ``Local variables may not be used in
argument expressions.'' dpANSI C++ 8.2.6 */ default argument expressions.''
/* If extern int i; within a function is not dpANSI C++ 8.2.6 */
considered a local variable, then this code is
wrong. */
cp_error ("local variable `%D' may not be used as a default argument", init); cp_error ("local variable `%D' may not be used as a default argument", init);
any_error = 1; any_error = 1;
} }
...@@ -11349,10 +11414,6 @@ grokparms (first_parm, funcdef_flag) ...@@ -11349,10 +11414,6 @@ grokparms (first_parm, funcdef_flag)
last_function_parms = decls; 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; return result;
} }
...@@ -11417,20 +11478,45 @@ grok_ctor_properties (ctype, decl) ...@@ -11417,20 +11478,45 @@ grok_ctor_properties (ctype, decl)
parmtype = TREE_VALUE (parmtypes); 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 if (TREE_CODE (parmtype) == REFERENCE_TYPE
&& TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype
&& (TREE_CHAIN (parmtypes) == NULL_TREE && (TREE_CHAIN (parmtypes) == NULL_TREE
|| TREE_CHAIN (parmtypes) == void_list_node || 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; TYPE_HAS_INIT_REF (ctype) = 1;
if (CP_TYPE_CONST_P (TREE_TYPE (parmtype))) if (CP_TYPE_CONST_P (TREE_TYPE (parmtype)))
TYPE_HAS_CONST_INIT_REF (ctype) = 1; 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 else if (TYPE_MAIN_VARIANT (parmtype) == ctype
&& (TREE_CHAIN (parmtypes) == NULL_TREE && (TREE_CHAIN (parmtypes) == NULL_TREE
|| TREE_CHAIN (parmtypes) == void_list_node || 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&)'", cp_error ("invalid constructor; you probably meant `%T (const %T&)'",
ctype, ctype); ctype, ctype);
...@@ -11486,7 +11572,15 @@ grok_op_properties (decl, virtualp, friendp) ...@@ -11486,7 +11572,15 @@ grok_op_properties (decl, virtualp, friendp)
if (! 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; TYPE_HAS_ASSIGNMENT (current_class_type) = 1;
else if (name == ansi_opname[(int) CALL_EXPR]) else if (name == ansi_opname[(int) CALL_EXPR])
TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1; TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
...@@ -12477,6 +12571,15 @@ static int function_depth; ...@@ -12477,6 +12571,15 @@ static int function_depth;
they describe the function's name and the type it returns, they describe the function's name and the type it returns,
but twisted together in a fashion that parallels the syntax of C. 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 This function creates a binding context for the function body
as well as setting up the FUNCTION_DECL in current_function_decl. as well as setting up the FUNCTION_DECL in current_function_decl.
...@@ -12577,17 +12680,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p) ...@@ -12577,17 +12680,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
doing_friend = 1; 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_parms = DECL_ARGUMENTS (decl1);
last_function_parm_tags = NULL_TREE; last_function_parm_tags = NULL_TREE;
} }
...@@ -12636,16 +12728,37 @@ start_function (declspecs, declarator, attrs, pre_parsed_p) ...@@ -12636,16 +12728,37 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
&& IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE) && IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE)
cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1))); 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; current_function_decl = decl1;
/* Save the parm names or decls from this function's declarator /* Save the parm names or decls from this function's declarator
where store_parm_decls will find them. */ where store_parm_decls will find them. */
current_function_parms = last_function_parms; current_function_parms = last_function_parms;
current_function_parm_tags = last_function_parm_tags; current_function_parm_tags = last_function_parm_tags;
announce_function (decl1);
if (! processing_template_decl) 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) if (TYPE_SIZE (complete_type (TREE_TYPE (fntype))) == NULL_TREE)
{ {
cp_error ("return-type `%#T' is an incomplete type", cp_error ("return-type `%#T' is an incomplete type",
...@@ -12695,13 +12808,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p) ...@@ -12695,13 +12808,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
(This does not mean `static' in the C sense!) */ (This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1; 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 /* We must call push_template_decl after current_class_type is set
up. (If we are processing inline definitions after exiting a up. (If we are processing inline definitions after exiting a
class scope, current_class_type will be NULL_TREE until set above class scope, current_class_type will be NULL_TREE until set above
...@@ -12937,9 +13043,6 @@ store_parm_decls () ...@@ -12937,9 +13043,6 @@ store_parm_decls ()
/* Initialize RTL machinery. */ /* Initialize RTL machinery. */
init_function_start (fndecl, input_filename, lineno); 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. */ /* Create a binding level for the parms. */
expand_start_bindings (0); expand_start_bindings (0);
...@@ -13025,6 +13128,9 @@ store_parm_decls () ...@@ -13025,6 +13128,9 @@ store_parm_decls ()
storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl))); storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
/* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
declare_function_name ();
/* Initialize the RTL code for the function. */ /* Initialize the RTL code for the function. */
DECL_SAVED_INSNS (fndecl) = NULL_RTX; DECL_SAVED_INSNS (fndecl) = NULL_RTX;
if (! processing_template_decl) if (! processing_template_decl)
...@@ -13135,18 +13241,23 @@ store_return_init (return_id, init) ...@@ -13135,18 +13241,23 @@ store_return_init (return_id, init)
This is called after parsing the body of the function definition. This is called after parsing the body of the function definition.
LINENO is the current line number. LINENO is the current line number.
C++: CALL_POPLEVEL is non-zero if an extra call to poplevel FLAGS is a bitwise or of the following values:
(and expand_end_bindings) must be made to take care of the binding 1 - CALL_POPLEVEL
contour for the base initializers. This is only relevant for An extra call to poplevel (and expand_end_bindings) must be
constructors. 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 NESTED is nonzero if we were in the middle of compiling another function
when we started on this one. */ when we started on this one. */
void void
finish_function (lineno, call_poplevel, nested) finish_function (lineno, flags, nested)
int lineno; int lineno;
int call_poplevel; int flags;
int nested; int nested;
{ {
register tree fndecl = current_function_decl; register tree fndecl = current_function_decl;
...@@ -13155,6 +13266,9 @@ finish_function (lineno, call_poplevel, nested) ...@@ -13155,6 +13266,9 @@ finish_function (lineno, call_poplevel, nested)
/* Label to use if this function is supposed to return a value. */ /* Label to use if this function is supposed to return a value. */
tree no_return_label = NULL_TREE; tree no_return_label = NULL_TREE;
tree decls = 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 /* When we get some parse errors, we can end up without a
current_function_decl, so cope. */ current_function_decl, so cope. */
...@@ -13560,6 +13674,27 @@ finish_function (lineno, call_poplevel, nested) ...@@ -13560,6 +13674,27 @@ finish_function (lineno, call_poplevel, nested)
/* Generate rtl for function exit. */ /* Generate rtl for function exit. */
expand_function_end (input_filename, lineno, 1); 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 /* This must come after expand_function_end because cleanups might
have declarations (from inline functions) that need to go into have declarations (from inline functions) that need to go into
...@@ -13568,6 +13703,13 @@ finish_function (lineno, call_poplevel, nested) ...@@ -13568,6 +13703,13 @@ finish_function (lineno, call_poplevel, nested)
my_friendly_abort (122); my_friendly_abort (122);
poplevel (1, 0, 1); 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, /* Reset scope for C++: if we were in the scope of a class,
then when we finish this function, we are not longer so. then when we finish this function, we are not longer so.
This cannot be done until we know for sure that no more This cannot be done until we know for sure that no more
...@@ -13579,14 +13721,7 @@ finish_function (lineno, call_poplevel, nested) ...@@ -13579,14 +13721,7 @@ finish_function (lineno, call_poplevel, nested)
pop_nested_class (1); pop_nested_class (1);
} }
/* Must mark the RESULT_DECL as being in this function. */ if (!in_template)
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)
{ {
int saved_flag_keep_inline_functions = int saved_flag_keep_inline_functions =
flag_keep_inline_functions; flag_keep_inline_functions;
...@@ -13670,12 +13805,6 @@ finish_function (lineno, call_poplevel, nested) ...@@ -13670,12 +13805,6 @@ finish_function (lineno, call_poplevel, nested)
/* Free all the tree nodes making up this function. */ /* Free all the tree nodes making up this function. */
/* Switch back to allocating nodes permanently /* Switch back to allocating nodes permanently
until we start another function. */ until we start another function. */
if (processing_template_decl)
{
--minimal_parse_mode;
DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl));
}
if (! nested) if (! nested)
permanent_allocation (1); permanent_allocation (1);
...@@ -13710,8 +13839,6 @@ finish_function (lineno, call_poplevel, nested) ...@@ -13710,8 +13839,6 @@ finish_function (lineno, call_poplevel, nested)
} }
/* Create the FUNCTION_DECL for a function definition. /* 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; DECLSPECS and DECLARATOR are the parts of the declaration;
they describe the return type and the name of the function, they describe the return type and the name of the function,
but twisted together in a fashion that parallels the syntax of C. but twisted together in a fashion that parallels the syntax of C.
...@@ -13849,23 +13976,11 @@ finish_method (decl) ...@@ -13849,23 +13976,11 @@ finish_method (decl)
for (link = current_binding_level->names; link; link = TREE_CHAIN (link)) for (link = current_binding_level->names; link; link = TREE_CHAIN (link))
{ {
if (DECL_NAME (link) != NULL_TREE) 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); my_friendly_assert (TREE_CODE (link) != FUNCTION_DECL, 163);
DECL_CONTEXT (link) = NULL_TREE; 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, GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
(HOST_WIDE_INT) current_binding_level->level_chain, (HOST_WIDE_INT) current_binding_level->level_chain,
current_binding_level->parm_flag, current_binding_level->parm_flag,
......
...@@ -4829,7 +4829,7 @@ do_local_using_decl (decl) ...@@ -4829,7 +4829,7 @@ do_local_using_decl (decl)
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype); do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
if (newval) if (newval)
set_identifier_local_value (name, newval); push_local_binding (name, newval);
if (newtype) if (newtype)
set_identifier_type_value (name, newtype); set_identifier_type_value (name, newtype);
} }
......
...@@ -84,6 +84,7 @@ static int reduce_cmp PROTO((int *, int *)); ...@@ -84,6 +84,7 @@ static int reduce_cmp PROTO((int *, int *));
static int token_cmp PROTO((int *, int *)); static int token_cmp PROTO((int *, int *));
#endif #endif
#endif #endif
static void begin_definition_of_inclass_inline PROTO((struct pending_inline*));
/* Given a file name X, return the nondirectory portion. /* Given a file name X, return the nondirectory portion.
Keep in mind that X can be computed more than once. */ Keep in mind that X can be computed more than once. */
...@@ -322,12 +323,13 @@ get_time_identifier (name) ...@@ -322,12 +323,13 @@ get_time_identifier (name)
bcopy (name, buf+5, len); bcopy (name, buf+5, len);
buf[len+5] = '\0'; buf[len+5] = '\0';
time_identifier = get_identifier (buf); time_identifier = get_identifier (buf);
if (IDENTIFIER_LOCAL_VALUE (time_identifier) == NULL_TREE) if (TIME_IDENTIFIER_TIME (time_identifier) == NULL_TREE)
{ {
push_obstacks_nochange (); push_obstacks_nochange ();
end_temporary_allocation (); end_temporary_allocation ();
IDENTIFIER_LOCAL_VALUE (time_identifier) = build_int_2 (0, 0); TIME_IDENTIFIER_TIME (time_identifier) = build_int_2 (0, 0);
IDENTIFIER_CLASS_VALUE (time_identifier) = build_int_2 (0, 1); TIME_IDENTIFIER_FILEINFO (time_identifier)
= build_int_2 (0, 1);
SET_IDENTIFIER_GLOBAL_VALUE (time_identifier, filename_times); SET_IDENTIFIER_GLOBAL_VALUE (time_identifier, filename_times);
filename_times = time_identifier; filename_times = time_identifier;
pop_obstacks (); pop_obstacks ();
...@@ -435,7 +437,8 @@ init_filename_times () ...@@ -435,7 +437,8 @@ init_filename_times ()
{ {
header_time = 0; header_time = 0;
body_time = my_get_run_time (); 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 () ...@@ -1145,7 +1148,7 @@ extract_interface_info ()
} }
if (!fileinfo) if (!fileinfo)
fileinfo = get_time_identifier (input_filename); fileinfo = get_time_identifier (input_filename);
fileinfo = IDENTIFIER_CLASS_VALUE (fileinfo); fileinfo = TIME_IDENTIFIER_FILEINFO (fileinfo);
interface_only = TREE_INT_CST_LOW (fileinfo); interface_only = TREE_INT_CST_LOW (fileinfo);
interface_unknown = TREE_INT_CST_HIGH (fileinfo); interface_unknown = TREE_INT_CST_HIGH (fileinfo);
} }
...@@ -1196,7 +1199,7 @@ set_typedecl_interface_info (prev, vars) ...@@ -1196,7 +1199,7 @@ set_typedecl_interface_info (prev, vars)
tree prev ATTRIBUTE_UNUSED, vars; tree prev ATTRIBUTE_UNUSED, vars;
{ {
tree id = get_time_identifier (DECL_SOURCE_FILE (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); tree type = TREE_TYPE (vars);
CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo) CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo)
...@@ -1222,6 +1225,37 @@ set_vardecl_interface_info (prev, vars) ...@@ -1222,6 +1225,37 @@ set_vardecl_interface_info (prev, vars)
return 0; 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 /* 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 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 to be parsed; after it has been, the rule for fndef in parse.y will
...@@ -1231,7 +1265,6 @@ void ...@@ -1231,7 +1265,6 @@ void
do_pending_inlines () do_pending_inlines ()
{ {
struct pending_inline *t; struct pending_inline *t;
tree context;
/* Oops, we're still dealing with the last batch. */ /* Oops, we're still dealing with the last batch. */
if (yychar == PRE_PARSED_FUNCTION_DECL) if (yychar == PRE_PARSED_FUNCTION_DECL)
...@@ -1258,32 +1291,7 @@ do_pending_inlines () ...@@ -1258,32 +1291,7 @@ do_pending_inlines ()
return; return;
/* Now start processing the first inline function. */ /* Now start processing the first inline function. */
context = hack_decl_function_context (t->fndecl); begin_definition_of_inclass_inline (t);
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;
} }
static int nextchar = -1; static int nextchar = -1;
...@@ -1299,7 +1307,6 @@ process_next_inline (t) ...@@ -1299,7 +1307,6 @@ process_next_inline (t)
tree context; tree context;
struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t); struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
context = hack_decl_function_context (i->fndecl); context = hack_decl_function_context (i->fndecl);
maybe_end_member_template_processing ();
if (context) if (context)
pop_cp_function_context (context); pop_cp_function_context (context);
i = i->next; i = i->next;
...@@ -1317,24 +1324,8 @@ process_next_inline (t) ...@@ -1317,24 +1324,8 @@ process_next_inline (t)
} }
yychar = YYEMPTY; yychar = YYEMPTY;
end_input (); 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) if (i)
{ begin_definition_of_inclass_inline (i);
interface_unknown = i->interface == 1;
interface_only = i->interface == 0;
}
else else
extract_interface_info (); extract_interface_info ();
} }
...@@ -2507,7 +2498,7 @@ linenum: ...@@ -2507,7 +2498,7 @@ linenum:
int this_time = my_get_run_time (); int this_time = my_get_run_time ();
tree time_identifier = get_time_identifier (TREE_STRING_POINTER (yylval.ttype)); tree time_identifier = get_time_identifier (TREE_STRING_POINTER (yylval.ttype));
header_time += this_time - body_time; 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_time - body_time;
this_filename_time = time_identifier; this_filename_time = time_identifier;
body_time = this_time; body_time = this_time;
...@@ -2943,11 +2934,9 @@ do_identifier (token, parsing, args) ...@@ -2943,11 +2934,9 @@ do_identifier (token, parsing, args)
/* Do Koenig lookup if appropriate (inside templates we build lookup /* Do Koenig lookup if appropriate (inside templates we build lookup
expressions instead). */ expressions instead). */
if (args && !current_template_parms && (!id || is_global (id))) if (args && !current_template_parms && (!id || is_global (id)))
{ /* If we have arguments and we only found global names, do Koenig
/* If we have arguments and we only found global names, lookup. */
do Koenig lookup. */ id = lookup_arg_dependent (token, id, args);
id = lookup_arg_dependent (token, id, args);
}
/* Remember that this name has been used in the class definition, as per /* Remember that this name has been used in the class definition, as per
[class.scope0] */ [class.scope0] */
...@@ -3183,16 +3172,20 @@ identifier_typedecl_value (node) ...@@ -3183,16 +3172,20 @@ identifier_typedecl_value (node)
type = IDENTIFIER_TYPE_VALUE (node); type = IDENTIFIER_TYPE_VALUE (node);
if (type == NULL_TREE) if (type == NULL_TREE)
return NULL_TREE; return NULL_TREE;
#define do(X) \
{ \ if (IDENTIFIER_BINDING (node))
t = (X); \ {
if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type) \ t = IDENTIFIER_VALUE (node);
return t; \ if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type)
} return t;
do (IDENTIFIER_LOCAL_VALUE (node)); }
do (IDENTIFIER_CLASS_VALUE (node)); if (IDENTIFIER_NAMESPACE_VALUE (node))
do (IDENTIFIER_NAMESPACE_VALUE (node)); {
#undef do t = IDENTIFIER_NAMESPACE_VALUE (node);
if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type)
return t;
}
/* Will this one ever happen? */ /* Will this one ever happen? */
if (TYPE_MAIN_DECL (type)) if (TYPE_MAIN_DECL (type))
return TYPE_MAIN_DECL (type); return TYPE_MAIN_DECL (type);
...@@ -4737,7 +4730,7 @@ dump_time_statistics () ...@@ -4737,7 +4730,7 @@ dump_time_statistics ()
{ {
register tree prev = 0, decl, next; register tree prev = 0, decl, next;
int this_time = my_get_run_time (); 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; += this_time - body_time;
fprintf (stderr, "\n******\n"); fprintf (stderr, "\n******\n");
...@@ -4756,7 +4749,7 @@ dump_time_statistics () ...@@ -4756,7 +4749,7 @@ dump_time_statistics ()
for (decl = prev; decl; decl = IDENTIFIER_GLOBAL_VALUE (decl)) for (decl = prev; decl; decl = IDENTIFIER_GLOBAL_VALUE (decl))
print_time (IDENTIFIER_POINTER (decl), print_time (IDENTIFIER_POINTER (decl),
TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (decl))); TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (decl)));
} }
void void
...@@ -4847,7 +4840,8 @@ handle_cp_pragma (pname) ...@@ -4847,7 +4840,8 @@ handle_cp_pragma (pname)
} }
else if (! strcmp (pname, "interface")) 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; char *main_filename = input_filename;
main_filename = file_name_nondirectory (main_filename); main_filename = file_name_nondirectory (main_filename);
...@@ -4882,7 +4876,7 @@ handle_cp_pragma (pname) ...@@ -4882,7 +4876,7 @@ handle_cp_pragma (pname)
#ifdef AUTO_IMPLEMENT #ifdef AUTO_IMPLEMENT
filename = file_name_nondirectory (main_input_filename); filename = file_name_nondirectory (main_input_filename);
fi = get_time_identifier (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_LOW (fi) = 0;
TREE_INT_CST_HIGH (fi) = 1; TREE_INT_CST_HIGH (fi) = 1;
/* Get default. */ /* Get default. */
...@@ -4902,7 +4896,8 @@ handle_cp_pragma (pname) ...@@ -4902,7 +4896,8 @@ handle_cp_pragma (pname)
} }
else if (! strcmp (pname, "implementation")) 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; char *main_filename = main_input_filename ? main_input_filename : input_filename;
main_filename = file_name_nondirectory (main_filename); main_filename = file_name_nondirectory (main_filename);
......
...@@ -236,7 +236,7 @@ empty_parms () ...@@ -236,7 +236,7 @@ empty_parms ()
%token <ttype> PRE_PARSED_CLASS_DECL DEFARG DEFARG_MARKER %token <ttype> PRE_PARSED_CLASS_DECL DEFARG DEFARG_MARKER
%type <ttype> component_constructor_declarator %type <ttype> component_constructor_declarator
%type <ttype> fn.def2 return_id fn.defpen 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_class_head named_class_head_sans_basetype
%type <ttype> named_complex_class_head_sans_basetype %type <ttype> named_complex_class_head_sans_basetype
%type <ttype> unnamed_class_head %type <ttype> unnamed_class_head
...@@ -639,7 +639,11 @@ fndef: ...@@ -639,7 +639,11 @@ fndef:
fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error
{ finish_function (lineno, (int)$3, 0); } { finish_function (lineno, (int)$3, 0); }
| fn.def1 maybe_return_init function_try_block | 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 | fn.def1 maybe_return_init error
{ } { }
; ;
...@@ -2037,7 +2041,7 @@ initlist: ...@@ -2037,7 +2041,7 @@ initlist:
fn.defpen: fn.defpen:
PRE_PARSED_FUNCTION_DECL PRE_PARSED_FUNCTION_DECL
{ start_function (NULL_TREE, TREE_VALUE ($1), { start_function (NULL_TREE, TREE_VALUE ($1),
NULL_TREE, 1); NULL_TREE, 2);
reinit_parse_for_function (); } reinit_parse_for_function (); }
pending_inline: pending_inline:
...@@ -2045,11 +2049,16 @@ pending_inline: ...@@ -2045,11 +2049,16 @@ pending_inline:
{ {
int nested = (hack_decl_function_context int nested = (hack_decl_function_context
(current_function_decl) != NULL_TREE); (current_function_decl) != NULL_TREE);
finish_function (lineno, (int)$3, nested); finish_function (lineno, (int)$3 | 2, nested);
process_next_inline ($1); process_next_inline ($1);
} }
| fn.defpen maybe_return_init function_try_block | 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 | fn.defpen maybe_return_init error
{ process_next_inline ($1); } { process_next_inline ($1); }
; ;
...@@ -3339,10 +3348,8 @@ function_try_block: ...@@ -3339,10 +3348,8 @@ function_try_block:
} }
handler_seq handler_seq
{ {
int nested = (hack_decl_function_context
(current_function_decl) != NULL_TREE);
expand_end_all_catch (); expand_end_all_catch ();
finish_function (lineno, (int)$3, nested); $$ = $3;
} }
; ;
......
...@@ -426,14 +426,14 @@ maybe_end_member_template_processing () ...@@ -426,14 +426,14 @@ maybe_end_member_template_processing ()
template <class T> class C { template <class U> void f(U); } template <class T> class C { template <class U> void f(U); }
then neither C<int>::f<char> nor C<T>::f<double> is considered 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 int
is_member_template (t) is_member_template (t)
tree t; tree t;
{ {
if (TREE_CODE (t) != FUNCTION_DECL if (!DECL_FUNCTION_TEMPLATE_P (t))
&& !DECL_FUNCTION_TEMPLATE_P (t))
/* Anything that isn't a function or a template function is /* Anything that isn't a function or a template function is
certainly not a member template. */ certainly not a member template. */
return 0; return 0;
...@@ -442,31 +442,12 @@ is_member_template (t) ...@@ -442,31 +442,12 @@ is_member_template (t)
if (hack_decl_function_context (t)) if (hack_decl_function_context (t))
return 0; return 0;
if ((DECL_FUNCTION_MEMBER_P (t) return (DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (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
/* If there are more levels of template parameters than /* If there are more levels of template parameters than
there are template classes surrounding the declaration, there are template classes surrounding the declaration,
then we have a member template. */ then we have a member template. */
&& (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)) > && (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) >
template_class_depth (DECL_CLASS_CONTEXT (t)))) template_class_depth (DECL_CLASS_CONTEXT (t))));
return 1;
}
return 0;
} }
#if 0 /* UNUSED */ #if 0 /* UNUSED */
...@@ -1487,28 +1468,27 @@ int comp_template_parms (parms1, parms2) ...@@ -1487,28 +1468,27 @@ int comp_template_parms (parms1, parms2)
} }
/* Returns 1 iff old_id is a template parameter. OLD_DECL is the decl /* Returns 1 iff DECL is a template parameter. */
from IDENTIFIER_LOCAL_VALUE (new identifier). */
int decl_template_parm_p (old_decl) int decl_template_parm_p (decl)
tree old_decl; tree decl;
{ {
/* For template template parms. */ /* For template template parms. */
if (TREE_CODE (old_decl) == TEMPLATE_DECL if (TREE_CODE (decl) == TEMPLATE_DECL
&& TREE_TYPE (old_decl) && TREE_TYPE (decl)
&& TREE_CODE (TREE_TYPE (old_decl)) == TEMPLATE_TEMPLATE_PARM) && TREE_CODE (TREE_TYPE (decl)) == TEMPLATE_TEMPLATE_PARM)
return 1; return 1;
/* For template type parms. */ /* For template type parms. */
if (TREE_CODE (old_decl) == TYPE_DECL if (TREE_CODE (decl) == TYPE_DECL
&& TREE_TYPE (old_decl) && TREE_TYPE (decl)
&& TREE_CODE (TREE_TYPE (old_decl)) == TEMPLATE_TYPE_PARM) && TREE_CODE (TREE_TYPE (decl)) == TEMPLATE_TYPE_PARM)
return 1; return 1;
/* For template non-type parms. */ /* For template non-type parms. */
if (TREE_CODE (old_decl) == CONST_DECL if (TREE_CODE (decl) == CONST_DECL
&& DECL_INITIAL (old_decl) && DECL_INITIAL (decl)
&& TREE_CODE (DECL_INITIAL (old_decl)) == TEMPLATE_PARM_INDEX) && TREE_CODE (DECL_INITIAL (decl)) == TEMPLATE_PARM_INDEX)
return 1; return 1;
return 0; return 0;
...@@ -1523,11 +1503,10 @@ void ...@@ -1523,11 +1503,10 @@ void
check_template_shadow (decl) check_template_shadow (decl)
tree decl; tree decl;
{ {
if (current_template_parms tree olddecl = IDENTIFIER_VALUE (DECL_NAME (decl));
&& IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl)))
{
tree olddecl = IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl));
if (current_template_parms && olddecl)
{
/* We check for decl != olddecl to avoid bogus errors for using a /* We check for decl != olddecl to avoid bogus errors for using a
name inside a class. We check TPFI to avoid duplicate errors for name inside a class. We check TPFI to avoid duplicate errors for
inline member templates. */ inline member templates. */
...@@ -3423,9 +3402,9 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope) ...@@ -3423,9 +3402,9 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
if (TREE_CODE (d1) == IDENTIFIER_NODE) if (TREE_CODE (d1) == IDENTIFIER_NODE)
{ {
if (IDENTIFIER_LOCAL_VALUE (d1) if (IDENTIFIER_VALUE (d1)
&& DECL_TEMPLATE_TEMPLATE_PARM_P (IDENTIFIER_LOCAL_VALUE (d1))) && DECL_TEMPLATE_TEMPLATE_PARM_P (IDENTIFIER_VALUE (d1)))
template = IDENTIFIER_LOCAL_VALUE (d1); template = IDENTIFIER_VALUE (d1);
else else
{ {
if (context) if (context)
...@@ -3468,9 +3447,10 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope) ...@@ -3468,9 +3447,10 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
my_friendly_abort (272); my_friendly_abort (272);
/* With something like `template <class T> class X class X { ... };' /* With something like `template <class T> class X class X { ... };'
we could end up with D1 having nothing but an IDENTIFIER_LOCAL_VALUE. 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 We don't want to do that, but we have to deal with the situation,
let's give them some syntax errors to chew on instead of a crash. */ so let's give them some syntax errors to chew on instead of a
crash. */
if (! template) if (! template)
{ {
cp_error ("`%T' is not a template", d1); cp_error ("`%T' is not a template", d1);
...@@ -5434,11 +5414,9 @@ tsubst_decl (t, args, type, in_decl) ...@@ -5434,11 +5414,9 @@ tsubst_decl (t, args, type, in_decl)
if (member && !strncmp (OPERATOR_TYPENAME_FORMAT, if (member && !strncmp (OPERATOR_TYPENAME_FORMAT,
IDENTIFIER_POINTER (DECL_NAME (r)), IDENTIFIER_POINTER (DECL_NAME (r)),
sizeof (OPERATOR_TYPENAME_FORMAT) - 1)) sizeof (OPERATOR_TYPENAME_FORMAT) - 1))
{ /* Type-conversion operator. Reconstruct the name, in
/* Type-conversion operator. Reconstruct the name, in case it's the name of one of the template's parameters. */
case it's the name of one of the template's parameters. */ DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
}
DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, t); DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, t);
DECL_MAIN_VARIANT (r) = r; DECL_MAIN_VARIANT (r) = r;
...@@ -5453,14 +5431,6 @@ tsubst_decl (t, args, type, in_decl) ...@@ -5453,14 +5431,6 @@ tsubst_decl (t, args, type, in_decl)
DECL_PENDING_INLINE_INFO (r) = 0; DECL_PENDING_INLINE_INFO (r) = 0;
TREE_USED (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 /* Set up the DECL_TEMPLATE_INFO for R and compute its mangled
name. There's no need to do this in the special friend name. There's no need to do this in the special friend
case mentioned above where GEN_TMPL is NULL. */ case mentioned above where GEN_TMPL is NULL. */
...@@ -5507,6 +5477,14 @@ tsubst_decl (t, args, type, in_decl) ...@@ -5507,6 +5477,14 @@ tsubst_decl (t, args, type, in_decl)
== NULL_TREE)) == NULL_TREE))
SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r); 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; break;
...@@ -7688,11 +7666,12 @@ unify (tparms, targs, parm, arg, strict, explicit_mask) ...@@ -7688,11 +7666,12 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
} }
case RECORD_TYPE: case RECORD_TYPE:
case UNION_TYPE:
if (TYPE_PTRMEMFUNC_FLAG (parm)) if (TYPE_PTRMEMFUNC_FLAG (parm))
return unify (tparms, targs, TYPE_PTRMEMFUNC_FN_TYPE (parm), return unify (tparms, targs, TYPE_PTRMEMFUNC_FN_TYPE (parm),
arg, strict, explicit_mask); arg, strict, explicit_mask);
if (TREE_CODE (arg) != RECORD_TYPE) if (TREE_CODE (arg) != TREE_CODE (parm))
return 1; return 1;
if (CLASSTYPE_TEMPLATE_INFO (parm) && uses_template_parms (parm)) if (CLASSTYPE_TEMPLATE_INFO (parm) && uses_template_parms (parm))
......
...@@ -152,7 +152,7 @@ print_lang_identifier (file, node, indent) ...@@ -152,7 +152,7 @@ print_lang_identifier (file, node, indent)
{ {
print_node (file, "bindings", IDENTIFIER_NAMESPACE_BINDINGS (node), indent + 4); print_node (file, "bindings", IDENTIFIER_NAMESPACE_BINDINGS (node), indent + 4);
print_node (file, "class", IDENTIFIER_CLASS_VALUE (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, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4); print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4);
print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4); print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
...@@ -168,7 +168,8 @@ lang_print_xnode (file, node, indent) ...@@ -168,7 +168,8 @@ lang_print_xnode (file, node, indent)
switch (TREE_CODE (node)) switch (TREE_CODE (node))
{ {
case CPLUS_BINDING: 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, "value", BINDING_VALUE (node), indent+4);
print_node (file, "chain", TREE_CHAIN (node), indent+4); print_node (file, "chain", TREE_CHAIN (node), indent+4);
break; break;
......
...@@ -4849,7 +4849,8 @@ mark_addressable (exp) ...@@ -4849,7 +4849,8 @@ mark_addressable (exp)
TREE_ASM_WRITTEN (x) = 0; TREE_ASM_WRITTEN (x) = 0;
DECL_RTL (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); 0);
TREE_ADDRESSABLE (x) = 1; TREE_ADDRESSABLE (x) = 1;
...@@ -7235,9 +7236,9 @@ c_expand_return (retval) ...@@ -7235,9 +7236,9 @@ c_expand_return (retval)
if (TEMP_NAME_P (DECL_NAME (whats_returned))) if (TEMP_NAME_P (DECL_NAME (whats_returned)))
warning ("reference to non-lvalue returned"); warning ("reference to non-lvalue returned");
else if (TREE_CODE (TREE_TYPE (whats_returned)) != REFERENCE_TYPE else if (TREE_CODE (TREE_TYPE (whats_returned)) != REFERENCE_TYPE
&& ! TREE_STATIC (whats_returned) && DECL_FUNCTION_SCOPE_P (whats_returned)
&& IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned)) && !(TREE_STATIC (whats_returned)
&& !TREE_PUBLIC (whats_returned)) || TREE_PUBLIC (whats_returned)))
cp_warning_at ("reference to local variable `%D' returned", whats_returned); cp_warning_at ("reference to local variable `%D' returned", whats_returned);
} }
} }
...@@ -7247,9 +7248,9 @@ c_expand_return (retval) ...@@ -7247,9 +7248,9 @@ c_expand_return (retval)
if (TREE_CODE (whats_returned) == VAR_DECL if (TREE_CODE (whats_returned) == VAR_DECL
&& DECL_NAME (whats_returned) && DECL_NAME (whats_returned)
&& IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned)) && DECL_FUNCTION_SCOPE_P (whats_returned)
&& !TREE_STATIC (whats_returned) && !(TREE_STATIC (whats_returned)
&& !TREE_PUBLIC (whats_returned)) || TREE_PUBLIC (whats_returned)))
cp_warning_at ("address of local variable `%D' returned", whats_returned); cp_warning_at ("address of local variable `%D' returned", whats_returned);
} }
} }
......
...@@ -8,11 +8,11 @@ ...@@ -8,11 +8,11 @@
// cfront 2.0 passes this test. // cfront 2.0 passes this test.
enum enum0 { enum0_value_0 }; // ERROR - enum enum0 { enum0_value_0 };
struct struct0 { struct struct0 {
int enum0; // ERROR - int enum0;
void member_function (enum0 e); void member_function (enum0 e); // ERROR -
}; };
void class0::member_function (enum0 e) { // ERROR - void class0::member_function (enum0 e) { // ERROR -
......
...@@ -6,11 +6,11 @@ ...@@ -6,11 +6,11 @@
// keywords: typedef names, shadowing, scope, formal parameter list // keywords: typedef names, shadowing, scope, formal parameter list
class class0; // ERROR - class class0;
struct struct1 { struct struct1 {
int class0; // ERROR - int class0;
void member_function (class0 *); void member_function (class0 *); // ERROR -
}; };
void class1::member_function (class0 *p) { // ERROR - void class1::member_function (class0 *p) { // ERROR -
......
// 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;
}
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;
}
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();
}
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;
}
// Build don't link: // Build don't link:
// excess errors test - XFAIL *-*-* // excess errors test
// This testcase won't fail if class ::foo is forward-declared in the // This testcase won't fail if class ::foo is forward-declared in the
// global namespace, nor if class bar is not a template class. // global namespace, nor if class bar is not a template class.
......
// 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment