mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-09 17:11:20 +08:00
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:
parent
0d4255d1f6
commit
9188c36364
@ -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.
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
|
266
gcc/cp/decl.c
266
gcc/cp/decl.c
@ -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. */
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
60
gcc/cp/lex.c
60
gcc/cp/lex.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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 (); }
|
||||
;
|
||||
|
||||
|
228
gcc/cp/pt.c
228
gcc/cp/pt.c
@ -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);
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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) {}
|
||||
};
|
||||
|
12
gcc/testsuite/g++.old-deja/g++.pt/defarg12.C
Normal file
12
gcc/testsuite/g++.old-deja/g++.pt/defarg12.C
Normal 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 {
|
||||
};
|
||||
}
|
||||
};
|
13
gcc/testsuite/g++.old-deja/g++.pt/defarg13.C
Normal file
13
gcc/testsuite/g++.old-deja/g++.pt/defarg13.C
Normal 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user