From 9188c36364c9a8bdd993a5d911b875ce124bb04d Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Sat, 14 Aug 1999 09:23:49 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 75 ++++++ gcc/cp/call.c | 25 +- gcc/cp/class.c | 6 +- gcc/cp/cp-tree.def | 2 +- gcc/cp/cp-tree.h | 35 ++- gcc/cp/decl.c | 266 +++++++++---------- gcc/cp/decl2.c | 6 +- gcc/cp/dump.c | 4 - gcc/cp/except.c | 24 +- gcc/cp/init.c | 3 +- gcc/cp/lex.c | 60 ++--- gcc/cp/lex.h | 2 + gcc/cp/parse.c | 2 +- gcc/cp/parse.y | 2 +- gcc/cp/pt.c | 228 ++++++++++++---- gcc/cp/search.c | 17 +- gcc/cp/semantics.c | 37 +-- gcc/cp/tree.c | 21 +- gcc/cp/typeck.c | 3 +- gcc/testsuite/g++.old-deja/g++.pt/crash15.C | 2 +- gcc/testsuite/g++.old-deja/g++.pt/defarg12.C | 12 + gcc/testsuite/g++.old-deja/g++.pt/defarg13.C | 13 + 22 files changed, 523 insertions(+), 322 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/defarg12.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/defarg13.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 37829332b358..4b882a6c730c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,78 @@ +1999-08-13 Mark Mitchell + + * 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 cp-tree.h (init_cplus_unsave): New. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index a4ed95b7fa85..fda38de4d9ac 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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 - struct S { - static T t(); - void f(T = t()); - }; - - we must be careful to do name lookup in the scope of S, - 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); diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 47f22a34b9b0..3df139052242 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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); diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 70801fc9563c..fecbbe5be58c 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -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) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 2e58406a77e0..410dc7a8681d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index b6e66a954ec4..8c960202514a 100644 --- a/gcc/cp/decl.c +++ b/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. */ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 217b7831d86b..3cebe815640f 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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; diff --git a/gcc/cp/dump.c b/gcc/cp/dump.c index 0ae83efce1e2..e04655264a8c 100644 --- a/gcc/cp/dump.c +++ b/gcc/cp/dump.c @@ -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: diff --git a/gcc/cp/except.c b/gcc/cp/except.c index dd708556e63e..0ef6e82795bc 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -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)); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 98b67eecf5e6..69758a62a459 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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; diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index a92a4f375a66..f36da5319919 100644 --- a/gcc/cp/lex.c +++ b/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; } diff --git a/gcc/cp/lex.h b/gcc/cp/lex.h index 8f997ad189fe..337e55aa7ca4 100644 --- a/gcc/cp/lex.h +++ b/gcc/cp/lex.h @@ -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; diff --git a/gcc/cp/parse.c b/gcc/cp/parse.c index 809a7eb3e74b..b2b85c94a624 100644 --- a/gcc/cp/parse.c +++ b/gcc/cp/parse.c @@ -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: diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 94acf0a78bb0..5698789e35b3 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -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 (); } ; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6e491e10aec8..e00afbd2c667 100644 --- a/gcc/cp/pt.c +++ b/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 + struct S { + static T t(); + void f(T = t()); + }; + + we must be careful to do name lookup in the scope of S, + 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 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 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 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); diff --git a/gcc/cp/search.c b/gcc/cp/search.c index f68edd677133..300d7107cf4a 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -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 struct S { S* sp; } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index f464c3342c80..0711da3df608 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index a6bbbe00afd8..7a35b47a0b10 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 37239365a8cb..044f48fdaa83 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash15.C b/gcc/testsuite/g++.old-deja/g++.pt/crash15.C index 75b10544ac9d..d0af82f9f3dd 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/crash15.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/crash15.C @@ -6,5 +6,5 @@ struct A { // ERROR - too many template parameter lists public: A() {} - A(const A& b) {} // ERROR - invalid use of template + A(const A& b) {} }; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/defarg12.C b/gcc/testsuite/g++.old-deja/g++.pt/defarg12.C new file mode 100644 index 000000000000..3c53e8e1fb64 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/defarg12.C @@ -0,0 +1,12 @@ +// Build don't link: +// Origin: Mark Mitchell + +template +struct S +{ + void f () + { + struct U { + }; + } +}; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/defarg13.C b/gcc/testsuite/g++.old-deja/g++.pt/defarg13.C new file mode 100644 index 000000000000..1082bf567e0a --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/defarg13.C @@ -0,0 +1,13 @@ +// Build don't link: +// Origin: Mark Mitchell + +template +void f (int i) +{ + struct S { void g (int j = i) {} }; // ERROR - default argument uses local + + S s; // ERROR - instantiated here +} + +template void f(int); // ERROR - instantiated here +