cp-tree.def (DECL_STMT): Make it smaller.

* cp-tree.def (DECL_STMT): Make it smaller.
	* cp-tree.h (lang_decl_flags): Move saved_tree to ...
	(lang_decl): ... here.  Add next.
	(DECL_SAVED_TREE): Adjust accordingly.
	(DECL_IMPLICIT_TYPEDEF_P): New macro.
	(SET_DECL_IMPLICIT_TYPEDEF_P): Likewise.
	(DECL_STMT_DECL): Likewise.
	(create_implicit_typedef): New function.
	(maybe_push_decl): Likewise.
	(tsubst_default_argument): New function.
	(at_function_scope_p): Likewise.
	(add_decl_stmt): Likewise.
	(push_permanent_obstack): Likewise.
	* call.c (convert_default_arg): Use tsubst_default_argument.
	* class.c (add_method): Use push_permanent_obstack.
	(build_self_reference): Create a TEMPLATE_DECL for the
	self-reference, if necessary.
	* decl.c (pseudo_global_level_p): Only look at the current binding
	level.
	(push_binding): Use push_permanent_obstack.
	(create_implicit_typedef): New function.
	(pushtag): Use it.
	(duplicate_decls): Use push_permanent_obstack.
	(maybe_push_decl): New function.
	(start_decl): Use it.  Remove dead code.  Use add_decl_stmt.
	(start_decl_1): Remove dead code.
	(cp_finish_decl): Remove DECL_STMT handling here.  Don't use
	pseudo_global_level_p.
	(grokvardecl): Create DECL_LANG_SPECIFIC for a VAR_DECL in a
	template.
	(grokdeclarator): Likewise, for TYPE_DECLs.  Don't use
	pseudo_global_level_p.
	* decl2.c (grokfield): Call push_template_decl for a TYPE_DECL in
	a template.
	(get_sentry): Use push_permanent_obstack.
	* dump.c (dequeue_and_dump): Enable DECL_STMT.
	* except.c (call_eh_info): Use push_permanent_obstack.
	(build_eh_type_ref): Likewise.
	(do_pop_exception): Likewise.
	(expand_eh_spec): Likewise.
	(alloc_eh_object): Likewise.
	(expand_throw): Likewise.
	* init.c (build_java_class_ref): Likewise.
	* lex.c (get_time_identifier): Likewise.
	(free_lang_decl_chain): Correct type.
	(retrofit_lang_decl): Adjust accordingly.
	(build_lang_field_decl): Likewise.
	* lex.h (free_lang_decl_chain): Likewise.
	* parse.y (lang_extdef): Don't use pseudo_global_level_p.
	* parse.c: Regenerated.
	* pt.c (tsubst_default_arguments): New function.
	(retrieve_local_specialization): Likewise.
	(register_local_specialization): Likewise.
	(push_template_decl_real): Use DECL_IMPLICIT_TYPEDEF_P.  Just use
	pseudo_global_level_p to determine whether or not a template is
	primary.
	(lookup_template_class): Likewise.  Use create_implicit_typedef.
	(instantiate_class_template): Call tsubst_default_arguments for
	member functions, if appropriate.
	(tsubst_default_argument): New function.
	(tsubst_decl): Use it.  Change TYPE_DECL handling to match VAR_DECLs.
	* search.c (at_function_scope_p): New function.
	* semantics.c (finish_asm_stmt): Use push_permanent_obstack.
	(finish_label_stmt): Likewise.
	(add_decl_stmt): New function.
	(begin_class_definition): Likewise.
	(finish_typeof): Likewise.
	* tree.c (copy_template_template_parm): Likewise.
	(copy_to_permanent): Likewise.
	(push_permanent_obstack): Define.
	(mark_addressable): Use it.
	* typeck.c (mark_addressable): Likewise.

From-SVN: r28709
This commit is contained in:
Mark Mitchell 1999-08-14 09:23:49 +00:00 committed by Mark Mitchell
parent 0d4255d1f6
commit 9188c36364
22 changed files with 523 additions and 322 deletions

View File

@ -1,3 +1,78 @@
1999-08-13 Mark Mitchell <mark@codesourcery.com>
* cp-tree.def (DECL_STMT): Make it smaller.
* cp-tree.h (lang_decl_flags): Move saved_tree to ...
(lang_decl): ... here. Add next.
(DECL_SAVED_TREE): Adjust accordingly.
(DECL_IMPLICIT_TYPEDEF_P): New macro.
(SET_DECL_IMPLICIT_TYPEDEF_P): Likewise.
(DECL_STMT_DECL): Likewise.
(create_implicit_typedef): New function.
(maybe_push_decl): Likewise.
(tsubst_default_argument): New function.
(at_function_scope_p): Likewise.
(add_decl_stmt): Likewise.
(push_permanent_obstack): Likewise.
* call.c (convert_default_arg): Use tsubst_default_argument.
* class.c (add_method): Use push_permanent_obstack.
(build_self_reference): Create a TEMPLATE_DECL for the
self-reference, if necessary.
* decl.c (pseudo_global_level_p): Only look at the current binding
level.
(push_binding): Use push_permanent_obstack.
(create_implicit_typedef): New function.
(pushtag): Use it.
(duplicate_decls): Use push_permanent_obstack.
(maybe_push_decl): New function.
(start_decl): Use it. Remove dead code. Use add_decl_stmt.
(start_decl_1): Remove dead code.
(cp_finish_decl): Remove DECL_STMT handling here. Don't use
pseudo_global_level_p.
(grokvardecl): Create DECL_LANG_SPECIFIC for a VAR_DECL in a
template.
(grokdeclarator): Likewise, for TYPE_DECLs. Don't use
pseudo_global_level_p.
* decl2.c (grokfield): Call push_template_decl for a TYPE_DECL in
a template.
(get_sentry): Use push_permanent_obstack.
* dump.c (dequeue_and_dump): Enable DECL_STMT.
* except.c (call_eh_info): Use push_permanent_obstack.
(build_eh_type_ref): Likewise.
(do_pop_exception): Likewise.
(expand_eh_spec): Likewise.
(alloc_eh_object): Likewise.
(expand_throw): Likewise.
* init.c (build_java_class_ref): Likewise.
* lex.c (get_time_identifier): Likewise.
(free_lang_decl_chain): Correct type.
(retrofit_lang_decl): Adjust accordingly.
(build_lang_field_decl): Likewise.
* lex.h (free_lang_decl_chain): Likewise.
* parse.y (lang_extdef): Don't use pseudo_global_level_p.
* parse.c: Regenerated.
* pt.c (tsubst_default_arguments): New function.
(retrieve_local_specialization): Likewise.
(register_local_specialization): Likewise.
(push_template_decl_real): Use DECL_IMPLICIT_TYPEDEF_P. Just use
pseudo_global_level_p to determine whether or not a template is
primary.
(lookup_template_class): Likewise. Use create_implicit_typedef.
(instantiate_class_template): Call tsubst_default_arguments for
member functions, if appropriate.
(tsubst_default_argument): New function.
(tsubst_decl): Use it. Change TYPE_DECL handling to match VAR_DECLs.
* search.c (at_function_scope_p): New function.
* semantics.c (finish_asm_stmt): Use push_permanent_obstack.
(finish_label_stmt): Likewise.
(add_decl_stmt): New function.
(begin_class_definition): Likewise.
(finish_typeof): Likewise.
* tree.c (copy_template_template_parm): Likewise.
(copy_to_permanent): Likewise.
(push_permanent_obstack): Define.
(mark_addressable): Use it.
* typeck.c (mark_addressable): Likewise.
1999-08-13 Gavin Romig-Koch <gavin@cygnus.com>
cp-tree.h (init_cplus_unsave): New.

View File

@ -3787,30 +3787,7 @@ convert_default_arg (type, arg, fn)
tree fn;
{
if (fn && DECL_TEMPLATE_INFO (fn))
{
/* This default argument came from a template. Instantiate the
default argument here, not in tsubst. In the case of
something like:
template <class T>
struct S {
static T t();
void f(T = t());
};
we must be careful to do name lookup in the scope of S<T>,
rather than in the current class. */
if (DECL_CLASS_SCOPE_P (fn))
pushclass (DECL_REAL_CONTEXT (fn), 2);
arg = tsubst_expr (arg, DECL_TI_ARGS (fn), /*complain=*/1, NULL_TREE);
if (DECL_CLASS_SCOPE_P (fn))
popclass ();
/* Make sure the default argument is reasonable. */
arg = check_default_argument (type, arg);
}
arg = tsubst_default_argument (fn, type, arg);
arg = break_out_target_exprs (arg);

View File

@ -1154,8 +1154,7 @@ void
add_method (type, fields, method)
tree type, *fields, method;
{
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
/* Setting the DECL_CONTEXT and DECL_CLASS_CONTEXT here is probably
redundant. */
@ -5379,6 +5378,9 @@ build_self_reference ()
DECL_CLASS_CONTEXT (value) = current_class_type;
DECL_ARTIFICIAL (value) = 1;
if (processing_template_decl)
value = push_template_decl (value);
saved_cas = current_access_specifier;
current_access_specifier = access_public_node;
finish_member_declaration (value);

View File

@ -217,7 +217,7 @@ DEFTREECODE (TYPEID_EXPR, "typeid_expr", 'e', 1)
DEFTREECODE (EXPR_STMT, "expr_stmt", 'e', 1)
DEFTREECODE (COMPOUND_STMT, "compound_stmt", 'e', 1)
DEFTREECODE (DECL_STMT, "decl_stmt", 'e', 3)
DEFTREECODE (DECL_STMT, "decl_stmt", 'e', 1)
DEFTREECODE (IF_STMT, "if_stmt", 'e', 3)
DEFTREECODE (FOR_STMT, "for_stmt", 'e', 4)
DEFTREECODE (WHILE_STMT, "while_stmt", 'e', 2)

View File

@ -77,6 +77,7 @@ Boston, MA 02111-1307, USA. */
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
3: DECL_IN_AGGR_P.
4: DECL_MAYBE_TEMPLATE.
5: DECL_INTERFACE_KNOWN.
@ -1192,11 +1193,8 @@ struct lang_decl_flags
tree access;
tree context;
/* In a template FUNCTION_DECL, this is DECL_SAVED_TREE. */
tree saved_tree;
union {
/* In a FUNCTION_DECL, this is DECL_TEMPLATE_INFO. */
/* In a FUNCTION_DECL or a VAR_DECL, this is DECL_TEMPLATE_INFO. */
tree template_info;
/* In a NAMESPACE_DECL, this is NAMESPACE_LEVEL. */
@ -1210,10 +1208,17 @@ struct lang_decl
tree main_decl_variant;
tree befriending_classes;
/* In a FUNCTION_DECL, this is DECL_SAVED_TREE. */
tree saved_tree;
union
{
tree sorted_fields;
struct pending_inline *pending_inline_info;
/* The lang_decls on the free_lang_decl_chain are chained together
through this pointer. */
struct lang_decl *next;
} u;
};
@ -1502,7 +1507,7 @@ struct lang_decl
/* In a template FUNCTION_DECL, the tree structure that will be
substituted into to obtain instantiations. */
#define DECL_SAVED_TREE(NODE) \
(DECL_LANG_SPECIFIC ((NODE))->decl_flags.saved_tree)
(DECL_LANG_SPECIFIC ((NODE))->saved_tree)
#define COMPOUND_STMT_NO_SCOPE(NODE) TREE_LANG_FLAG_0 (NODE)
#define NEW_EXPR_USE_GLOBAL(NODE) TREE_LANG_FLAG_0 (NODE)
@ -1984,6 +1989,18 @@ extern int flag_new_for_scope;
#define DECL_DECLARES_TYPE_P(NODE) \
(TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (NODE))
/* Nonzero if NODE is the typedef implicitly generated for a type when
the type is declared. (In C++, `struct S {};' is roughly equivalent
to `struct S {}; typedef struct S S;' in C. This macro will hold
for the typedef indicated in this example. Note that in C++, there
is a second implicit typedef for each class, in the scope of `S'
itself, so that you can `S::S'. This macro does *not* hold for
those typedefs. */
#define DECL_IMPLICIT_TYPEDEF_P(NODE) \
(TREE_CODE ((NODE)) == TYPE_DECL && DECL_LANG_FLAG_2 ((NODE)))
#define SET_DECL_IMPLICIT_TYPEDEF_P(NODE) \
(DECL_LANG_FLAG_2 ((NODE)) = 1)
/* A `primary' template is one that has its own template header. A
member function of a class template is a template, but not primary.
A member template is primary. Friend templates are primary, too. */
@ -2120,6 +2137,7 @@ extern int flag_new_for_scope;
#define ASM_OUTPUTS(NODE) TREE_OPERAND (NODE, 2)
#define ASM_INPUTS(NODE) TREE_OPERAND (NODE, 3)
#define ASM_CLOBBERS(NODE) TREE_OPERAND (NODE, 4)
#define DECL_STMT_DECL(NODE) TREE_OPERAND (NODE, 0)
/* Nonzero for an ASM_STMT if the assembly statement is volatile. */
#define ASM_VOLATILE_P(NODE) \
@ -2936,6 +2954,8 @@ extern int walk_namespaces PROTO((walk_namespaces_fn,
void *));
extern int wrapup_globals_for_namespace PROTO((tree, void *));
extern tree cp_namespace_decls PROTO((tree));
extern tree create_implicit_typedef PROTO((tree, tree));
extern tree maybe_push_decl PROTO((tree));
/* in decl2.c */
extern int check_java_method PROTO((tree));
@ -3191,7 +3211,6 @@ extern void do_type_instantiation PROTO((tree, tree));
extern tree instantiate_decl PROTO((tree));
extern tree do_poplevel PROTO((void));
extern tree get_bindings PROTO((tree, tree, tree));
/* CONT ... */
extern void add_tree PROTO((tree));
extern void begin_tree PROTO((void));
extern void end_tree PROTO((void));
@ -3210,6 +3229,7 @@ extern void maybe_check_template_type PROTO((tree));
extern tree most_specialized_instantiation PROTO((tree, tree));
extern void print_candidates PROTO((tree));
extern int instantiate_pending_templates PROTO((void));
extern tree tsubst_default_argument PROTO((tree, tree, tree));
extern int processing_specialization;
extern int processing_explicit_instantiation;
@ -3257,6 +3277,7 @@ extern void print_search_statistics PROTO((void));
extern void init_search_processing PROTO((void));
extern void reinit_search_statistics PROTO((void));
extern tree current_scope PROTO((void));
extern int at_function_scope_p PROTO((void));
extern tree lookup_conversions PROTO((tree));
extern tree binfo_for_vtable PROTO((tree));
extern int binfo_from_vbase PROTO((tree));
@ -3342,6 +3363,7 @@ extern tree finish_base_specifier PROTO((tree, tree));
extern void finish_member_declaration PROTO((tree));
extern void check_multiple_declarators PROTO((void));
extern tree finish_typeof PROTO((tree));
extern void add_decl_stmt PROTO((tree));
/* in spew.c */
extern void init_spew PROTO((void));
@ -3420,6 +3442,7 @@ extern tree mapcar PROTO((tree, tree (*) (tree)));
extern tree no_linkage_check PROTO((tree));
extern void debug_binfo PROTO((tree));
extern void push_expression_obstack PROTO((void));
extern void push_permanent_obstack PROTO((void));
extern tree build_dummy_object PROTO((tree));
extern tree maybe_dummy_object PROTO((tree, tree *));
extern int is_dummy_object PROTO((tree));

View File

@ -923,9 +923,7 @@ declare_namespace_level ()
int
pseudo_global_level_p ()
{
struct binding_level *b = innermost_nonclass_level ();
return b->pseudo_global;
return current_binding_level->pseudo_global;
}
void
@ -1018,8 +1016,7 @@ push_binding (id, decl, level)
if (!free_binding_nodes)
{
/* There are no free nodes, so we must build one here. */
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
binding = make_node (CPLUS_BINDING);
pop_obstacks ();
}
@ -2761,6 +2758,29 @@ maybe_process_template_type_declaration (type, globalize, b)
return decl;
}
/* In C++, you don't have to write `struct S' to refer to `S'; you
can just use `S'. We accomplish this by creating a TYPE_DECL as
if the user had written `typedef struct S S'. Create and return
the TYPE_DECL for TYPE. */
tree
create_implicit_typedef (name, type)
tree name;
tree type;
{
tree decl;
decl = build_decl (TYPE_DECL, name, type);
SET_DECL_ARTIFICIAL (decl);
/* There are other implicit type declarations, like the one *within*
a class that allows you to write `S::S'. We must distinguish
amongst these. */
SET_DECL_IMPLICIT_TYPEDEF_P (decl);
TYPE_NAME (type) = decl;
return decl;
}
/* Push a tag name NAME for struct/class/union/enum type TYPE.
Normally put it into the inner-most non-tag-transparent scope,
but if GLOBALIZE is true, put it in the inner-most non-class scope.
@ -2790,9 +2810,8 @@ pushtag (name, type, globalize)
{
register tree d = NULL_TREE;
int in_class = 0;
tree context;
tree context = TYPE_CONTEXT (type);
context = type ? TYPE_CONTEXT (type) : NULL_TREE;
if (! context)
{
tree cs = current_scope ();
@ -2813,16 +2832,14 @@ pushtag (name, type, globalize)
|| b->parm_flag == 2)
in_class = 1;
d = build_decl (TYPE_DECL, name, type);
if (current_lang_name == lang_name_java)
TYPE_FOR_JAVA (type) = 1;
SET_DECL_ARTIFICIAL (d);
d = create_implicit_typedef (name, type);
DECL_CONTEXT (d) = FROB_CONTEXT (context);
if (! in_class)
set_identifier_type_value_with_scope (name, type, b);
TYPE_NAME (type) = d;
DECL_CONTEXT (d) = FROB_CONTEXT (context);
d = maybe_process_template_type_declaration (type,
globalize, b);
@ -3449,10 +3466,7 @@ duplicate_decls (newdecl, olddecl)
if (oldtype)
push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
else
{
push_obstacks_nochange ();
end_temporary_allocation ();
}
push_permanent_obstack ();
/* Merge the data types specified in the two decls. */
newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
@ -3733,14 +3747,13 @@ duplicate_decls (newdecl, olddecl)
{
if (DECL_MAIN_VARIANT (olddecl) == olddecl)
{
/* Save these lang_decls that would otherwise be lost. */
extern tree free_lang_decl_chain;
tree free_lang_decl = (tree) ol;
struct lang_decl *free_lang_decl = ol;
/* Save these lang_decls that would otherwise be lost. */
if (DECL_LANG_SPECIFIC (olddecl) == ol)
abort ();
TREE_CHAIN (free_lang_decl) = free_lang_decl_chain;
free_lang_decl->u.next = free_lang_decl_chain;
free_lang_decl_chain = free_lang_decl;
}
else
@ -4310,6 +4323,35 @@ pushdecl_class_level (x)
}
}
/* Enter DECL into the symbol table, if that's appropriate. Returns
DECL, or a modified version thereof. */
tree
maybe_push_decl (decl)
tree decl;
{
tree type = TREE_TYPE (decl);
/* Add this decl to the current binding level, but not if it comes
from another scope, e.g. a static member variable. TEM may equal
DECL or it may be a previous decl of the same name. */
if ((TREE_CODE (decl) != PARM_DECL
&& DECL_CONTEXT (decl) != NULL_TREE
/* Definitions of namespace members outside their namespace are
possible. */
&& TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
|| (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
|| TREE_CODE (type) == UNKNOWN_TYPE
/* The declaration of template specializations does not affect
the functions available for overload resolution, so we do not
call pushdecl. */
|| (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_TEMPLATE_SPECIALIZATION (decl)))
return decl;
else
return pushdecl (decl);
}
#if 0
/* This function is used to push the mangled decls for nested types into
the appropriate scope. Previously pushdecl_top_level was used, but that
@ -6987,34 +7029,22 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
decl);
}
/* Add this decl to the current binding level, but not if it
comes from another scope, e.g. a static member variable.
TEM may equal DECL or it may be a previous decl of the same name. */
if ((TREE_CODE (decl) != PARM_DECL && DECL_CONTEXT (decl) != NULL_TREE
/* Definitions of namespace members outside their namespace are
possible. */
&& TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
|| (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
|| TREE_CODE (type) == LANG_TYPE
/* The declaration of template specializations does not affect
the functions available for overload resolution, so we do not
call pushdecl. */
|| (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_TEMPLATE_SPECIALIZATION (decl)))
tem = decl;
else
tem = pushdecl (decl);
/* Enter this declaration into the symbol table. */
tem = maybe_push_decl (decl);
if (processing_template_decl)
{
if (! current_function_decl)
tem = push_template_decl (tem);
else
DECL_VINDEX (tem)
= build_min_nt (DECL_STMT, copy_to_permanent (declarator),
copy_to_permanent (declspecs),
NULL_TREE);
if (at_function_scope_p ())
push_permanent_obstack ();
tem = push_template_decl (tem);
/* In a a local scope, add a representation of this declaration
to the statement tree. */
if (at_function_scope_p ())
{
add_decl_stmt (decl);
pop_obstacks ();
}
}
@ -7033,32 +7063,6 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
/* Corresponding pop_obstacks is done in `cp_finish_decl'. */
push_obstacks_nochange ();
#if 0
/* We have no way of knowing whether the initializer will need to be
evaluated at run-time or not until we've parsed it, so let's just put
it in the permanent obstack. (jason) */
if (init_written
&& ! (TREE_CODE (tem) == PARM_DECL
|| (TREE_READONLY (tem)
&& (TREE_CODE (tem) == VAR_DECL
|| TREE_CODE (tem) == FIELD_DECL))))
{
/* When parsing and digesting the initializer,
use temporary storage. Do this even if we will ignore the value. */
if (toplevel_bindings_p () && debug_temp_inits)
{
if (processing_template_decl
|| TYPE_NEEDS_CONSTRUCTING (type)
|| TREE_CODE (type) == REFERENCE_TYPE)
/* In this case, the initializer must lay down in permanent
storage, since it will be saved until `finish_file' is run. */
;
else
temporary_allocation ();
}
}
#endif
return tem;
}
@ -7130,23 +7134,6 @@ start_decl_1 (decl)
}
}
#if 0
/* We don't do this yet for GNU C++. */
/* For a local variable, define the RTL now. */
if (! toplevel_bindings_p ()
/* But not if this is a duplicate decl
and we preserved the rtl from the previous one
(which may or may not happen). */
&& DECL_RTL (tem) == NULL_RTX)
{
if (TYPE_SIZE (TREE_TYPE (tem)) != NULL_TREE)
expand_decl (tem);
else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
&& DECL_INITIAL (tem) != NULL_TREE)
expand_decl (tem);
}
#endif
if (! initialized)
DECL_INITIAL (decl) = NULL_TREE;
}
@ -7380,22 +7367,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
if (processing_template_decl)
{
if (init && DECL_INITIAL (decl))
DECL_INITIAL (decl) = init;
if (current_function_decl && ! DECL_ARTIFICIAL (decl))
{
tree stmt = DECL_VINDEX (decl);
/* If the decl is declaring a member of a local class (in a
template function), the DECL_VINDEX will either be NULL,
or it will be an actual virtual function index, not a
DECL_STMT. */
if (stmt != NULL_TREE && TREE_CODE (stmt) == DECL_STMT)
{
DECL_VINDEX (decl) = NULL_TREE;
TREE_OPERAND (stmt, 2) = copy_to_permanent (init);
add_tree (stmt);
}
}
DECL_INITIAL (decl) = copy_to_permanent (init);
goto finish_end0;
}
@ -7466,9 +7438,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
else if (TREE_CODE (type) == REFERENCE_TYPE)
{
if (TREE_STATIC (decl))
make_decl_rtl (decl, NULL_PTR,
toplevel_bindings_p ()
|| pseudo_global_level_p ());
make_decl_rtl (decl, NULL_PTR, toplevel_bindings_p ());
grok_reference_init (decl, type, init);
init = NULL_TREE;
}
@ -7678,7 +7648,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
|| TREE_CODE (decl) == RESULT_DECL)
{
/* ??? FIXME: What about nested classes? */
int toplev = toplevel_bindings_p () || pseudo_global_level_p ();
int toplev = toplevel_bindings_p ();
int was_temp
= (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)
&& allocation_temporary_p ());
@ -8647,7 +8617,17 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
else
context = NULL_TREE;
decl = build_decl (VAR_DECL, declarator, complete_type (type));
if (processing_template_decl)
{
/* If we're in a template, we need DECL_LANG_SPECIFIC so that
we can call push_template_decl. */
push_permanent_obstack ();
decl = build_lang_field_decl (VAR_DECL, declarator,
complete_type (type));
pop_obstacks ();
}
else
decl = build_decl (VAR_DECL, declarator, complete_type (type));
if (context)
set_decl_namespace (decl, context, 0);
@ -9259,8 +9239,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
We also want to avoid calling this a PARM if it is in a namespace. */
if (decl_context == NORMAL && ! namespace_bindings_p ()
&& ! pseudo_global_level_p ())
if (decl_context == NORMAL && !toplevel_bindings_p ())
{
struct binding_level *b = current_binding_level;
current_binding_level = b->level_chain;
@ -10568,15 +10547,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
since it might be used as a template parameter. */
if (type != error_mark_node)
push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
decl = build_decl (TYPE_DECL, declarator, type);
if (processing_template_decl)
decl = build_lang_field_decl (TYPE_DECL, declarator, type);
else
decl = build_decl (TYPE_DECL, declarator, type);
if (type != error_mark_node)
pop_obstacks ();
}
/* If the user declares "struct {...} foo" then `foo' will have
an anonymous name. Fill that name in now. Nothing can
refer to it, so nothing needs know about the name change.
The TYPE_NAME field was filled in by build_struct_xref. */
/* If the user declares "typedef struct {...} foo" then the
struct will have an anonymous name. Fill that name in now.
Nothing can refer to it, so nothing needs know about the name
change. */
if (type != error_mark_node
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
@ -11039,7 +11021,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
/* C++ allows static class members.
All other work for this is done by grokfield.
This VAR_DCL is built by build_lang_field_decl.
This VAR_DECL is built by build_lang_field_decl.
All other VAR_DECLs are built by build_decl. */
decl = build_lang_field_decl (VAR_DECL, declarator, type);
TREE_STATIC (decl) = 1;
@ -12913,6 +12895,31 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
if (pre_parsed_p == 2)
maybe_begin_member_template_processing (decl1);
/* Effective C++ rule 15. See also c_expand_return. */
if (warn_ecpp
&& DECL_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR]
&& TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
cp_warning ("`operator=' should return a reference to `*this'");
/* Make the init_value nonzero so pushdecl knows this is not tentative.
error_mark_node is replaced below (in poplevel) with the BLOCK. */
DECL_INITIAL (decl1) = error_mark_node;
#ifdef SET_DEFAULT_DECL_ATTRIBUTES
SET_DEFAULT_DECL_ATTRIBUTES (decl1, attrs);
#endif
/* This function exists in static storage.
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
/* We must call push_template_decl after current_class_type is set
up. (If we are processing inline definitions after exiting a
class scope, current_class_type will be NULL_TREE until set above
by push_nested_class.) */
if (processing_template_decl)
decl1 = push_template_decl (decl1);
/* We are now in the scope of the function being defined. */
current_function_decl = decl1;
@ -12955,31 +12962,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
abstract_virtuals_error (decl1, TREE_TYPE (fntype));
}
/* Effective C++ rule 15. See also c_expand_return. */
if (warn_ecpp
&& DECL_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR]
&& TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
cp_warning ("`operator=' should return a reference to `*this'");
/* Make the init_value nonzero so pushdecl knows this is not tentative.
error_mark_node is replaced below (in poplevel) with the BLOCK. */
DECL_INITIAL (decl1) = error_mark_node;
#ifdef SET_DEFAULT_DECL_ATTRIBUTES
SET_DEFAULT_DECL_ATTRIBUTES (decl1, attrs);
#endif
/* This function exists in static storage.
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
/* We must call push_template_decl after current_class_type is set
up. (If we are processing inline definitions after exiting a
class scope, current_class_type will be NULL_TREE until set above
by push_nested_class.) */
if (processing_template_decl)
decl1 = push_template_decl (decl1);
/* Record the decl so that the function name is defined.
If we already have a decl for this name, and it is a FUNCTION_DECL,
use the old decl. */

View File

@ -1644,6 +1644,9 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
DECL_ASSEMBLER_NAME (value) =
get_identifier (build_overload_name (TREE_TYPE (value), 1, 1));
if (processing_template_decl)
value = push_template_decl (value);
return value;
}
@ -2823,8 +2826,7 @@ get_sentry (base)
tree sentry = IDENTIFIER_GLOBAL_VALUE (sname);
if (! sentry)
{
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
sentry = build_decl (VAR_DECL, sname, integer_type_node);
TREE_PUBLIC (sentry) = 1;
DECL_ARTIFICIAL (sentry) = 1;

View File

@ -662,12 +662,8 @@ dequeue_and_dump (di)
case DECL_STMT:
dump_stmt (di, t);
#if 0
/* We do not yet have DECL_STMT_DECL; there are declarators and
such hanging about in DECL_STMTs. */
if (dump_children_p)
dump_child ("decl", DECL_STMT_DECL (t));
#endif
break;
case DO_STMT:

View File

@ -240,8 +240,7 @@ call_eh_info ()
/* Declare cp_eh_info * __start_cp_handler (void),
as defined in exception.cc. */
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
/* struct cp_eh_info. This must match exception.cc. Note that this
type is not pushed anywhere. */
@ -422,8 +421,7 @@ build_eh_type_type_ref (type)
/* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
if (flag_rtti)
{
@ -502,8 +500,7 @@ do_pop_exception ()
{
/* Declare void __cp_pop_exception (void *),
as defined in exception.cc. */
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
fn = build_lang_decl
(FUNCTION_DECL, fn,
build_function_type (void_type_node, tree_cons
@ -773,8 +770,7 @@ expand_end_eh_spec (raises)
fn = IDENTIFIER_GLOBAL_VALUE (fn);
else
{
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
tmp = tree_cons
(NULL_TREE, integer_type_node, tree_cons
@ -920,8 +916,7 @@ alloc_eh_object (type)
{
/* Declare __eh_alloc (size_t), as defined in exception.cc. */
tree tmp;
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
tmp = tree_cons (NULL_TREE, sizetype, void_list_node);
fn = build_lang_decl (FUNCTION_DECL, fn,
build_function_type (ptr_type_node, tmp));
@ -973,8 +968,7 @@ expand_throw (exp)
the internal type of a destructor. */
if (cleanup_type == NULL_TREE)
{
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
cleanup_type = build_pointer_type
(build_function_type
(void_type_node, tree_cons
@ -1074,8 +1068,7 @@ expand_throw (exp)
/* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
as defined in exception.cc. */
tree tmp;
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
tmp = tree_cons
(NULL_TREE, ptr_type_node, tree_cons
(NULL_TREE, ptr_type_node, tree_cons
@ -1108,8 +1101,7 @@ expand_throw (exp)
{
/* Declare void __uncatch_exception (void)
as defined in exception.cc. */
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
fn = build_lang_decl (FUNCTION_DECL, fn,
build_function_type (void_type_node,
void_list_node));

View File

@ -2141,8 +2141,7 @@ build_java_class_ref (type)
class_decl = IDENTIFIER_GLOBAL_VALUE (name);
if (class_decl == NULL_TREE)
{
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
TREE_STATIC (class_decl) = 1;
DECL_EXTERNAL (class_decl) = 1;

View File

@ -330,8 +330,7 @@ get_time_identifier (name)
time_identifier = get_identifier (buf);
if (TIME_IDENTIFIER_TIME (time_identifier) == NULL_TREE)
{
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
TIME_IDENTIFIER_TIME (time_identifier) = build_int_2 (0, 0);
TIME_IDENTIFIER_FILEINFO (time_identifier)
= build_int_2 (0, 1);
@ -4716,8 +4715,8 @@ extern int tree_node_sizes[];
#endif
/* Place to save freed lang_decls which were allocated on the
permanent_obstack. @@ Not currently used. */
tree free_lang_decl_chain;
permanent_obstack. */
struct lang_decl *free_lang_decl_chain;
tree
build_lang_decl (code, name, type)
@ -4738,8 +4737,7 @@ retrofit_lang_decl (t)
tree t;
{
struct obstack *obstack = current_obstack;
register int i = sizeof (struct lang_decl) / sizeof (int);
register int *pi;
struct lang_decl *ld;
if (! TREE_PERMANENT (t))
obstack = saveable_obstack;
@ -4749,20 +4747,18 @@ retrofit_lang_decl (t)
if (free_lang_decl_chain && obstack == &permanent_obstack)
{
pi = (int *)free_lang_decl_chain;
free_lang_decl_chain = TREE_CHAIN (free_lang_decl_chain);
ld = free_lang_decl_chain;
free_lang_decl_chain = free_lang_decl_chain->u.next;
}
else
pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
ld = ((struct lang_decl *)
obstack_alloc (obstack, sizeof (struct lang_decl)));
while (i > 0)
pi[--i] = 0;
bzero (ld, sizeof (struct lang_decl));
DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
LANG_DECL_PERMANENT ((struct lang_decl *) pi)
= obstack == &permanent_obstack;
my_friendly_assert (LANG_DECL_PERMANENT ((struct lang_decl *) pi)
== TREE_PERMANENT (t), 234);
DECL_LANG_SPECIFIC (t) = ld;
LANG_DECL_PERMANENT (ld) = obstack == &permanent_obstack;
my_friendly_assert (LANG_DECL_PERMANENT (ld) == TREE_PERMANENT (t), 234);
DECL_MAIN_VARIANT (t) = t;
if (current_lang_name == lang_name_cplusplus)
DECL_LANGUAGE (t) = lang_cplusplus;
@ -4772,21 +4768,15 @@ retrofit_lang_decl (t)
DECL_LANGUAGE (t) = lang_java;
else my_friendly_abort (64);
#if 0 /* not yet, should get fixed properly later */
if (code == TYPE_DECL)
{
tree id;
id = get_identifier (build_overload_name (type, 1, 1));
DECL_ASSEMBLER_NAME (t) = id;
}
#endif
#ifdef GATHER_STATISTICS
tree_node_counts[(int)lang_decl] += 1;
tree_node_sizes[(int)lang_decl] += sizeof (struct lang_decl);
#endif
}
/* Like build_decl, except that a new lang_decl_flags structure is
placed in DECL_LANG_SPECIFIC. */
tree
build_lang_field_decl (code, name, type)
enum tree_code code;
@ -4796,28 +4786,16 @@ build_lang_field_decl (code, name, type)
extern struct obstack *current_obstack, *saveable_obstack;
register tree t = build_decl (code, name, type);
struct obstack *obstack = current_obstack;
register int i = sizeof (struct lang_decl_flags) / sizeof (int);
register int *pi;
#if 0 /* not yet, should get fixed properly later */
if (code == TYPE_DECL)
{
tree id;
id = get_identifier (build_overload_name (type, 1, 1));
DECL_ASSEMBLER_NAME (t) = id;
}
#endif
if (! TREE_PERMANENT (t))
obstack = saveable_obstack;
else
my_friendly_assert (obstack == &permanent_obstack, 235);
pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl_flags));
while (i > 0)
pi[--i] = 0;
DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
DECL_LANG_SPECIFIC (t)
= ((struct lang_decl *)
obstack_alloc (obstack, sizeof (struct lang_decl_flags)));
bzero (DECL_LANG_SPECIFIC (t), sizeof (struct lang_decl_flags));
return t;
}

View File

@ -131,3 +131,5 @@ extern tree got_object;
extern int pending_lang_change;
extern int yylex PROTO((void));
extern struct lang_decl *free_lang_decl_chain;

View File

@ -4444,7 +4444,7 @@ case 12:
break;}
case 13:
#line 386 "parse.y"
{ if (! toplevel_bindings_p () && ! pseudo_global_level_p())
{ if (! toplevel_bindings_p ())
pop_everything (); ;
break;}
case 14:

View File

@ -383,7 +383,7 @@ asm_keyword:
lang_extdef:
{ if (pending_lang_change) do_pending_lang_change(); }
extdef
{ if (! toplevel_bindings_p () && ! pseudo_global_level_p())
{ if (! toplevel_bindings_p ())
pop_everything (); }
;

View File

@ -123,7 +123,9 @@ static tree build_template_parm_index PROTO((int, int, int, tree, tree));
static int inline_needs_template_parms PROTO((tree));
static void push_inline_template_parms_recursive PROTO((tree, int));
static tree retrieve_specialization PROTO((tree, tree));
static tree retrieve_local_specialization PROTO((tree, tree));
static tree register_specialization PROTO((tree, tree, tree));
static tree register_local_specialization PROTO((tree, tree, tree));
static int unregister_specialization PROTO((tree, tree));
static tree reduce_template_parm_level PROTO((tree, tree, int));
static tree build_template_decl PROTO((tree, tree));
@ -160,6 +162,7 @@ static int coerce_template_template_parms PROTO((tree, tree, int,
static tree determine_specialization PROTO((tree, tree, tree *, int));
static int template_args_equal PROTO((tree, tree));
static void print_template_context PROTO((int));
static void tsubst_default_arguments PROTO((tree));
/* We use TREE_VECs to hold template arguments. If there is only one
level of template arguments, then the TREE_VEC contains the
@ -756,6 +759,18 @@ retrieve_specialization (tmpl, args)
return NULL_TREE;
}
/* Like retrieve_speciailization, but for local declarations. FN is
the function in which we are looking for an instantiation. */
static tree
retrieve_local_specialization (tmpl, fn)
tree tmpl;
tree fn;
{
tree s = purpose_member (fn, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
return s ? TREE_VALUE (s) : NULL_TREE;
}
/* Returns non-zero iff DECL is a specialization of TMPL. */
int
@ -911,6 +926,22 @@ unregister_specialization (spec, tmpl)
return 0;
}
/* Like register_specialization, but for local declarations. FN is
the function in which we are registering SPEC, an instantiation of
TMPL. */
static tree
register_local_specialization (spec, tmpl, fn)
tree spec;
tree tmpl;
tree fn;
{
DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
= perm_tree_cons (fn, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
return spec;
}
/* Print the list of candidate FNS in an error message. */
void
@ -2350,7 +2381,7 @@ push_template_decl_real (decl, is_friend)
int is_partial;
/* See if this is a partial specialization. */
is_partial = (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)
is_partial = (DECL_IMPLICIT_TYPEDEF_P (decl)
&& TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
&& CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)));
@ -2368,7 +2399,7 @@ push_template_decl_real (decl, is_friend)
else
/* Otherwise, if we're currently definining some class, the DECL
is assumed to be a member of the class. */
ctx = current_class_type;
ctx = current_scope ();
if (ctx && TREE_CODE (ctx) == NAMESPACE_DECL)
ctx = NULL_TREE;
@ -2376,22 +2407,8 @@ push_template_decl_real (decl, is_friend)
if (!DECL_CONTEXT (decl))
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
/* For determining whether this is a primary template or not, we're really
interested in the lexical context, not the true context. */
if (is_friend)
info = current_class_type;
else
info = ctx;
/* See if this is a primary template. */
if (info && TREE_CODE (info) == FUNCTION_DECL)
primary = 0;
/* Note that template_class_depth returns 0 if given NULL_TREE, so
this next line works even when we are at global scope. */
else if (processing_template_decl > template_class_depth (info))
primary = 1;
else
primary = 0;
primary = pseudo_global_level_p ();
if (primary)
{
@ -2546,7 +2563,7 @@ push_template_decl_real (decl, is_friend)
info = perm_tree_cons (tmpl, args, NULL_TREE);
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
if (DECL_IMPLICIT_TYPEDEF_P (decl))
{
SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info);
if ((!ctx || TREE_CODE (ctx) != FUNCTION_DECL)
@ -3932,16 +3949,13 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
{
TYPE_CONTEXT (t) = FROB_CONTEXT (context);
/* Create a stub TYPE_DECL for it. */
type_decl = build_decl (TYPE_DECL, DECL_NAME (template), t);
SET_DECL_ARTIFICIAL (type_decl);
type_decl = create_implicit_typedef (DECL_NAME (template), t);
DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
TYPE_STUB_DECL (t) = type_decl;
DECL_SOURCE_FILE (type_decl)
= DECL_SOURCE_FILE (TYPE_STUB_DECL (template_type));
DECL_SOURCE_LINE (type_decl)
= DECL_SOURCE_LINE (TYPE_STUB_DECL (template_type));
TYPE_STUB_DECL (t) = TYPE_NAME (t) = type_decl;
}
else
type_decl = TYPE_NAME (t);
@ -5193,6 +5207,18 @@ instantiate_class_template (type)
TYPE_BEING_DEFINED (type) = 0;
repo_template_used (type);
/* Now that the class is complete, instantiate default arguments for
any member functions. We don't do this earlier because the
default arguments may reference members of the class. */
if (!PRIMARY_TEMPLATE_P (template))
for (t = TYPE_METHODS (type); t; t = TREE_CHAIN (t))
if (TREE_CODE (t) == FUNCTION_DECL
/* Implicitly generated member functions will not have tmplate
information; they are not instantiations, but instead are
created "fresh" for each instantiation. */
&& DECL_TEMPLATE_INFO (t))
tsubst_default_arguments (t);
popclass ();
pop_from_top_level ();
pop_tinst_level ();
@ -5417,6 +5443,66 @@ tsubst_aggr_type (t, args, complain, in_decl, entering_scope)
}
}
/* Substitute into the default argument ARG (a default argument for
FN), which has the indicated TYPE. */
tree
tsubst_default_argument (fn, type, arg)
tree fn;
tree type;
tree arg;
{
/* This default argument came from a template. Instantiate the
default argument here, not in tsubst. In the case of
something like:
template <class T>
struct S {
static T t();
void f(T = t());
};
we must be careful to do name lookup in the scope of S<T>,
rather than in the current class. */
if (DECL_CLASS_SCOPE_P (fn))
pushclass (DECL_REAL_CONTEXT (fn), 2);
arg = tsubst_expr (arg, DECL_TI_ARGS (fn), /*complain=*/1, NULL_TREE);
if (DECL_CLASS_SCOPE_P (fn))
popclass ();
/* Make sure the default argument is reasonable. */
arg = check_default_argument (type, arg);
return arg;
}
/* Substitute into all the default arguments for FN. */
static void
tsubst_default_arguments (fn)
tree fn;
{
tree arg;
tree tmpl_args;
tmpl_args = DECL_TI_ARGS (fn);
/* If this function is not yet instantiated, we certainly don't need
its default arguments. */
if (uses_template_parms (tmpl_args))
return;
for (arg = TYPE_ARG_TYPES (TREE_TYPE (fn));
arg;
arg = TREE_CHAIN (arg))
if (TREE_PURPOSE (arg))
TREE_PURPOSE (arg) = tsubst_default_argument (fn,
TREE_VALUE (arg),
TREE_PURPOSE (arg));
}
/* Substitute the ARGS into the T, which is a _DECL. TYPE is the
(already computed) substitution of ARGS into TREE_TYPE (T), if
appropriate. Return the result of the substitution. IN_DECL is as
@ -5804,6 +5890,22 @@ tsubst_decl (t, args, type, in_decl)
&& (IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r))
== NULL_TREE))
SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
/* We're not supposed to instantiate default arguments
until they are called, for a template. But, for a
declaration like:
template <class T> void f ()
{ extern void g(int i = T()); }
we should do the substitution when the template is
instantiated. We handle the member function case in
instantiate_class_template since the default arguments
might refer to other members of the class. */
if (!member
&& !PRIMARY_TEMPLATE_P (gen_tmpl)
&& !uses_template_parms (argvec))
tsubst_default_arguments (r);
}
/* Copy the list of befriending classes. */
@ -5877,26 +5979,56 @@ tsubst_decl (t, args, type, in_decl)
}
break;
case TYPE_DECL:
if (DECL_IMPLICIT_TYPEDEF_P (t))
{
/* For an implicit typedef, we just want the implicit
typedef for the tsubst'd type. We've already got the
tsubst'd type, as TYPE, so we just need it's associated
declaration. */
r = TYPE_NAME (type);
break;
}
else if (!DECL_LANG_SPECIFIC (t))
{
/* For a template type parameter, we don't have to do
anything special. */
r= TYPE_NAME (type);
break;
}
/* Fall through. */
case VAR_DECL:
{
tree argvec;
tree gen_tmpl;
tree spec;
tree tmpl;
tree ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
/*complain=*/1,
in_decl, /*entering_scope=*/1);
tree ctx;
/* Nobody should be tsubst'ing into non-template variables. */
my_friendly_assert (DECL_LANG_SPECIFIC (t)
&& DECL_TEMPLATE_INFO (t) != NULL_TREE, 0);
if (TYPE_P (DECL_CONTEXT (t)))
ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
/*complain=*/1,
in_decl, /*entering_scope=*/1);
else
/* Subsequent calls to pushdecl will fill this in. */
ctx = NULL_TREE;
/* Check to see if we already have this specialization. */
tmpl = DECL_TI_TEMPLATE (t);
gen_tmpl = most_general_template (tmpl);
argvec = tsubst (DECL_TI_ARGS (t), args, /*complain=*/1, in_decl);
spec = retrieve_specialization (gen_tmpl, argvec);
if (ctx)
spec = retrieve_specialization (gen_tmpl, argvec);
else
spec = retrieve_local_specialization (gen_tmpl,
current_function_decl);
if (spec)
{
r = spec;
@ -5923,26 +6055,18 @@ tsubst_decl (t, args, type, in_decl)
DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
SET_DECL_IMPLICIT_INSTANTIATION (r);
register_specialization (r, gen_tmpl, argvec);
if (ctx)
register_specialization (r, gen_tmpl, argvec);
else
register_local_specialization (r, gen_tmpl,
current_function_decl);
TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (type) == VOID_TYPE)
if (TREE_CODE (r) == VAR_DECL && TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r);
}
break;
case TYPE_DECL:
if (t == TYPE_NAME (TREE_TYPE (t)))
r = TYPE_NAME (type);
else
{
r = copy_node (t);
TREE_TYPE (r) = type;
DECL_CONTEXT (r) = current_class_type;
TREE_CHAIN (r) = NULL_TREE;
}
break;
default:
my_friendly_abort (0);
}
@ -6759,15 +6883,15 @@ tsubst_copy (t, args, complain, in_decl)
return t;
/* Unfortunately, we cannot just call lookup_name here.
Consider:
template <int I> int f() {
enum E { a = I };
struct S { void g() { E e = a; } };
};
When we instantiate f<7>::S::g(), say, lookup_name is not
clever enough to find f<7>::a. */
Consider:
template <int I> int f() {
enum E { a = I };
struct S { void g() { E e = a; } };
};
When we instantiate f<7>::S::g(), say, lookup_name is not
clever enough to find f<7>::a. */
enum_type
= tsubst_aggr_type (TREE_TYPE (t), args, complain, in_decl,
/*entering_scope=*/0);

View File

@ -622,6 +622,17 @@ current_scope ()
return current_class_type;
}
/* Returns non-zero if we are currently in a function scope. Note
that this function returns zero if we are within a local class, but
not within a member function body of the local class. */
int
at_function_scope_p ()
{
tree cs = current_scope ();
return cs && TREE_CODE (cs) == FUNCTION_DECL;
}
/* Return the scope of DECL, as appropriate when doing name-lookup. */
static tree
@ -1212,9 +1223,9 @@ lookup_field_queue_p (binfo, data)
return binfo;
}
/* Within the scope of a template class, you can refer to the
particular to the current specialization with the name of the
template itself. For example:
/* Within the scope of a template class, you can refer to the to the
current specialization with the name of the template itself. For
example:
template <typename T> struct S { S* sp; }

View File

@ -780,12 +780,9 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
if (TREE_CHAIN (string))
{
if (processing_template_decl)
{
/* We need to build the combined string on the permanent
obstack so that we can use it during instantiations. */
push_obstacks_nochange ();
end_temporary_allocation ();
}
/* We need to build the combined string on the permanent
obstack so that we can use it during instantiations. */
push_permanent_obstack ();
string = combine_strings (string);
@ -842,8 +839,7 @@ finish_label_stmt (name)
if (processing_template_decl)
{
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
decl = build_decl (LABEL_DECL, name, void_type_node);
pop_obstacks ();
DECL_SOURCE_LINE (decl) = lineno;
@ -858,6 +854,21 @@ finish_label_stmt (name)
}
}
/* Create a declaration statement for the declaration given by the
DECL. */
void
add_decl_stmt (decl)
tree decl;
{
tree decl_stmt;
/* We need the type to last until instantiation time. */
TREE_TYPE (decl) = copy_to_permanent (TREE_TYPE (decl));
decl_stmt = build_min_nt (DECL_STMT, decl);
add_tree (decl_stmt);
}
/* Finish a parenthesized expression EXPR. */
tree
@ -1302,9 +1313,8 @@ tree
begin_class_definition (t)
tree t;
{
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
if (t == error_mark_node
|| ! IS_AGGR_TYPE (t))
{
@ -1726,12 +1736,9 @@ finish_typeof (expr)
{
tree t;
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
t = make_lang_type (TYPEOF_TYPE);
TYPE_FIELDS (t) = expr;
pop_obstacks ();
return t;

View File

@ -442,7 +442,7 @@ build_cplus_array_type_1 (elt_type, index_type)
push_obstacks_nochange ();
/* We need a new one. If both ELT_TYPE and INDEX_TYPE are permanent,
/* If both ELT_TYPE and INDEX_TYPE are permanent,
make this permanent too. */
if (TREE_PERMANENT (elt_type)
&& (index_type == 0 || TREE_PERMANENT (index_type)))
@ -1533,8 +1533,7 @@ copy_template_template_parm (t)
tree t2;
/* Make sure these end up on the permanent_obstack. */
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM);
template = copy_node (template);
@ -2086,11 +2085,8 @@ copy_to_permanent (t)
if (t == NULL_TREE || TREE_PERMANENT (t))
return t;
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
t = mapcar (t, perm_manip);
pop_obstacks ();
return t;
@ -2622,6 +2618,17 @@ push_expression_obstack ()
current_obstack = expression_obstack;
}
/* Begin allocating on the permanent obstack. When you're done
allocating there, call pop_obstacks to return to the previous set
of obstacks. */
void
push_permanent_obstack ()
{
push_obstacks_nochange ();
end_temporary_allocation ();
}
/* The type of ARG when used as an lvalue. */
tree

View File

@ -5090,8 +5090,7 @@ mark_addressable (exp)
{
/* We thought this would make a good constant variable,
but we were wrong. */
push_obstacks_nochange ();
end_temporary_allocation ();
push_permanent_obstack ();
TREE_ASM_WRITTEN (x) = 0;
DECL_RTL (x) = 0;

View File

@ -6,5 +6,5 @@ struct A { // ERROR - too many template parameter lists
public:
A() {}
A(const A<T>& b) {} // ERROR - invalid use of template
A(const A<T>& b) {}
};

View File

@ -0,0 +1,12 @@
// Build don't link:
// Origin: Mark Mitchell <mark@codesourcery.com>
template <class T = int>
struct S
{
void f ()
{
struct U {
};
}
};

View File

@ -0,0 +1,13 @@
// Build don't link:
// Origin: Mark Mitchell <mark@codesourcery.com>
template <class T>
void f (int i)
{
struct S { void g (int j = i) {} }; // ERROR - default argument uses local
S s; // ERROR - instantiated here
}
template void f<double>(int); // ERROR - instantiated here