From 36a117a5b33194265633e62df5968d2385baf8be Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Tue, 28 Jul 1998 01:03:16 +0000 Subject: [PATCH] cp-tree.h (TI_USES_TEMPLATE_PARMS): Remove. * cp-tree.h (TI_USES_TEMPLATE_PARMS): Remove. (build_template_decl_overload): Remove. (set_mangled_name_for_decl): New function. (innermost_args): Remove is_spec parameter. (most_specialized, most_specialized_class): Remove declarations. (lookup_template_class): Add entering_scope parameter. (maybe_process_partial_specialization): New function. (finish_template_decl): Likewise. (finish_template_type): Likewise. * class.c (finish_struct): Clean up processing of member template specializations. * decl.c (pushtag): Fix formatting. (lookup_tag): Improve handling of pseudo-global levels. (make_typename_type): Adjust call to lookup_template_class. (shadow_tag): Use maybe_process_partial_specialization. (xref_tag): Improve handling of member friends. (start_function): Call push_nested_class before push_template_decl. Don't call push_template_decl for specializations. * decl2.c (grok_x_components): Don't call xref_tag for template instantiations. Handle UNION_TYPEs like RECORD_TYPEs. (grokclassfn): Use set_mangled_name_for_decl. (arg_assoc_class): Adjust call to innermost_args. (mark_used): Don't call instantiate_decl for a TEMPLATE_DECL. * error.c (dump_function_name): Improve printing of template function names. * friend.c (is_friend): Don't compare types of decls to determine friendship, unless flag_guiding_decls. (make_friend_class): Partial specializations cannot be friends. (do_friend): Use set_mangled_name_for_decl. Call push_template_decl_real instead of push_template_decl. * method.c (build_decl_overload_real): Remove prototype. Give it external linkage. (build_overload_identififer): Adjust call to innermost_args. (build_template_decl_overload): Remove. (set_mangled_name_for_decl): New function. * parse.y (.finish_template_type): New non-terminal. (template_def): Use finish_template_decl. Use template_extdef instead of extdef. (template_extdef, template_datadef): New non-terminals, containing only those rules for things which can be templates. (datadef): Tidy. (template_type, self_template_type): Use .finish_template_type. (named_class_head): Use maybe_process_partial_specialization. * pt.c (mangle_class_name_for_template): Remove context parameter. (get_class_bindings): Remove outer_args parameter. (complete_template_args): Remove. (add_outermost_template_args): New function. (register_specialization): Return the specialization. (unregister_specialization): New function. (tsubst_template_parms): Likewise. (most_specialized, most_specialized_class): Prototype here as static. (original_template): Rename to most_general_template. (tsubst_template_parms): New function. (set_mangled_name_for_template_decl): Likewise. (TMPL_ARGS_DEPTH): New macro. (TMPL_ARGS_HAVE_MULTIPLE_LEVELS): Adjust. (TMPL_ARGS_LEVEL): New macro. (SET_TMPL_ARGS_LEVEL): Likewise. (TMPL_ARG): Likewise. (SET_TMPL_ARG): Likewise. (TMPL_ARGS_DEPTH): Likewise. (finish_member_template_decl): Use finish_template_decl. (maybe_process_partial_specialization): New function, split out from tsubst. (inline_needs_template_parms): Use TMPL_PARMS_DEPTH. (maybe_begin_member_template_processing): Use new macros. (is_member_template): Likewise. (is_member_template_class): Likewise. (add_to_template_args): Likewise. Deal with multiple levels of args. (maybe_process_partial_specialization): New function. (retrieve_specialization): Add consistency check. (determine_specialization): Return full argument list. (check_explicit_specialization): Tweak friend handling. Use full argument lists. Simplify. (current_template_args): Use new macros. (push_template_decl_real): Change ill-named mainargs to specargs. Check that a partial specialization actually specializes at least one parameter. Improve friend handling. Modify for full template arguments. (classtype_mangled_name): Don't mangle the names of specializations. (lookup_template_class): Add entering_scope parameter. Use it to avoid finding a template type when an instantiation is required. Simplify. Use full template arguments. (tsubst_friend_function): Use unregister_specialization. Use new macros. Use full template arguments. (tsubst_friend_class): Substitute, using tsubst_template_parms, into the template parameters before passing them to redeclare_class_template. (instantiate_class_template): Simplify. Use full template arguments. Adjust calls to get_class_bindings. Use SET_IDENTIFIER_TYPE_VALUE where needed. Improve friend handling. (innermost_args): Use new macros. (tsubst_aggr_type): New function, split out from tsubst. (tsubst): Use tsubst_aggr_type, tsubst_template_parms, new calling conventions for lookup_tmeplate_class. Refine handling of partial instantiations. Remove calls to complete_template_args. Simplify. Add consistency checks. Use set_mangled_name_for_decl and set_mangled_name_for_template_decl. (tsubst_copy): Use tsubst_aggr_type. (instantiate_template): Use full template arguments. (more_specialized): Improve formatting. (more_specialized_class): Adjust calls to get_class_bindings. (get_bindings_real): Don't call complete_template_args. (most_specialized): Don't overwrite input; create a new list. (most_specialized_class): Use most_general_template. (regenerate_decl_from_template): Use unregister_specialization. Use full template arguments. (instantiate_decl): Use full template arguments. (set_mangled_name_for_template_decl): New function. * semantics.c (begin_class_definition): Use maybe_process_partial_specialization. (finish_member_class_template): New function. (finish_template_decl): Likewise. (finish_template_type): Likewise. (typeck.c): Don't crash after issuing a compiler_error. * Makefile.in (CONFLICTS): Adjust; we removed a s/r conflict. From-SVN: r21433 --- gcc/cp/ChangeLog | 123 + gcc/cp/Makefile.in | 2 +- gcc/cp/class.c | 44 +- gcc/cp/cp-tree.h | 115 +- gcc/cp/decl.c | 185 +- gcc/cp/decl2.c | 76 +- gcc/cp/error.c | 124 +- gcc/cp/friend.c | 73 +- gcc/cp/method.c | 53 +- gcc/cp/parse.y | 97 +- gcc/cp/pt.c | 2121 ++++++++++------- gcc/cp/semantics.c | 56 +- gcc/cp/typeck.c | 5 +- .../g++.old-deja/g++.brendan/crash56.C | 6 +- .../g++.old-deja/g++.brendan/crash8.C | 4 +- gcc/testsuite/g++.old-deja/g++.pt/crash11.C | 13 + gcc/testsuite/g++.old-deja/g++.pt/crash13.C | 6 + gcc/testsuite/g++.old-deja/g++.pt/crash14.C | 5 + gcc/testsuite/g++.old-deja/g++.pt/crash8.C | 34 + gcc/testsuite/g++.old-deja/g++.pt/friend21.C | 2 +- gcc/testsuite/g++.old-deja/g++.pt/friend22.C | 10 + gcc/testsuite/g++.old-deja/g++.pt/friend23.C | 10 + gcc/testsuite/g++.old-deja/g++.pt/friend24.C | 18 + gcc/testsuite/g++.old-deja/g++.pt/friend25.C | 15 + gcc/testsuite/g++.old-deja/g++.pt/friend26.C | 6 + gcc/testsuite/g++.old-deja/g++.pt/friend27.C | 7 + .../g++.old-deja/g++.pt/memclass13.C | 16 + .../g++.old-deja/g++.pt/memclass14.C | 15 + .../g++.old-deja/g++.pt/memclass15.C | 27 + gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C | 25 + gcc/testsuite/g++.old-deja/g++.pt/ttp52.C | 4 +- gcc/testsuite/g++.old-deja/g++.pt/typename3.C | 1 + gcc/testsuite/g++.old-deja/g++.pt/typename4.C | 1 + gcc/testsuite/g++.old-deja/g++.pt/typename5.C | 1 + gcc/testsuite/g++.old-deja/g++.pt/typename6.C | 1 + .../g++.old-deja/g++.robertl/eb125.C | 2 +- gcc/testsuite/g++.old-deja/g++.robertl/eb49.C | 2 +- 37 files changed, 2061 insertions(+), 1244 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/crash11.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/crash13.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/crash14.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/crash8.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/friend22.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/friend23.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/friend24.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/friend25.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/friend26.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/friend27.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/memclass13.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/memclass14.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/memclass15.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 72cbecd8526..52df5d573d2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,126 @@ +1998-07-27 Mark Mitchell + + * cp-tree.h (TI_USES_TEMPLATE_PARMS): Remove. + (build_template_decl_overload): Remove. + (set_mangled_name_for_decl): New function. + (innermost_args): Remove is_spec parameter. + (most_specialized, most_specialized_class): Remove declarations. + (lookup_template_class): Add entering_scope parameter. + (maybe_process_partial_specialization): New function. + (finish_template_decl): Likewise. + (finish_template_type): Likewise. + * class.c (finish_struct): Clean up processing of member template + specializations. + * decl.c (pushtag): Fix formatting. + (lookup_tag): Improve handling of pseudo-global levels. + (make_typename_type): Adjust call to lookup_template_class. + (shadow_tag): Use maybe_process_partial_specialization. + (xref_tag): Improve handling of member friends. + (start_function): Call push_nested_class before + push_template_decl. Don't call push_template_decl for + specializations. + * decl2.c (grok_x_components): Don't call xref_tag for + template instantiations. Handle UNION_TYPEs like RECORD_TYPEs. + (grokclassfn): Use set_mangled_name_for_decl. + (arg_assoc_class): Adjust call to innermost_args. + (mark_used): Don't call instantiate_decl for a TEMPLATE_DECL. + * error.c (dump_function_name): Improve printing of template + function names. + * friend.c (is_friend): Don't compare types of decls to determine + friendship, unless flag_guiding_decls. + (make_friend_class): Partial specializations cannot be friends. + (do_friend): Use set_mangled_name_for_decl. Call + push_template_decl_real instead of push_template_decl. + * method.c (build_decl_overload_real): Remove prototype. Give it + external linkage. + (build_overload_identififer): Adjust call to innermost_args. + (build_template_decl_overload): Remove. + (set_mangled_name_for_decl): New function. + * parse.y (.finish_template_type): New non-terminal. + (template_def): Use finish_template_decl. Use template_extdef + instead of extdef. + (template_extdef, template_datadef): New non-terminals, containing + only those rules for things which can be templates. + (datadef): Tidy. + (template_type, self_template_type): Use .finish_template_type. + (named_class_head): Use maybe_process_partial_specialization. + * pt.c (mangle_class_name_for_template): Remove context parameter. + (get_class_bindings): Remove outer_args parameter. + (complete_template_args): Remove. + (add_outermost_template_args): New function. + (register_specialization): Return the specialization. + (unregister_specialization): New function. + (tsubst_template_parms): Likewise. + (most_specialized, most_specialized_class): Prototype here as + static. + (original_template): Rename to most_general_template. + (tsubst_template_parms): New function. + (set_mangled_name_for_template_decl): Likewise. + (TMPL_ARGS_DEPTH): New macro. + (TMPL_ARGS_HAVE_MULTIPLE_LEVELS): Adjust. + (TMPL_ARGS_LEVEL): New macro. + (SET_TMPL_ARGS_LEVEL): Likewise. + (TMPL_ARG): Likewise. + (SET_TMPL_ARG): Likewise. + (TMPL_ARGS_DEPTH): Likewise. + (finish_member_template_decl): Use finish_template_decl. + (maybe_process_partial_specialization): New function, split out + from tsubst. + (inline_needs_template_parms): Use TMPL_PARMS_DEPTH. + (maybe_begin_member_template_processing): Use new macros. + (is_member_template): Likewise. + (is_member_template_class): Likewise. + (add_to_template_args): Likewise. Deal with multiple levels of + args. + (maybe_process_partial_specialization): New function. + (retrieve_specialization): Add consistency check. + (determine_specialization): Return full argument list. + (check_explicit_specialization): Tweak friend handling. Use full + argument lists. Simplify. + (current_template_args): Use new macros. + (push_template_decl_real): Change ill-named mainargs to specargs. + Check that a partial specialization actually specializes at least + one parameter. Improve friend handling. Modify for full + template arguments. + (classtype_mangled_name): Don't mangle the names of + specializations. + (lookup_template_class): Add entering_scope parameter. Use it to + avoid finding a template type when an instantiation is required. + Simplify. Use full template arguments. + (tsubst_friend_function): Use unregister_specialization. Use new + macros. Use full template arguments. + (tsubst_friend_class): Substitute, using tsubst_template_parms, + into the template parameters before passing them to + redeclare_class_template. + (instantiate_class_template): Simplify. Use full template + arguments. Adjust calls to get_class_bindings. Use + SET_IDENTIFIER_TYPE_VALUE where needed. Improve friend handling. + (innermost_args): Use new macros. + (tsubst_aggr_type): New function, split out from tsubst. + (tsubst): Use tsubst_aggr_type, tsubst_template_parms, new calling + conventions for lookup_tmeplate_class. Refine handling of partial + instantiations. Remove calls to complete_template_args. + Simplify. Add consistency checks. Use set_mangled_name_for_decl + and set_mangled_name_for_template_decl. + (tsubst_copy): Use tsubst_aggr_type. + (instantiate_template): Use full template arguments. + (more_specialized): Improve formatting. + (more_specialized_class): Adjust calls to get_class_bindings. + (get_bindings_real): Don't call complete_template_args. + (most_specialized): Don't overwrite input; create a new list. + (most_specialized_class): Use most_general_template. + (regenerate_decl_from_template): Use unregister_specialization. + Use full template arguments. + (instantiate_decl): Use full template arguments. + (set_mangled_name_for_template_decl): New function. + * semantics.c (begin_class_definition): Use + maybe_process_partial_specialization. + (finish_member_class_template): New function. + (finish_template_decl): Likewise. + (finish_template_type): Likewise. + (typeck.c): Don't crash after issuing a compiler_error. + * Makefile.in (CONFLICTS): Adjust; we removed a s/r conflict. + 1998-07-27 Jason Merrill * typeck2.c (build_functional_cast): Handle default-initialization. diff --git a/gcc/cp/Makefile.in b/gcc/cp/Makefile.in index 523bbe0eb3d..085fe3c5c86 100644 --- a/gcc/cp/Makefile.in +++ b/gcc/cp/Makefile.in @@ -215,7 +215,7 @@ parse.o : $(PARSE_C) $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h \ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \ `echo $(PARSE_C) | sed 's,^\./,,'` -CONFLICTS = expect 26 shift/reduce conflicts and 42 reduce/reduce conflicts. +CONFLICTS = expect 25 shift/reduce conflicts and 42 reduce/reduce conflicts. $(PARSE_H) : $(PARSE_C) $(PARSE_C) : $(srcdir)/parse.y @echo $(CONFLICTS) diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 714aad64225..098f6c3c717 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -4458,49 +4458,21 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) /* Now, figure out which member templates we're specializing. */ for (x = specializations; x != NULL_TREE; x = TREE_CHAIN (x)) { - tree spec_args; - tree fn; int pending_specialization; - if (uses_template_parms (t)) - /* If t is a template class, and x is a specialization, then x - is itself really a template. Due to the vagaries of the - parser, however, we will have a handle to a function - declaration, rather than the template declaration, at this - point. */ - { - my_friendly_assert (DECL_TEMPLATE_INFO (x) != NULL_TREE, 0); - my_friendly_assert (DECL_TI_TEMPLATE (x) != NULL_TREE, 0); - fn = DECL_TI_TEMPLATE (x); - } - else - fn = x; - - /* We want the specialization arguments, which will be the - innermost ones. */ - if (DECL_TI_ARGS (fn) && TREE_CODE (DECL_TI_ARGS (fn)) == TREE_VEC) - spec_args - = TREE_VEC_ELT (DECL_TI_ARGS (fn), 0); - else - spec_args = DECL_TI_ARGS (fn); - pending_specialization - = TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (fn)); + = TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (x)); check_explicit_specialization - (lookup_template_function (DECL_NAME (fn), spec_args), - fn, 0, 1 | (8 * pending_specialization)); - TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (fn)) = 0; + (lookup_template_function (DECL_NAME (x), DECL_TI_ARGS (x)), + x, 0, 1 | (8 * pending_specialization)); + TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (x)) = 0; /* Now, the assembler name will be correct for fn, so we make its RTL. */ - DECL_RTL (fn) = 0; - make_decl_rtl (fn, NULL_PTR, 1); - - if (x != fn) - { - DECL_RTL (x) = 0; - make_decl_rtl (x, NULL_PTR, 1); - } + DECL_RTL (x) = 0; + make_decl_rtl (x, NULL_PTR, 1); + DECL_RTL (DECL_TI_TEMPLATE (x)) = 0; + make_decl_rtl (DECL_TI_TEMPLATE (x), NULL_PTR, 1); } if (current_class_type) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 7572921cb5f..be97c1b1ca0 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -27,7 +27,6 @@ Boston, MA 02111-1307, USA. */ /* Usage of TREE_LANG_FLAG_?: 0: TREE_NONLOCAL_FLAG (in TREE_LIST or _TYPE). BINFO_MARKED (BINFO nodes). - TI_USES_TEMPLATE_PARMS. COMPOUND_STMT_NO_SCOPE (in COMPOUND_STMT). NEW_EXPR_USE_GLOBAL (in NEW_EXPR). DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR). @@ -1250,13 +1249,35 @@ struct lang_decl #define TI_TEMPLATE(NODE) (TREE_PURPOSE (NODE)) #define TI_ARGS(NODE) (TREE_VALUE (NODE)) #define TI_SPEC_INFO(NODE) (TREE_CHAIN (NODE)) -#define TI_USES_TEMPLATE_PARMS(NODE) TREE_LANG_FLAG_0 (NODE) #define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE) /* TI_PENDING_SPECIALIZATION_FLAG on a template-info node indicates that the template is a specialization of a member template, but that we don't yet know which one. */ #define TI_PENDING_SPECIALIZATION_FLAG(NODE) TREE_LANG_FLAG_1 (NODE) +/* The TEMPLATE_DECL instantiated or specialized by NODE. This + TEMPLATE_DECL will be the immediate parent, not the most general + template. For example, in: + + template struct S { template void f(U); } + + the FUNCTION_DECL for S::f will have, as its + DECL_TI_TEMPLATE, `template S::f'. + + As a special case, for a member friend template of a template + class, this value will not be a TEMPLATE_DECL, but rather a + LOOKUP_EXPR indicating the name of the template and any explicit + template arguments provided. For example, in: + + template struct S { friend void f(int, double); } + + the DECL_TI_TEMPLATE will be a LOOKUP_EXPR for `f' and the + DECL_TI_ARGS will be {int}. */ #define DECL_TI_TEMPLATE(NODE) TI_TEMPLATE (DECL_TEMPLATE_INFO (NODE)) +/* The template arguments used to obtain this decl from the most + general form of DECL_TI_TEMPLATE. For the example given for + DECL_TI_TEMPLATE, the DECL_TI_ARGS will be {int, double}. These + are always the full set of arguments required to instantiate this + declaration from the most general template specialized here. */ #define DECL_TI_ARGS(NODE) TI_ARGS (DECL_TEMPLATE_INFO (NODE)) #define CLASSTYPE_TI_TEMPLATE(NODE) TI_TEMPLATE (CLASSTYPE_TEMPLATE_INFO (NODE)) #define CLASSTYPE_TI_ARGS(NODE) TI_ARGS (CLASSTYPE_TEMPLATE_INFO (NODE)) @@ -1528,25 +1549,80 @@ extern int flag_new_for_scope; /* Accessor macros for C++ template decl nodes. */ /* The DECL_TEMPLATE_PARMS are a list. The TREE_PURPOSE of each node - indicates the level of the template parameters, with 1 being the - outermost set of template parameters. The TREE_VALUE is a vector, - whose elements are the template parameters at each level. Each - element in the vector is a TREE_LIST, whose TREE_VALUE is a - PARM_DECL (if the parameter is a non-type parameter), or a - TYPE_DECL (if the parameter is a type parameter). The TREE_PURPOSE - is the default value, if any. The TEMPLATE_PARM_INDEX for the - parameter is avilable as the DECL_INITIAL (for a PARM_DECL) or as - the TREE_TYPE (for a TYPE_DECL). */ + is a INT_CST whose TREE_INT_CST_HIGH indicates the level of the + template parameters, with 1 being the outermost set of template + parameters. The TREE_VALUE is a vector, whose elements are the + template parameters at each level. Each element in the vector is a + TREE_LIST, whose TREE_VALUE is a PARM_DECL (if the parameter is a + non-type parameter), or a TYPE_DECL (if the parameter is a type + parameter). The TREE_PURPOSE is the default value, if any. The + TEMPLATE_PARM_INDEX for the parameter is avilable as the + DECL_INITIAL (for a PARM_DECL) or as the TREE_TYPE (for a + TYPE_DECL). */ #define DECL_TEMPLATE_PARMS(NODE) DECL_ARGUMENTS(NODE) #define DECL_INNERMOST_TEMPLATE_PARMS(NODE) \ INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (NODE)) #define DECL_NTPARMS(NODE) \ TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (NODE)) -/* For class templates. */ -#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE(NODE) /* For function, method, class-data templates. */ #define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE) +/* For a static member variable template, the + DECL_TEMPLATE_INSTANTIATIONS list contains the explicitly and + implicitly generated instantiations of the variable. There are no + partial instantiations of static member variables, so all of these + will be full instantiations. + + For a class template the DECL_TEMPLATE_INSTANTIATIONS lists holds + all instantiations and specializations of the class type, including + partial instantiations and partial specializations. + + In both cases, the TREE_PURPOSE of each node contains the arguments + used; the TREE_VALUE contains the generated variable. The template + arguments are always complete. For example, given: + + template struct S1 { + template struct S2 {}; + template struct S2 {}; + }; + + the record for the partial specialization will contain, as its + argument list, { {T}, {U*} }, and will be on the + DECL_TEMPLATE_INSTANTIATIONS list for `template template + struct S1::S2'. + + This list is not used for function templates. */ #define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE) +/* For a function template, the DECL_TEMPLATE_SPECIALIZATIONS lists + contains all instantiations and specializations of the function, + including partial instantiations. For a partial instantiation + which is a specialization, this list holds only full + specializations of the template that are instantiations of the + partial instantiation. For example, given: + + template struct S { + template void f(U); + template <> void f(T); + }; + + the `S::f(int)' function will appear on the + DECL_TEMPLATE_SPECIALIZATIONS list for both `template + template void S::f(U)' and `template void + S::f(T)'. In the latter case, however, it will have only the + innermost set of arguments (T, in this case). The DECL_TI_TEMPLATE + for the function declaration will point at the specialization, not + the fully general template. + + For a class template, this list contains the partial + specializations of this template. (Full specializations are not + recorded on this list.) The TREE_PURPOSE holds the innermost + arguments used in the partial specialization (e.g., for `template + struct S' this will be `T*'.) The TREE_VALUE + holds the innermost template parameters for the specialization + (e.g., `T' in the example above.) The TREE_TYPE is the _TYPE node + for the partial specialization. + + This list is not used for static variable templates. */ +#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE(NODE) #define DECL_TEMPLATE_INJECT(NODE) DECL_INITIAL(NODE) /* Nonzero for TEMPLATE_DECL nodes that represents template template @@ -2649,7 +2725,9 @@ extern void do_inline_function_hair PROTO((tree, tree)); extern char *build_overload_name PROTO((tree, int, int)); extern tree build_static_name PROTO((tree, tree)); extern tree build_decl_overload PROTO((tree, tree, int)); -extern tree build_template_decl_overload PROTO((tree, tree, tree, tree, tree, int)); +extern tree build_decl_overload_real PROTO((tree, tree, tree, tree, + tree, int)); +extern tree set_mangled_name_for_decl PROTO((tree)); extern tree build_typename_overload PROTO((tree)); extern tree build_overload_with_type PROTO((tree, tree)); extern tree build_destructor_name PROTO((tree)); @@ -2661,7 +2739,7 @@ extern void synthesize_method PROTO((tree)); extern tree get_id_2 PROTO((char *, tree)); /* in pt.c */ -extern tree innermost_args PROTO ((tree, int)); +extern tree innermost_args PROTO ((tree)); extern tree tsubst PROTO ((tree, tree, tree)); extern tree tsubst_expr PROTO ((tree, tree, tree)); extern tree tsubst_copy PROTO ((tree, tree, tree)); @@ -2684,7 +2762,7 @@ extern tree current_template_args PROTO((void)); extern tree push_template_decl PROTO((tree)); extern tree push_template_decl_real PROTO((tree, int)); extern void redeclare_class_template PROTO((tree, tree)); -extern tree lookup_template_class PROTO((tree, tree, tree, tree)); +extern tree lookup_template_class PROTO((tree, tree, tree, tree, int)); extern tree lookup_template_function PROTO((tree, tree)); extern int uses_template_parms PROTO((tree)); extern tree instantiate_class_template PROTO((tree)); @@ -2708,8 +2786,6 @@ extern void begin_tree PROTO((void)); extern void end_tree PROTO((void)); extern void add_maybe_template PROTO((tree, tree)); extern void pop_tinst_level PROTO((void)); -extern tree most_specialized PROTO((tree, tree, tree)); -extern tree most_specialized_class PROTO((tree, tree, tree)); extern int more_specialized_class PROTO((tree, tree)); extern void do_pushlevel PROTO((void)); extern int is_member_template PROTO((tree)); @@ -2717,6 +2793,7 @@ extern int comp_template_parms PROTO((tree, tree)); extern int template_class_depth PROTO((tree)); extern int is_specialization_of PROTO((tree, tree)); extern int comp_template_args PROTO((tree, tree)); +extern void maybe_process_partial_specialization PROTO((tree)); extern int processing_specialization; extern int processing_explicit_instantiation; @@ -2839,6 +2916,8 @@ extern tree finish_class_definition PROTO((tree, tree, tree, int)); extern void finish_default_args PROTO((void)); extern void begin_inline_definitions PROTO((void)); extern tree finish_member_class_template PROTO((tree, tree)); +extern void finish_template_decl PROTO((tree)); +extern tree finish_template_type PROTO((tree, tree, int)); /* in sig.c */ extern tree build_signature_pointer_type PROTO((tree, int, int)); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 0149679cb9e..aa5204ec844 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2339,8 +2339,8 @@ pushtag (name, type, globalize) class scope. In the friend case, push_template_decl will already have put the friend into global scope, if appropriate. */ - if (!globalize && b->pseudo_global && - b->level_chain->parm_flag == 2) + if (!globalize && b->pseudo_global + && b->level_chain->parm_flag == 2) { pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type), b->level_chain); @@ -4455,6 +4455,9 @@ lookup_tag (form, name, binding_level, thislevel_only) int thislevel_only; { register struct binding_level *level; + /* Non-zero if, we should look past a pseudo-global level, even if + THISLEVEL_ONLY. */ + int allow_pseudo_global = 1; for (level = binding_level; level; level = level->level_chain) { @@ -4472,7 +4475,19 @@ lookup_tag (form, name, binding_level, thislevel_only) /* XXX: is this a real lookup, considering using-directives etc. ??? */ for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail)) { - tree old = BINDING_TYPE (binding_for_name (name, tail)); + tree old = binding_for_name (name, tail); + + /* If we just skipped past a pseudo global level, even + though THISLEVEL_ONLY, and we find a template class + declaration, then we use the _TYPE node for the + template. See the example below. */ + if (thislevel_only && !allow_pseudo_global + && old && BINDING_VALUE (old) + && DECL_CLASS_TEMPLATE_P (BINDING_VALUE (old))) + old = TREE_TYPE (BINDING_VALUE (old)); + else + old = BINDING_TYPE (old); + /* If it has an original type, it is a typedef, and we should not return it. */ if (old && DECL_ORIGINAL_TYPE (TYPE_NAME (old))) @@ -4509,16 +4524,24 @@ lookup_tag (form, name, binding_level, thislevel_only) } if (thislevel_only && ! level->tag_transparent) { - if (level->pseudo_global) - { - tree t = IDENTIFIER_CLASS_VALUE (name); - if (t && DECL_CLASS_TEMPLATE_P (t)) - return TREE_TYPE (t); - t = IDENTIFIER_NAMESPACE_VALUE (name); - if (t && DECL_CLASS_TEMPLATE_P (t)) - return TREE_TYPE (t); + if (level->pseudo_global && allow_pseudo_global) + { + /* We must deal with cases like this: + + template struct S; + template struct S {}; + + When looking up `S', for the second declaration, we + would like to find the first declaration. But, we + are in the pseudo-global level created for the + template parameters, rather than the (surrounding) + namespace level. Thus, we keep going one more level, + even though THISLEVEL_ONLY is non-zero. */ + allow_pseudo_global = 0; + continue; } - return NULL_TREE; + else + return NULL_TREE; } if (current_class_type && level->level_chain->namespace_p) { @@ -4730,7 +4753,8 @@ make_typename_type (context, name) } return lookup_template_class (t, TREE_OPERAND (fullname, 1), - NULL_TREE, context); + NULL_TREE, context, + /*entering_scope=*/0); } else { @@ -6207,18 +6231,7 @@ shadow_tag (declspecs) { my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261); - if (IS_AGGR_TYPE (value) && CLASSTYPE_USE_TEMPLATE (value)) - { - if (CLASSTYPE_IMPLICIT_INSTANTIATION (value) - && TYPE_SIZE (value) == NULL_TREE) - { - SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (value); - if (processing_template_decl) - push_template_decl (TYPE_MAIN_DECL (value)); - } - else if (CLASSTYPE_TEMPLATE_INSTANTIATION (value)) - cp_error ("specialization after instantiation of `%T'", value); - } + maybe_process_partial_specialization (value); t = value; ok_code = code; @@ -10241,9 +10254,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) { tree t = NULL_TREE; if (decl && DECL_NAME (decl)) - t = do_friend (ctype, declarator, decl, - last_function_parms, flags, quals, - funcdef_flag); + { + if (template_class_depth (current_class_type) == 0) + decl + = check_explicit_specialization + (declarator, decl, + template_count, 2 * (funcdef_flag != 0) + 4); + t = do_friend (ctype, declarator, decl, + last_function_parms, flags, quals, + funcdef_flag); + } if (t && funcdef_flag) return t; @@ -11321,37 +11341,66 @@ xref_tag (code_type_node, name, binfo, globalize) if (t && TYPE_CONTEXT (t) && got_type) ref = t; else - { - /* If we know we are defining this tag, only look it up in - this scope and don't try to find it as a type. */ - ref = lookup_tag (code, name, b, 1); - } + /* If we know we are defining this tag, only look it up in + this scope and don't try to find it as a type. */ + ref = lookup_tag (code, name, b, 1); } else { - if (t) - ref = t; - else - ref = lookup_tag (code, name, b, 0); - - if (! ref) - { - /* Try finding it as a type declaration. If that wins, use it. */ - ref = lookup_name (name, 1); + if (current_class_type + && template_class_depth (current_class_type) + && (processing_template_decl + > template_class_depth (current_class_type))) + /* Since GLOBALIZE is non-zero, we are not looking at a + definition of this tag. Since, in addition, we are currently + processing a (member) template declaration of a template + class, we don't want to do any lookup at all; consider: + + template + struct S1 + + template + struct S2 + { template + friend struct S1; }; + + Here, the S2::S1 declaration should not be confused with the + outer declaration. In particular, the inner version should + have a template parameter of level 2, not level 1. This + would be particularly important if the member declaration + were instead: + + template friend struct S1; + + say, when we should tsubst into `U' when instantiating S2. */ + ref = NULL_TREE; + else + { + if (t) + ref = t; + else + ref = lookup_tag (code, name, b, 0); + + if (! ref) + { + /* Try finding it as a type declaration. If that wins, + use it. */ + ref = lookup_name (name, 1); - if (ref != NULL_TREE - && processing_template_decl - && DECL_CLASS_TEMPLATE_P (ref) - && template_class_depth (current_class_type) == 0) - /* Since GLOBALIZE is true, we're declaring a global + if (ref != NULL_TREE + && processing_template_decl + && DECL_CLASS_TEMPLATE_P (ref) + && template_class_depth (current_class_type) == 0) + /* Since GLOBALIZE is true, we're declaring a global template, so we want this type. */ - ref = DECL_RESULT (ref); + ref = DECL_RESULT (ref); - if (ref && TREE_CODE (ref) == TYPE_DECL - && TREE_CODE (TREE_TYPE (ref)) == code) - ref = TREE_TYPE (ref); - else - ref = NULL_TREE; + if (ref && TREE_CODE (ref) == TYPE_DECL + && TREE_CODE (TREE_TYPE (ref)) == code) + ref = TREE_TYPE (ref); + else + ref = NULL_TREE; + } } } @@ -12121,13 +12170,24 @@ start_function (declspecs, declarator, attrs, pre_parsed_p) (This does not mean `static' in the C sense!) */ TREE_STATIC (decl1) = 1; + /* Set up current_class_type, and enter the scope of the class, if + appropriate. */ + if (ctype) + push_nested_class (ctype, 1); + else if (DECL_STATIC_FUNCTION_P (decl1)) + push_nested_class (DECL_CONTEXT (decl1), 2); + + /* We must call push_template_decl after current_class_type is set + up. (If we are processing inline definitions after exiting a + class scope, current_class_type will be NULL_TREE until set above + 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. */ - - if (processing_template_decl) - decl1 = push_template_decl (decl1); - else if (pre_parsed_p == 0) + if (!processing_template_decl && pre_parsed_p == 0) { /* A specialization is not used to guide overload resolution. */ if ((flag_guiding_decls @@ -12207,8 +12267,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p) if (ctype) { - push_nested_class (ctype, 1); - /* If we're compiling a friend function, neither of the variables current_class_ptr nor current_class_type will have values. */ if (! doing_friend) @@ -12241,10 +12299,8 @@ start_function (declspecs, declarator, attrs, pre_parsed_p) } else { - if (DECL_STATIC_FUNCTION_P (decl1)) - push_nested_class (DECL_CONTEXT (decl1), 2); - else - push_memoized_context (0, 1); + if (!DECL_STATIC_FUNCTION_P (decl1)) + push_memoized_context (NULL_TREE, 1); current_class_ptr = current_class_ref = NULL_TREE; } @@ -13185,7 +13241,8 @@ start_method (declspecs, declarator) if (flag_default_inline) DECL_INLINE (fndecl) = 1; - if (processing_template_decl) + /* We process method specializations in finish_struct_1. */ + if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl)) fndecl = push_template_decl (fndecl); /* We read in the parameters on the maybepermanent_obstack, diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 901f5658722..3aa5d73593b 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -912,34 +912,29 @@ grok_x_components (specs, components) break; case RECORD_TYPE: - /* This code may be needed for UNION_TYPEs as - well. */ - tcode = record_type_node; + case UNION_TYPE: + if (TREE_CODE (t) == UNION_TYPE) + tcode = union_type_node; + else + tcode = record_type_node; if (CLASSTYPE_DECLARED_CLASS (t)) tcode = class_type_node; else if (IS_SIGNATURE (t)) tcode = signature_type_node; - - if (CLASSTYPE_IS_TEMPLATE (t)) - /* In this case, the TYPE_IDENTIFIER will be something - like S, rather than S, so to get the correct name we - look at the template. */ - x = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t)); - else - x = TYPE_IDENTIFIER (t); - - t = xref_tag (tcode, x, NULL_TREE, 0); - return NULL_TREE; - break; - - case UNION_TYPE: - case ENUMERAL_TYPE: - if (TREE_CODE (t) == UNION_TYPE) - tcode = union_type_node; + + if (TYPE_LANG_SPECIFIC (t) + && CLASSTYPE_USE_TEMPLATE (t)) + /* We have already looked up this type. */ + ; else - tcode = enum_type_node; + { + if (CLASSTYPE_IS_TEMPLATE (t)) + x = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t)); + else + x = TYPE_IDENTIFIER (t); + t = xref_tag (tcode, x, NULL_TREE, 0); + } - t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0); if (ANON_UNION_TYPE_P (t)) { /* See also shadow_tag. */ @@ -972,11 +967,17 @@ grok_x_components (specs, components) for (; *p; *p = (*p)->next) if (DECL_CONTEXT ((*p)->fndecl) != t) break; + + return x; } - else if (TREE_CODE (t) == ENUMERAL_TYPE) - x = grok_enum_decls (NULL_TREE); - else - x = NULL_TREE; + + return NULL_TREE; + break; + + case ENUMERAL_TYPE: + tcode = enum_type_node; + t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0); + x = grok_enum_decls (NULL_TREE); return x; break; @@ -1132,16 +1133,7 @@ grokclassfn (ctype, cname, function, flags, quals) TYPE_HAS_DESTRUCTOR (ctype) = 1; } else - { - if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE) - /* Only true for static member functions. */ - arg_types = hash_tree_chain (build_pointer_type (qualtype), - arg_types); - - DECL_ASSEMBLER_NAME (function) - = build_decl_overload (fn_name, arg_types, - 1 + DECL_CONSTRUCTOR_P (function)); - } + set_mangled_name_for_decl (function); } /* Work on the expr used by alignof (this is only called by the parser). */ @@ -4299,7 +4291,7 @@ arg_assoc_class (k, type) /* Process template arguments. */ if (CLASSTYPE_TEMPLATE_INFO (type)) { - list = innermost_args (CLASSTYPE_TI_ARGS (type), 0); + list = innermost_args (CLASSTYPE_TI_ARGS (type)); for (i = 0; i < TREE_VEC_LENGTH (list); ++i) arg_assoc (k, TREE_VEC_ELT (list, i)); } @@ -4690,13 +4682,21 @@ mark_used (decl) if (processing_template_decl) return; assemble_external (decl); + /* Is it a synthesized method that needs to be synthesized? */ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CLASS_CONTEXT (decl) && DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl) /* Kludge: don't synthesize for default args. */ && current_function_decl) synthesize_method (decl); - if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)) + + /* If this is a function or variable that is an instance of some + template, we now know that we will need to actually do the + instantiation. A TEMPLATE_DECL may also have DECL_TEMPLATE_INFO, + if it's a partial instantiation, but there's no need to + instantiate such a thing. */ + if (TREE_CODE (decl) != TEMPLATE_DECL + && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)) instantiate_decl (decl); } diff --git a/gcc/cp/error.c b/gcc/cp/error.c index bb21bcb5021..bd459c2a6f8 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1042,91 +1042,75 @@ dump_function_name (t) else dump_decl (name, 0); - if (DECL_LANG_SPECIFIC (t) && DECL_USE_TEMPLATE (t)) + if (DECL_LANG_SPECIFIC (t) && DECL_USE_TEMPLATE (t) + && DECL_TEMPLATE_INFO (t) + && (DECL_TEMPLATE_SPECIALIZATION (t) + || TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL + || DECL_TEMPLATE_SPECIALIZATION (DECL_TI_TEMPLATE (t)) + || PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t)))) { tree args = DECL_TEMPLATE_INFO (t) ? DECL_TI_ARGS (t) : NULL_TREE; + OB_PUTC ('<'); - if (args != NULL_TREE - && DECL_CONTEXT (t) != NULL_TREE - && uses_template_parms (DECL_CONTEXT (t)) - /* This next clause checks that there is only one level of - template arguments. In that case, they are the - arguments for the class context. */ - && (TREE_CODE (args) == TREE_LIST - || (TREE_CODE (args) == TREE_VEC - && TREE_VEC_ELT (args, 0) != NULL_TREE - && TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC))) - /* We have something like this: - - template struct S { void f(); }; - - and we are printing S::f(). This is a template - instantiation, but we don't print anything after the f. */ - ; - else + /* Be careful only to print things when we have them, so as not + to crash producing error messages. */ + if (args) { - OB_PUTC ('<'); - - /* Be careful only to print things when we have them, so as not - to crash producing error messages. */ - if (args) + if (TREE_CODE (args) == TREE_LIST) { - if (TREE_CODE (args) == TREE_LIST) + tree arg; + int need_comma = 0; + + for (arg = args; arg; arg = TREE_CHAIN (arg)) { - tree arg; - int need_comma = 0; - - for (arg = args; arg; arg = TREE_CHAIN (arg)) - { - tree a = TREE_VALUE (arg); - - if (need_comma) - OB_PUTS (", "); - - if (a) - { - if (TREE_CODE_CLASS (TREE_CODE (a)) == 't' - || TREE_CODE (a) == TEMPLATE_DECL) - dump_type (a, 0); - else - dump_expr (a, 0); - } + tree a = TREE_VALUE (arg); + + if (need_comma) + OB_PUTS (", "); - need_comma = 1; + if (a) + { + if (TREE_CODE_CLASS (TREE_CODE (a)) == 't' + || TREE_CODE (a) == TEMPLATE_DECL) + dump_type (a, 0); + else + dump_expr (a, 0); } + + need_comma = 1; } - else if (TREE_CODE (args) == TREE_VEC) + } + else if (TREE_CODE (args) == TREE_VEC) + { + int i; + int need_comma = 0; + + if (TREE_VEC_LENGTH (args) > 0 + && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC) + args = TREE_VEC_ELT (args, + TREE_VEC_LENGTH (args) - 1); + + for (i = 0; i < TREE_VEC_LENGTH (args); i++) { - int i; - int need_comma = 0; - - if (TREE_VEC_LENGTH (args) > 0 - && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC) - args = TREE_VEC_ELT (args, - TREE_VEC_LENGTH (args) - 1); - - for (i = 0; i < TREE_VEC_LENGTH (args); i++) - { - tree a = TREE_VEC_ELT (args, i); - - if (need_comma) - OB_PUTS (", "); - - if (a) - { - if (TREE_CODE_CLASS (TREE_CODE (a)) == 't' - || TREE_CODE (a) == TEMPLATE_DECL) - dump_type (a, 0); - else - dump_expr (a, 0); - } + tree a = TREE_VEC_ELT (args, i); + + if (need_comma) + OB_PUTS (", "); - need_comma = 1; + if (a) + { + if (TREE_CODE_CLASS (TREE_CODE (a)) == 't' + || TREE_CODE (a) == TEMPLATE_DECL) + dump_type (a, 0); + else + dump_expr (a, 0); } + + need_comma = 1; } } - OB_PUTC ('>'); } + OB_PUTC ('>'); } } diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index 58747effcf0..4bd0b08ecff 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -70,21 +70,22 @@ is_friend (type, supplicant) if (TREE_VALUE (friends) == NULL_TREE) continue; - if (TREE_CODE (TREE_VALUE (friends)) == TEMPLATE_DECL) - { - if (is_specialization_of (supplicant, - TREE_VALUE (friends))) - return 1; - - continue; - } - - /* FIXME: The use of comptypes here is bogus, since - two specializations of a template with non-type - parameters may have the same type, but be - different. */ - if (comptypes (TREE_TYPE (supplicant), - TREE_TYPE (TREE_VALUE (friends)), 1)) + if (supplicant == TREE_VALUE (friends)) + return 1; + + /* With -fguiding-decls we are more lenient about + friendship. This is bogus in general since two + specializations of a template with non-type + template parameters may have the same type, but + be different. */ + if (flag_guiding_decls + && comptypes (TREE_TYPE (supplicant), + TREE_TYPE (TREE_VALUE (friends)), 1)) + return 1; + + if (TREE_CODE (TREE_VALUE (friends)) == TEMPLATE_DECL + && is_specialization_of (supplicant, + TREE_VALUE (friends))) return 1; } break; @@ -253,6 +254,21 @@ make_friend_class (type, friend_type) IDENTIFIER_POINTER (TYPE_IDENTIFIER (friend_type))); return; } + + if (CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type)) + { + /* [temp.friend] + + Friend declarations shall not declare partial + specializations. + + Note that CLASSTYPE_TEMPLATE_SPECIALIZATION is not set for + full specializations. */ + cp_error ("partial specialization `%T' declared `friend'", + friend_type); + return; + } + if (processing_template_decl > template_class_depth (type)) /* If the TYPE is a template then it makes sense for it to be friends with itself; this means that each instantiation is @@ -407,9 +423,7 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag) Note that because classes all wind up being top-level in their scope, their friend wind up in top-level scope as well. */ - DECL_ASSEMBLER_NAME (decl) - = build_decl_overload (declarator, TYPE_ARG_TYPES (TREE_TYPE (decl)), - TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE); + set_mangled_name_for_decl (decl); DECL_ARGUMENTS (decl) = parmdecls; if (funcdef_flag) DECL_CLASS_CONTEXT (decl) = current_class_type; @@ -417,20 +431,17 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag) if (! DECL_USE_TEMPLATE (decl)) { /* We can call pushdecl here, because the TREE_CHAIN of this - FUNCTION_DECL is not needed for other purposes. Don't do this - for a template instantiation. */ - if (!is_friend_template) - { - /* However, we don't call pushdecl() for a friend - function of a template class, since in general, - such a declaration depends on template - parameters. Instead, we call pushdecl when the - class is instantiated. */ - if (template_class_depth (current_class_type) == 0) - decl = pushdecl (decl); - } + FUNCTION_DECL is not needed for other purposes. Don't do + this for a template instantiation. However, we don't + call pushdecl() for a friend function of a template + class, since in general, such a declaration depends on + template parameters. Instead, we call pushdecl when the + class is instantiated. */ + if (!is_friend_template + && template_class_depth (current_class_type) == 0) + decl = pushdecl (decl); else - decl = push_template_decl (decl); + decl = push_template_decl_real (decl, /*is_friend=*/1); if (! funcdef_flag && ! flag_guiding_decls && ! is_friend_template && current_template_parms && uses_template_parms (decl)) diff --git a/gcc/cp/method.c b/gcc/cp/method.c index d718a44920b..a4c19822897 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -71,8 +71,6 @@ static void process_overload_item PROTO((tree,int)); static void do_build_assign_ref PROTO((tree)); static void do_build_copy_constructor PROTO((tree)); static tree largest_union_member PROTO((tree)); -static tree build_decl_overload_real PROTO((tree, tree, tree, tree, - tree, int)); static void build_template_template_parm_names PROTO((tree)); static void build_template_parm_names PROTO((tree, tree)); static void build_underscore_int PROTO((int)); @@ -922,7 +920,7 @@ build_overload_identifier (name) /* NAME is the TYPE_DECL for a template specialization. */ tree template, parmlist, arglist, tname; template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name)); - arglist = innermost_args (TREE_VALUE (template), 0); + arglist = innermost_args (TREE_VALUE (template)); template = TREE_PURPOSE (template); tname = DECL_NAME (template); parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template); @@ -1499,7 +1497,10 @@ build_static_name (context, name) return get_identifier ((char *)obstack_base (&scratch_obstack)); } -static tree +/* FOR_METHOD should be 1 if the declaration in question is for a member + of a class (including a static member) and 2 if the declaration is + for a constructor. */ +tree build_decl_overload_real (dname, parms, ret_type, tparms, targs, for_method) tree dname; @@ -1660,38 +1661,32 @@ build_decl_overload (dname, parms, for_method) NULL_TREE, for_method); } - -/* Like build_decl_overload, but for template functions. */ +/* Set the mangled name (DECL_ASSEMBLER_NAME) for DECL. */ tree -build_template_decl_overload (decl, parms, ret_type, tparms, targs, - for_method) +set_mangled_name_for_decl (decl) tree decl; - tree parms; - tree ret_type; - tree tparms; - tree targs; - int for_method; { - tree res, saved_ctx; + tree parm_types = TYPE_ARG_TYPES (TREE_TYPE (decl)); - /* If the template is in a namespace, we need to put that into the - mangled name. Unfortunately, build_decl_overload_real does not - get the decl to mangle, so it relies on the current - namespace. Therefore, we set that here temporarily. */ - - my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 980702); - saved_ctx = current_namespace; - current_namespace = CP_DECL_CONTEXT (decl); - - res = build_decl_overload_real (DECL_NAME (decl), parms, ret_type, - tparms, targs, for_method); - - current_namespace = saved_ctx; - return res; + if (DECL_STATIC_FUNCTION_P (decl)) + parm_types = + hash_tree_chain (build_pointer_type (DECL_CLASS_CONTEXT (decl)), + parm_types); + else + /* The only member functions whose type is a FUNCTION_TYPE, rather + than a METHOD_TYPE, should be static members. */ + my_friendly_assert (!DECL_CONTEXT (decl) + || !IS_AGGR_TYPE_CODE (TREE_CODE (DECL_CONTEXT (decl))) + || TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE, + 0); + + DECL_ASSEMBLER_NAME (decl) + = build_decl_overload (DECL_NAME (decl), parm_types, + DECL_FUNCTION_MEMBER_P (decl) + + DECL_CONSTRUCTOR_P (decl)); } - /* Build an overload name for the type expression TYPE. */ tree diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 1113c15ba95..22d92428291 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -267,7 +267,7 @@ empty_parms () %type named_class_head_sans_basetype_defn %type identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN -%type self_template_type +%type self_template_type .finish_template_type %token NSNAME %type NSNAME @@ -556,22 +556,38 @@ template_parm: ; template_def: - template_header - extdef - { - if ($1) - end_template_decl (); - else - end_specialization (); - } - | template_header - error %prec EMPTY - { - if ($1) - end_template_decl (); - else - end_specialization (); - } + template_header template_extdef + { finish_template_decl ($1); } + | template_header error %prec EMPTY + { finish_template_decl ($1); } + ; + +template_extdef: + fndef eat_saved_input + { if (pending_inlines) do_pending_inlines (); } + | template_datadef + { if (pending_inlines) do_pending_inlines (); } + | template_def + { if (pending_inlines) do_pending_inlines (); } + | extern_lang_string .hush_warning fndef .warning_ok eat_saved_input + { if (pending_inlines) do_pending_inlines (); + pop_lang_context (); } + | extern_lang_string .hush_warning template_datadef .warning_ok + { if (pending_inlines) do_pending_inlines (); + pop_lang_context (); } + | extension template_extdef + { pedantic = $1; } + ; + +template_datadef: + nomods_initdecls ';' + | declmods notype_initdecls ';' + {} + | typed_declspecs initdecls ';' + { note_list_got_semicolon ($1.t); } + | structsp ';' + { maybe_process_partial_specialization ($1.t); + note_got_semicolon ($1.t); } ; datadef: @@ -579,9 +595,7 @@ datadef: | declmods notype_initdecls ';' {} | typed_declspecs initdecls ';' - { - note_list_got_semicolon ($1.t); - } + { note_list_got_semicolon ($1.t); } | declmods ';' { pedwarn ("empty declaration"); } | explicit_instantiation ';' @@ -870,29 +884,29 @@ end_explicit_instantiation: template_type: PTYPENAME '<' template_arg_list_opt template_close_bracket - { - $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE); - if ($$ != error_mark_node) - $$ = TYPE_STUB_DECL ($$); - } + .finish_template_type + { $$ = $5; } | TYPENAME '<' template_arg_list_opt template_close_bracket - { - $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE); - if ($$ != error_mark_node) - $$ = TYPE_STUB_DECL ($$); - } + .finish_template_type + { $$ = $5; } | self_template_type ; self_template_type: SELFNAME '<' template_arg_list_opt template_close_bracket - { - $$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE); - if ($$ != error_mark_node) - $$ = TYPE_STUB_DECL ($$); - } + .finish_template_type + { $$ = $5; } ; +.finish_template_type: + { + if (yychar == YYEMPTY) + yychar = YYLEX; + + $$ = finish_template_type ($-3, $-1, + yychar == SCOPE); + } + template_close_bracket: '>' | RSHIFT @@ -2193,18 +2207,7 @@ named_class_head: cp_pedwarn ("non-`union' tag used in declaring `%#T'", $$); if ($2) { - if (IS_AGGR_TYPE ($$) && CLASSTYPE_USE_TEMPLATE ($$)) - { - if (CLASSTYPE_IMPLICIT_INSTANTIATION ($$) - && TYPE_SIZE ($$) == NULL_TREE) - { - SET_CLASSTYPE_TEMPLATE_SPECIALIZATION ($$); - if (processing_template_decl) - push_template_decl (TYPE_MAIN_DECL ($$)); - } - else if (CLASSTYPE_TEMPLATE_INSTANTIATION ($$)) - cp_error ("specialization after instantiation of `%T'", $$); - } + maybe_process_partial_specialization ($$); xref_basetypes (current_aggr, $1, $$, $2); } } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 9c724314ccf..07174a0b4c0 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -80,29 +80,29 @@ static int unify PROTO((tree, tree, tree, tree, int, int*)); static void add_pending_template PROTO((tree)); static int push_tinst_level PROTO((tree)); static tree classtype_mangled_name PROTO((tree)); -static char *mangle_class_name_for_template PROTO((char *, tree, tree, tree)); +static char *mangle_class_name_for_template PROTO((char *, tree, tree)); static tree tsubst_expr_values PROTO((tree, tree)); static int list_eq PROTO((tree, tree)); -static tree get_class_bindings PROTO((tree, tree, tree, tree)); +static tree get_class_bindings PROTO((tree, tree, tree)); static tree coerce_template_parms PROTO((tree, tree, tree, int, int)); static tree tsubst_enum PROTO((tree, tree, tree *)); static tree add_to_template_args PROTO((tree, tree)); +static tree add_outermost_template_args PROTO((tree, tree)); static void maybe_adjust_types_for_deduction PROTO((unification_kind_t, tree*, tree*)); static int type_unification_real PROTO((tree, tree, tree, tree, int, unification_kind_t, int, int*)); -static tree complete_template_args PROTO((tree, tree, int)); static void note_template_header PROTO((int)); static tree maybe_fold_nontype_arg PROTO((tree)); static tree convert_nontype_argument PROTO((tree, tree)); static tree get_bindings_overload PROTO((tree, tree, tree)); static int for_each_template_parm PROTO((tree, tree_fn_t, void*)); static tree build_template_parm_index PROTO((int, int, int, tree, tree)); -static tree original_template PROTO((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 void register_specialization PROTO((tree, tree, tree)); +static tree register_specialization PROTO((tree, tree, tree)); +static int unregister_specialization PROTO((tree, tree)); static void print_candidates PROTO((tree)); static tree reduce_template_parm_level PROTO((tree, tree, int)); static tree build_template_decl PROTO((tree, tree)); @@ -114,17 +114,72 @@ static int template_decl_level PROTO((tree)); static tree maybe_get_template_decl_from_type_decl PROTO((tree)); static int check_cv_quals_for_unify PROTO((int, tree, tree)); static tree tsubst_template_arg_vector PROTO((tree, tree)); +static tree tsubst_template_parms PROTO((tree, tree)); static void regenerate_decl_from_template PROTO((tree, tree)); static int is_member_template_class PROTO((tree)); - -/* Nonzero if ARGVEC contains multiple levels of template arguments. */ -#define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE) \ - (NODE != NULL_TREE \ - && TREE_CODE (NODE) == TREE_VEC \ - && TREE_VEC_LENGTH (NODE) > 0 \ - && TREE_VEC_ELT (NODE, 0) != NULL_TREE \ +static tree most_specialized PROTO((tree, tree, tree)); +static tree most_specialized_class PROTO((tree, tree)); +static tree most_general_template PROTO((tree)); +static void set_mangled_name_for_template_decl 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 + arguments directly. If there is more than one level of template + arguments, then each entry in the TREE_VEC is itself a TREE_VEC, + containing the template arguments for a single level. The first + entry in the outer TREE_VEC is the outermost level of template + parameters; the last is the innermost. + + It is incorrect to ever form a template argument vector containing + only one level of arguments, but which is a TREE_VEC containing as + its only entry the TREE_VEC for that level. */ + +/* The depth of a template argument vector. When called directly by + the parser, we use a TREE_LIST rather than a TREE_VEC to represent + template arguments. In fact, we may even see NULL_TREE if there + are no template arguments. In both of those cases, there is only + one level of template arguments. */ +#define TMPL_ARGS_DEPTH(NODE) \ + ((NODE != NULL_TREE \ + && TREE_CODE (NODE) == TREE_VEC \ + && TREE_VEC_LENGTH (NODE) > 0 \ + && TREE_VEC_ELT (NODE, 0) != NULL_TREE \ + && TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC) ? \ + TREE_VEC_LENGTH (NODE) : 1) + +/* Non-zero if the template arguments is actually a vector of vectors, + rather than just a vector. */ +#define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE) \ + (NODE != NULL_TREE \ + && TREE_CODE (NODE) == TREE_VEC \ + && TREE_VEC_LENGTH (NODE) > 0 \ + && TREE_VEC_ELT (NODE, 0) != NULL_TREE \ && TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC) +/* The LEVELth level of the template ARGS. Note that template + parameter levels are indexed from 1, not from 0. */ +#define TMPL_ARGS_LEVEL(ARGS, LEVEL) \ + (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (ARGS) \ + ? TREE_VEC_ELT ((ARGS), (LEVEL) - 1) : ARGS) + +/* Set the LEVELth level of the template ARGS to VAL. This macro does + not work with single-level argument vectors. */ +#define SET_TMPL_ARGS_LEVEL(ARGS, LEVEL, VAL) \ + (TREE_VEC_ELT ((ARGS), (LEVEL) - 1) = (VAL)) + +/* Accesses the IDXth parameter in the LEVELth level of the ARGS. */ +#define TMPL_ARG(ARGS, LEVEL, IDX) \ + (TREE_VEC_ELT (TMPL_ARGS_LEVEL (ARGS, LEVEL), IDX)) + +/* Set the IDXth element in the LEVELth level of ARGS to VAL. This + macro does not work with single-level argument vectors. */ +#define SET_TMPL_ARG(ARGS, LEVEL, IDX, VAL) \ + (TREE_VEC_ELT (TREE_VEC_ELT ((ARGS), (LEVEL) - 1), (IDX)) = (VAL)) + +/* The number of levels of template parameters given by NODE. */ +#define TMPL_PARMS_DEPTH(NODE) \ + (TREE_INT_CST_HIGH (TREE_PURPOSE (NODE))) + /* Do any processing required when DECL (a member template declaration using TEMPLATE_PARAMETERS as its innermost parameter list) is finished. Returns the TEMPLATE_DECL corresponding to DECL, unless @@ -135,10 +190,7 @@ finish_member_template_decl (template_parameters, decl) tree template_parameters; tree decl; { - if (template_parameters) - end_template_decl (); - else - end_specialization (); + finish_template_decl (template_parameters); if (decl == NULL_TREE || decl == void_type_node) return NULL_TREE; @@ -203,18 +255,6 @@ template_class_depth (type) return depth; } -/* Return the original template for this decl, disregarding any - specializations. */ - -static tree -original_template (decl) - tree decl; -{ - while (DECL_TEMPLATE_INFO (decl)) - decl = DECL_TI_TEMPLATE (decl); - return decl; -} - /* Returns 1 if processing DECL as part of do_pending_inlines needs us to push template parms. */ @@ -225,7 +265,7 @@ inline_needs_template_parms (decl) if (! DECL_TEMPLATE_INFO (decl)) return 0; - return (list_length (DECL_TEMPLATE_PARMS (original_template (decl))) + return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (most_general_template (decl))) > (processing_template_decl + DECL_TEMPLATE_SPECIALIZATION (decl))); } @@ -293,9 +333,9 @@ maybe_begin_member_template_processing (decl) if (! inline_needs_template_parms (decl)) return; - parms = DECL_TEMPLATE_PARMS (original_template (decl)); + parms = DECL_TEMPLATE_PARMS (most_general_template (decl)); - levels = list_length (parms) - processing_template_decl; + levels = TMPL_PARMS_DEPTH (parms) - processing_template_decl; if (DECL_TEMPLATE_SPECIALIZATION (decl)) { @@ -371,7 +411,7 @@ is_member_template (t) /* If there are more levels of template parameters than there are template classes surrounding the declaration, then we have a member template. */ - && (list_length (DECL_TEMPLATE_PARMS (tmpl)) > + && (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)) > template_class_depth (DECL_CLASS_CONTEXT (t)))) return 1; } @@ -400,146 +440,58 @@ is_member_template_class (t) /* If there are more levels of template parameters than there are template classes surrounding the declaration, then we have a member template. */ - return (list_length (DECL_TEMPLATE_PARMS (t)) > + return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) > template_class_depth (DECL_CONTEXT (t))); } -/* Return a new template argument vector which contains all of ARGS - for all outer templates TMPL is contained in, but has as its - innermost set of arguments the EXTRA_ARGS. If UNBOUND_ONLY, we - are only interested in unbound template arguments, not arguments from - enclosing templates that have been instantiated already. */ +/* Return a new template argument vector which contains all of ARGS, + but has as its innermost set of arguments the EXTRA_ARGS. The + resulting vector will be built on a temporary obstack, and so must + be explicitly copied to the permanent obstack, if required. */ static tree -complete_template_args (tmpl, extra_args, unbound_only) - tree tmpl, extra_args; - int unbound_only; +add_to_template_args (args, extra_args) + tree args; + tree extra_args; { - /* depth is the number of levels of enclosing args we're adding. */ - int depth, i; - tree args, new_args, spec_args = NULL_TREE; - int extra_arg_depth; - - my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0); - my_friendly_assert (TREE_CODE (extra_args) == TREE_VEC, 0); - - if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (extra_args)) - extra_arg_depth = TREE_VEC_LENGTH (extra_args); - else - extra_arg_depth = 1; - - if (DECL_TEMPLATE_INFO (tmpl) && !unbound_only) - { - /* A specialization of a member template of a template class shows up - as a TEMPLATE_DECL with DECL_TEMPLATE_SPECIALIZATION set. - DECL_TI_ARGS is the specialization args, and DECL_TI_TEMPLATE - is the template being specialized. */ - if (DECL_TEMPLATE_SPECIALIZATION (tmpl)) - { - spec_args = DECL_TI_ARGS (tmpl); - tmpl = DECL_TI_TEMPLATE (tmpl); - } - - if (DECL_TEMPLATE_INFO (tmpl)) - { - /* A partial instantiation of a member template shows up as a - TEMPLATE_DECL with DECL_TEMPLATE_INFO. DECL_TI_ARGS is - all the bound template arguments. */ - args = DECL_TI_ARGS (tmpl); - if (!TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)) - depth = 1; - else - depth = TREE_VEC_LENGTH (args); - } - else - /* If we are a specialization, we might have no previously bound - template args. */ - depth = 0; - - new_args = make_tree_vec (depth + extra_arg_depth + (!!spec_args)); - - if (depth == 1) - TREE_VEC_ELT (new_args, 0) = args; - else - for (i = 0; i < depth; ++i) - TREE_VEC_ELT (new_args, i) = TREE_VEC_ELT (args, i); - } - else - { - tree type; - int skip; - - /* For unbound args, we have to do more work. We are getting bindings - for the innermost args from extra_args, so we start from our - context and work out until we've seen all the args. We need to - do it this way to handle partial specialization. */ - - depth = list_length (DECL_TEMPLATE_PARMS (tmpl)) - 1; - if (depth == 0) - return extra_args; - - new_args = make_tree_vec (depth + extra_arg_depth); - - /* If this isn't a member template, extra_args is for the innermost - template class, so skip over it. */ - skip = (! is_member_template (tmpl)); - - if (depth > skip) - { - type = DECL_REAL_CONTEXT (tmpl); - for (i = depth; i; type = TYPE_CONTEXT (type)) - if (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))) - { - if (skip) - skip = 0; - else - { - --i; - TREE_VEC_ELT (new_args, i) = CLASSTYPE_TI_ARGS (type); - } - } - } - } + tree new_args; + int extra_depth; + int i; + int j; - if (extra_arg_depth == 1) - TREE_VEC_ELT (new_args, depth++) = extra_args; - else - for (i = 0; i < extra_arg_depth; ++i) - TREE_VEC_ELT (new_args, depth++) = TREE_VEC_ELT (extra_args, i); + extra_depth = TMPL_ARGS_DEPTH (extra_args); + new_args = make_temp_vec (TMPL_ARGS_DEPTH (args) + extra_depth); - if (spec_args) - TREE_VEC_ELT (new_args, depth) = spec_args; + for (i = 1; i <= TMPL_ARGS_DEPTH (args); ++i) + SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (args, i)); + for (j = 1; j <= extra_depth; ++j, ++i) + SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (extra_args, j)); + return new_args; } -/* Return a new template argument vector which contains all of ARGS, - but has as its innermost set of arguments the EXTRA_ARGS. */ +/* Like add_to_template_args, but only the outermost ARGS are added to + the EXTRA_ARGS. In particular, all but TMPL_ARGS_DEPTH + (EXTRA_ARGS) levels are added. This function is used to combine + the template arguments from a partial instantiation with the + template arguments used to attain the full instantiation from the + partial instantiation. */ static tree -add_to_template_args (args, extra_args) +add_outermost_template_args (args, extra_args) tree args; tree extra_args; { tree new_args; - if (!TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)) - { - new_args = make_tree_vec (2); - TREE_VEC_ELT (new_args, 0) = args; - } - else - { - int i; - - new_args = make_tree_vec (TREE_VEC_LENGTH (args) + 1); + /* For the moment, we make ARGS look like it contains fewer levels. */ + TREE_VEC_LENGTH (args) -= TMPL_ARGS_DEPTH (extra_args); + + new_args = add_to_template_args (args, extra_args); - for (i = 0; i < TREE_VEC_LENGTH (args); ++i) - TREE_VEC_ELT (new_args, i) = TREE_VEC_ELT (args, i); - } - - TREE_VEC_ELT (new_args, - TREE_VEC_LENGTH (new_args) - 1) = extra_args; + /* Now, we restore ARGS to its full dimensions. */ + TREE_VEC_LENGTH (args) += TMPL_ARGS_DEPTH (extra_args); return new_args; } @@ -625,6 +577,27 @@ end_explicit_instantiation () --processing_explicit_instantiation; } +/* The TYPE is being declared. If it is a template type, that means it + is a partial specialization. Do appropriate error-checking. */ + +void +maybe_process_partial_specialization (type) + tree type; +{ + if (IS_AGGR_TYPE (type) && CLASSTYPE_USE_TEMPLATE (type)) + { + if (CLASSTYPE_IMPLICIT_INSTANTIATION (type) + && TYPE_SIZE (type) == NULL_TREE) + { + SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type); + if (processing_template_decl) + push_template_decl (TYPE_MAIN_DECL (type)); + } + else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type)) + cp_error ("specialization of `%T' after instantiation", type); + } +} + /* Retrieve the specialization (in the sense of [temp.spec] - a specialization is either an instantiation or an explicit specialization) of TMPL for the given template ARGS. If there is @@ -641,6 +614,12 @@ retrieve_specialization (tmpl, args) my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0); + /* There should be as many levels of arguments as there are + levels of parameters. */ + my_friendly_assert (TMPL_ARGS_DEPTH (args) + == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)), + 0); + for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); s != NULL_TREE; s = TREE_CHAIN (s)) @@ -684,9 +663,10 @@ is_specialization_of (decl, tmpl) } /* Register the specialization SPEC as a specialization of TMPL with - the indicated ARGS. */ + the indicated ARGS. Returns SPEC, or an equivalent prior + declaration, if available. */ -static void +static tree register_specialization (spec, tmpl, args) tree spec; tree tmpl; @@ -696,14 +676,27 @@ register_specialization (spec, tmpl, args) my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0); - if (TREE_CODE (spec) != TEMPLATE_DECL - && list_length (DECL_TEMPLATE_PARMS (tmpl)) > 1) - /* Avoid registering function declarations as - specializations of member templates, as would otherwise - happen with out-of-class specializations of member - templates. */ - return; + if (TREE_CODE (spec) == FUNCTION_DECL + && uses_template_parms (DECL_TI_ARGS (spec))) + /* This is the FUNCTION_DECL for a partial instantiation. Don't + register it; we want the corresponding TEMPLATE_DECL instead. + We use `uses_template_parms (DECL_TI_ARGS (spec))' rather than + the more obvious `uses_template_parms (spec)' to avoid problems + with default function arguments. In particular, given + something like this: + + template void f(T t1, T t = T()) + + the default argument expression is not substituted for in an + instantiation unless and until it is actually needed. */ + return spec; + /* There should be as many levels of arguments as there are + levels of parameters. */ + my_friendly_assert (TMPL_ARGS_DEPTH (args) + == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)), + 0); + for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); s != NULL_TREE; s = TREE_CHAIN (s)) @@ -720,7 +713,7 @@ register_specialization (spec, tmpl, args) { cp_error ("specialization of %D after instantiation", fn); - return; + return spec; } else { @@ -729,10 +722,22 @@ register_specialization (spec, tmpl, args) the second is an explicit specialization, and the implicit instantiation has not yet been used. That situation can occur if we have - implicitly instantiated a member function of - class type, and then specialized it later. */ - TREE_VALUE (s) = spec; - return; + implicitly instantiated a member function and + then specialized it later. + + We can also wind up here if a friend + declaration that looked like an instantiation + turns out to be a specialization: + + template void foo(T); + class S { friend void foo<>(int) }; + template <> void foo(int); + + We transform the existing DECL in place so that + any pointers to it become pointers to the + updated declaration. */ + duplicate_decls (spec, TREE_VALUE (s)); + return TREE_VALUE (s); } } else if (DECL_TEMPLATE_SPECIALIZATION (fn)) @@ -741,13 +746,38 @@ register_specialization (spec, tmpl, args) cp_error ("duplicate specialization of %D", fn); TREE_VALUE (s) = spec; - return; + return spec; } } } DECL_TEMPLATE_SPECIALIZATIONS (tmpl) = perm_tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl)); + + return spec; +} + +/* Unregister the specialization SPEC as a specialization of TMPL. + Returns nonzero if the SPEC was listed as a specialization of + TMPL. */ + +static int +unregister_specialization (spec, tmpl) + tree spec; + tree tmpl; +{ + tree* s; + + for (s = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl); + *s != NULL_TREE; + s = &TREE_CHAIN (*s)) + if (TREE_VALUE (*s) == spec) + { + *s = TREE_CHAIN (*s); + return 1; + } + + return 0; } /* Print the list of candidate FNS in an error message. */ @@ -856,13 +886,26 @@ determine_specialization (template_id, decl, targs_out, if (decl != NULL_TREE) { tree tmpl = most_specialized (templates, decl, targs_in); + tree inner_args; + tree tmpl_args; if (tmpl == error_mark_node) goto ambiguous; else if (tmpl == NULL_TREE) goto no_match; - *targs_out = get_bindings (tmpl, decl, targs_in); + inner_args = get_bindings (tmpl, decl, targs_in); + tmpl_args = DECL_TI_ARGS (DECL_RESULT (tmpl)); + if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (tmpl_args)) + { + *targs_out = copy_node (tmpl_args); + SET_TMPL_ARGS_LEVEL (*targs_out, + TMPL_ARGS_DEPTH (*targs_out), + inner_args); + } + else + *targs_out = inner_args; + return tmpl; } @@ -927,8 +970,7 @@ determine_specialization (template_id, decl, targs_out, template struct S {}; template <> struct S { void f(); } - template <> - void S::f(); + template <> void S::f(); the TEMPLATE_COUNT would be 0. (Note that this declaration is illegal; there should be no template <>.) @@ -1018,7 +1060,8 @@ check_explicit_specialization (declarator, decl, template_count, flags) } else if (ctype != NULL_TREE && !TYPE_BEING_DEFINED (ctype) - && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype)) + && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype) + && !is_friend) { /* This case catches outdated code that looks like this: @@ -1049,13 +1092,21 @@ check_explicit_specialization (declarator, decl, template_count, flags) } else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR) { - /* This case handles bogus declarations like - template <> template - void f(); */ + if (is_friend) + /* This could be something like: - cp_error ("template-id `%D' in declaration of primary template", - declarator); - return decl; + template void f(T); + class S { friend void f<>(int); } */ + specialization = 1; + else + { + /* This case handles bogus declarations like template <> + template void f(); */ + + cp_error ("template-id `%D' in declaration of primary template", + declarator); + return decl; + } } } @@ -1073,6 +1124,7 @@ check_explicit_specialization (declarator, decl, template_count, flags) if (specialization || member_specialization || explicit_instantiation) { + tree gen_tmpl; tree tmpl = NULL_TREE; tree targs = NULL_TREE; @@ -1172,9 +1224,10 @@ check_explicit_specialization (declarator, decl, template_count, flags) Note that for an explicit instantiation, even one for a member function, we cannot tell apriori whether the instantiation is for a member template, or just a member - function of a template class. In particular, even in if the - instantiation is for a member template, the template - arguments could be deduced from the declaration. */ + function of a template class. Even if a member template is + being instantiated, the member template arguments may be + elided if they can be deduced from the rest of the + declaration. */ tmpl = determine_specialization (declarator, decl, &targs, member_specialization, @@ -1182,9 +1235,11 @@ check_explicit_specialization (declarator, decl, template_count, flags) if (tmpl && tmpl != error_mark_node) { + gen_tmpl = most_general_template (tmpl); + if (explicit_instantiation) { - decl = instantiate_template (tmpl, targs); + decl = instantiate_template (tmpl, innermost_args (targs)); if (!DECL_TEMPLATE_SPECIALIZATION (decl)) /* There doesn't seem to be anything in the draft to prevent a specialization from being explicitly @@ -1194,72 +1249,49 @@ check_explicit_specialization (declarator, decl, template_count, flags) SET_DECL_EXPLICIT_INSTANTIATION (decl); return decl; } - else if (DECL_STATIC_FUNCTION_P (tmpl) - && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) + + /* If we though that the DECL was a member function, but it + turns out to be specializing a static member function, + make DECL a static member function as well. */ + if (DECL_STATIC_FUNCTION_P (tmpl) + && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) { revert_static_member_fn (&decl, 0, 0); last_function_parms = TREE_CHAIN (last_function_parms); } + /* Set up the DECL_TEMPLATE_INFO for DECL. */ + DECL_TEMPLATE_INFO (decl) + = perm_tree_cons (tmpl, targs, NULL_TREE); + /* Mangle the function name appropriately. Note that we do not mangle specializations of non-template member functions of template classes, e.g. with + template struct S { void f(); } + and given the specialization + template <> void S::f() {} + we do not mangle S::f() here. That's because it's just an ordinary member function and doesn't need special - treatment. */ + treatment. We do this here so that the ordinary, + non-template, name-mangling algorith will not be used + later. */ if ((is_member_template (tmpl) || ctype == NULL_TREE) && name_mangling_version >= 1) - { - tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (tmpl)); - - if (ctype - && TREE_CODE (TREE_TYPE (tmpl)) == FUNCTION_TYPE) - arg_types = - hash_tree_chain (build_pointer_type (ctype), - arg_types); - - DECL_ASSEMBLER_NAME (decl) - = build_template_decl_overload - (decl, arg_types, TREE_TYPE (TREE_TYPE (tmpl)), - DECL_INNERMOST_TEMPLATE_PARMS (tmpl), - targs, ctype != NULL_TREE); - } + set_mangled_name_for_template_decl (decl); if (is_friend && !have_def) - { - /* This is not really a declaration of a specialization. - It's just the name of an instantiation. But, it's not - a request for an instantiation, either. */ + /* This is not really a declaration of a specialization. + It's just the name of an instantiation. But, it's not + a request for an instantiation, either. */ SET_DECL_IMPLICIT_INSTANTIATION (decl); - DECL_TEMPLATE_INFO (decl) - = perm_tree_cons (tmpl, targs, NULL_TREE); - return decl; - } - - /* If DECL_TI_TEMPLATE (decl), the decl is an - instantiation of a specialization of a member template. - (In other words, there was a member template, in a - class template. That member template was specialized. - We then instantiated the class, so there is now an - instance of that specialization.) - - According to the CD2, - - 14.7.3.13 [tmpl.expl.spec] - - A specialization of a member function template or - member class template of a non-specialized class - template is itself a template. - - So, we just leave the template info alone in this case. */ - if (!(DECL_TEMPLATE_INFO (decl) && DECL_TI_TEMPLATE (decl))) - DECL_TEMPLATE_INFO (decl) - = perm_tree_cons (tmpl, targs, NULL_TREE); - register_specialization (decl, tmpl, targs); + /* Register this specialization so that we can find it + again. */ + decl = register_specialization (decl, gen_tmpl, targs); return decl; } @@ -1521,26 +1553,34 @@ end_template_decl () (void) get_pending_sizes (); /* Why? */ } -/* Generate a valid set of template args from current_template_parms. */ +/* Given a template argument vector containing the template PARMS. + The innermost PARMS are given first. */ tree current_template_args () { - tree header = current_template_parms; - int length = list_length (header); - tree args = make_tree_vec (length); + tree header; + tree args; + int length = TMPL_PARMS_DEPTH (current_template_parms); int l = length; - while (header) + /* If there is only one level of template parameters, we do not + create a TREE_VEC of TREE_VECs. Instead, we return a single + TREE_VEC containing the arguments. */ + if (length > 1) + args = make_tree_vec (length); + + for (header = current_template_parms; header; header = TREE_CHAIN (header)) { tree a = copy_node (TREE_VALUE (header)); - int i = TREE_VEC_LENGTH (a); + int i; + TREE_TYPE (a) = NULL_TREE; - while (i--) + for (i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i) { tree t = TREE_VEC_ELT (a, i); - /* t will be a list if we are called from within a + /* T will be a list if we are called from within a begin/end_template_parm_list pair, but a vector directly if within a begin/end_member_template_processing pair. */ if (TREE_CODE (t) == TREE_LIST) @@ -1552,18 +1592,19 @@ current_template_args () t = TREE_TYPE (t); else t = DECL_INITIAL (t); + TREE_VEC_ELT (a, i) = t; } - - TREE_VEC_ELT (a, i) = t; } - TREE_VEC_ELT (args, --l) = a; - header = TREE_CHAIN (header); + + if (length > 1) + TREE_VEC_ELT (args, --l) = a; + else + args = a; } return args; } - /* Return a TEMPLATE_DECL corresponding to DECL, using the indicated template PARMS. Used by push_template_decl below. */ @@ -1668,9 +1709,7 @@ push_template_decl_real (decl, is_friend) /* 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) - /* For a TYPE_DECL, there is no DECL_CLASS_CONTEXT. */ - info = TREE_CODE (decl) == FUNCTION_DECL - ? DECL_CLASS_CONTEXT (decl) : current_class_type; + info = current_class_type; else info = ctx; @@ -1697,8 +1736,7 @@ push_template_decl_real (decl, is_friend) { tree type = TREE_TYPE (decl); tree maintmpl = CLASSTYPE_TI_TEMPLATE (type); - tree mainargs = CLASSTYPE_TI_ARGS (type); - tree spec = DECL_TEMPLATE_SPECIALIZATIONS (maintmpl); + tree specargs = CLASSTYPE_TI_ARGS (type); /* We check that each of the template parameters given in the partial specialization is used in the argument list to the @@ -1732,15 +1770,16 @@ push_template_decl_real (decl, is_friend) or some such would have been OK. */ int i; struct template_parm_data tpd; - int ntparms = TREE_VEC_LENGTH (TREE_VALUE (current_template_parms)); + int ntparms + = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (current_template_parms)); int did_error_intro = 0; - tpd.level = TREE_INT_CST_HIGH (TREE_PURPOSE (current_template_parms)); + tpd.level = TMPL_PARMS_DEPTH (current_template_parms); tpd.parms = alloca (sizeof (int) * ntparms); for (i = 0; i < ntparms; ++i) tpd.parms[i] = 0; - for (i = 0; i < TREE_VEC_LENGTH (mainargs); ++i) - for_each_template_parm (TREE_VEC_ELT (mainargs, i), + for (i = 0; i < TREE_VEC_LENGTH (specargs); ++i) + for_each_template_parm (TREE_VEC_ELT (specargs, i), &mark_template_parm, &tpd); for (i = 0; i < ntparms; ++i) @@ -1760,16 +1799,22 @@ push_template_decl_real (decl, is_friend) i))); } - for (; spec; spec = TREE_CHAIN (spec)) - { - /* purpose: args to main template - value: spec template */ - if (comp_template_args (TREE_PURPOSE (spec), mainargs)) - return decl; - } + /* [temp.class.spec] + + The argument list of the specialization shall not be + identical to the implicit argument list of the primary + template. */ + if (comp_template_args (specargs, + CLASSTYPE_TI_ARGS (TREE_TYPE (maintmpl)))) + cp_error ("partial specialization `%T' does not specialize any template arguments", type); + + if (retrieve_specialization (maintmpl, specargs)) + /* We've already got this specialization. */ + return decl; DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) = CLASSTYPE_TI_SPEC_INFO (type) - = perm_tree_cons (mainargs, TREE_VALUE (current_template_parms), + = perm_tree_cons (innermost_args (specargs), + INNERMOST_TEMPLATE_PARMS (current_template_parms), DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)); TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type; return decl; @@ -1857,7 +1902,7 @@ push_template_decl_real (decl, is_friend) return decl; } - a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1); + a = innermost_args (args); t = DECL_INNERMOST_TEMPLATE_PARMS (tmpl); if (TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a)) { @@ -1865,15 +1910,15 @@ push_template_decl_real (decl, is_friend) TREE_VEC_LENGTH (a), decl); cp_error (" but %d required", TREE_VEC_LENGTH (t)); } - if (TREE_VEC_LENGTH (args) > 1) + if (TMPL_ARGS_DEPTH (args) > 1) /* Get the template parameters for the enclosing template class. */ - a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 2); + a = TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args) - 1); else a = NULL_TREE; } else - a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1); + a = innermost_args (args); t = NULL_TREE; @@ -1899,23 +1944,18 @@ push_template_decl_real (decl, is_friend) cp_error (" but `%#T' has %d", ctx, TREE_VEC_LENGTH (t)); } } - /* Get the innermost set of template arguments. We don't do this - for a non-template member function of a nested template class - because there we will never get a `partial instantiation' of the - function containing the outer arguments, and so we must save all - of the arguments here. */ - if (TREE_CODE (decl) != FUNCTION_DECL - || template_class_depth (ctx) <= 1 - || primary) - args = innermost_args (args, 0); DECL_TEMPLATE_RESULT (tmpl) = decl; TREE_TYPE (tmpl) = TREE_TYPE (decl); - if (! ctx && !(is_friend && template_class_depth (info) > 0)) - /* Note that we do not try to push a global template friend - declared in a template class; such a thing may well depend on - the template parameters of the class. */ + /* Push template declarations for global functions and types. Note + that we do not try to push a global template friend declared in a + template class; such a thing may well depend on the template + parameters of the class. With guiding declarations, however, we + push the template so that subsequent declarations of the template + will match this one. */ + if (! ctx + && !(is_friend && template_class_depth (current_class_type) > 0)) tmpl = pushdecl_namespace_level (tmpl); if (primary) @@ -2733,7 +2773,7 @@ comp_template_args (oldargs, newargs) if (TREE_CODE (nt) == TREE_VEC) { /* For member templates */ - if (comp_template_args (nt, ot)) + if (comp_template_args (ot, nt)) continue; } else if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't') @@ -2752,10 +2792,9 @@ comp_template_args (oldargs, newargs) for the instantiation. */ static char * -mangle_class_name_for_template (name, parms, arglist, ctx) +mangle_class_name_for_template (name, parms, arglist) char *name; tree parms, arglist; - tree ctx; { static struct obstack scratch_obstack; static char *scratch_firstobj; @@ -2767,37 +2806,13 @@ mangle_class_name_for_template (name, parms, arglist, ctx) obstack_free (&scratch_obstack, scratch_firstobj); scratch_firstobj = obstack_alloc (&scratch_obstack, 1); -#if 0 -#define buflen sizeof(buf) -#define check if (bufp >= buf+buflen-1) goto too_long -#define ccat(c) *bufp++=(c); check -#define advance bufp+=strlen(bufp); check -#define cat(s) strncpy(bufp, s, buf+buflen-bufp-1); advance -#else -#define check #define ccat(c) obstack_1grow (&scratch_obstack, (c)); -#define advance #define cat(s) obstack_grow (&scratch_obstack, (s), strlen (s)) -#endif - if (ctx && ctx != global_namespace) - { - char* s; - - if (TREE_CODE (ctx) == FUNCTION_DECL) - s = fndecl_as_string (ctx, 0); - else if (TREE_CODE_CLASS (TREE_CODE (ctx)) == 't') - s = type_as_string_real (ctx, 0, 1); - else if (TREE_CODE (ctx) == NAMESPACE_DECL) - s = decl_as_string (ctx, 0); - else - my_friendly_abort (0); - cat (s); - cat ("::"); - } cat (name); ccat ('<'); nparms = TREE_VEC_LENGTH (parms); + arglist = innermost_args (arglist); my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268); for (i = 0; i < nparms; i++) { @@ -2860,13 +2875,6 @@ mangle_class_name_for_template (name, parms, arglist, ctx) ccat ('>'); ccat ('\0'); return (char *) obstack_base (&scratch_obstack); - -#if 0 - too_long: -#endif - fatal ("out of (preallocated) string space creating template instantiation name"); - /* NOTREACHED */ - return NULL; } static tree @@ -2874,22 +2882,18 @@ classtype_mangled_name (t) tree t; { if (CLASSTYPE_TEMPLATE_INFO (t) + /* Specializations have already had their names set up in + lookup_template_class. */ + && !CLASSTYPE_TEMPLATE_SPECIALIZATION (t) + /* For non-primary templates, the template parameters are + implicit from their surrounding context. */ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t))) { tree name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t)); - /* We do not pass in the context here since that is only needed - when mangling the name of instantiations, not the primary - template declaration. In reality, it should not be needed - then either, but the way lookup_template_class operates - requires the context for the moment. In the long run, - lookup_template_class should not be looking for existing - instantiations by matching mangled names, but rather by - matching the templates, and then scanning the instantiation - list. */ char *mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (name), DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)), - CLASSTYPE_TI_ARGS (t), NULL_TREE); + CLASSTYPE_TI_ARGS (t)); tree id = get_identifier (mangled_name); IDENTIFIER_TEMPLATE (id) = name; return id; @@ -2967,21 +2971,28 @@ maybe_get_template_decl_from_type_decl (decl) parameters, find the desired type. D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments. - Since ARGLIST is build on the decl_obstack, we must copy it here - to keep it from being reclaimed when the decl storage is reclaimed. + (Actually ARGLIST may be either a TREE_LIST or a TREE_VEC. It will + be a TREE_LIST if called directly from the parser, and a TREE_VEC + otherwise.) Since ARGLIST is build on the decl_obstack, we must + copy it here to keep it from being reclaimed when the decl storage + is reclaimed. IN_DECL, if non-NULL, is the template declaration we are trying to instantiate. + If ENTERING_SCOPE is non-zero, we are about to enter the scope of + the class we are looking up. + If the template class is really a local class in a template function, then the FUNCTION_CONTEXT is the function in which it is being instantiated. */ tree -lookup_template_class (d1, arglist, in_decl, context) +lookup_template_class (d1, arglist, in_decl, context, entering_scope) tree d1, arglist; tree in_decl; tree context; + int entering_scope; { tree template = NULL_TREE, parmlist; char *mangled_name; @@ -3070,161 +3081,185 @@ lookup_template_class (d1, arglist, in_decl, context) TYPE_SIZE (parm) = 0; return parm; } - else if (PRIMARY_TEMPLATE_P (template) - || (TREE_CODE (TYPE_CONTEXT (TREE_TYPE (template))) - == FUNCTION_DECL)) + else { - tree arglist_for_mangling; + tree template_type = TREE_TYPE (template); + tree type_decl; + tree found = NULL_TREE; + int arg_depth; + int parm_depth; - parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template); + template = most_general_template (template); + parmlist = DECL_TEMPLATE_PARMS (template); + parm_depth = TMPL_PARMS_DEPTH (parmlist); + arg_depth = TMPL_ARGS_DEPTH (arglist); + + if (arg_depth == 1 && parm_depth > 1) + { + /* We've been with an incomplete set of template arguments. + For example, given: + + template struct S1 { + template struct S2 {}; + template struct S2 {}; + }; + + we will be called with an ARGLIST of `U*', but the + TEMPLATE will be `template template + struct S1::S2'. We must fill in the missing + arguments. */ + my_friendly_assert (context != NULL_TREE, 0); + while (!IS_AGGR_TYPE_CODE (TREE_CODE (context))) + context = DECL_REAL_CONTEXT (context); + arglist = add_to_template_args (CLASSTYPE_TI_ARGS (context), + arglist); + arg_depth = TMPL_ARGS_DEPTH (arglist); + } - if (/* ARGLIST can be NULL_TREE if there are default arguments. */ - arglist != NULL_TREE - && TREE_CODE (arglist) == TREE_VEC - && TREE_VEC_LENGTH (arglist) > 1 - && list_length (DECL_TEMPLATE_PARMS (template)) > 1) + my_friendly_assert (parm_depth == arg_depth, 0); + + /* Calculate the BOUND_ARGS. These will be the args that are + actually tsubst'd into the definition to create the + instantiation. */ + if (parm_depth > 1) { /* We have multiple levels of arguments to coerce, at once. */ - tree new_args = - make_tree_vec (list_length (DECL_TEMPLATE_PARMS (template))); int i; + + tree bound_args = make_tree_vec (parm_depth); for (i = TREE_VEC_LENGTH (arglist) - 1, t = DECL_TEMPLATE_PARMS (template); i >= 0 && t != NULL_TREE; --i, t = TREE_CHAIN (t)) - TREE_VEC_ELT (new_args, i) = + TREE_VEC_ELT (bound_args, i) = coerce_template_parms (TREE_VALUE (t), TREE_VEC_ELT (arglist, i), template, 1, 1); - arglist = new_args; + arglist = bound_args; } else - arglist = coerce_template_parms (parmlist, - innermost_args (arglist, 0), - template, 1, 1); - if (arglist == error_mark_node) + arglist + = coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist), + innermost_args (arglist), + template, 1, 1); + + if (arglist == error_mark_node) + /* We were unable to bind the arguments. */ return error_mark_node; - if (uses_template_parms (arglist)) - { - tree found; - if (comp_template_args - (CLASSTYPE_TI_ARGS (TREE_TYPE (template)), arglist)) - found = TREE_TYPE (template); - else - { - for (found = DECL_TEMPLATE_INSTANTIATIONS (template); - found; found = TREE_CHAIN (found)) - { - if (TI_USES_TEMPLATE_PARMS (found) - && comp_template_args (TREE_PURPOSE (found), arglist)) - break; - } - if (found) - found = TREE_VALUE (found); - } - if (found) + /* In the scope of a template class, explicit references to the + template class refer to the type of the template, not any + instantiation of it. For example, in: + + template class C { void f(C); } + + the `C' is just the same as `C'. Outside of the + class, however, such a reference is an instantiation. */ + if (comp_template_args (CLASSTYPE_TI_ARGS (template_type), + arglist)) + { + found = template_type; + + if (!entering_scope && PRIMARY_TEMPLATE_P (template)) { - if (can_free (&permanent_obstack, arglist)) - obstack_free (&permanent_obstack, arglist); - return found; + tree ctx; + + /* Note that we use DECL_CONTEXT, rather than + CP_DECL_CONTEXT, so that the termination test is + always just `ctx'. We're not interested in namepace + scopes. */ + for (ctx = current_class_type; + ctx; + ctx = (TREE_CODE_CLASS (TREE_CODE (ctx)) == 't') + ? TYPE_CONTEXT (ctx) : DECL_CONTEXT (ctx)) + if (comptypes (ctx, template_type, 1)) + break; + + if (!ctx) + /* We're not in the scope of the class, so the + TEMPLATE_TYPE is not the type we want after + all. */ + found = NULL_TREE; } } - - if (TREE_CODE (arglist) == TREE_VEC) - arglist_for_mangling = innermost_args (arglist, 0); - else - arglist_for_mangling = arglist; - - /* FIXME avoid duplication. */ - mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1), - parmlist, - arglist_for_mangling, - context); - id = get_identifier (mangled_name); - IDENTIFIER_TEMPLATE (id) = d1; - - maybe_push_to_top_level (uses_template_parms (arglist)); - t = xref_tag_from_type (TREE_TYPE (template), id, 1); - - if (context != NULL_TREE) + + if (!found) { - /* Set up the context for the type_decl correctly. Note - that we must clear DECL_ASSEMBLER_NAME to fool - build_overload_name into creating a new name. */ - tree type_decl = TYPE_STUB_DECL (t); - - TYPE_CONTEXT (t) = FROB_CONTEXT (context); - DECL_CONTEXT (type_decl) = FROB_CONTEXT (context); - DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl); - DECL_ASSEMBLER_NAME (type_decl) = - get_identifier (build_overload_name (t, 1, 1)); - } + for (found = DECL_TEMPLATE_INSTANTIATIONS (template); + found; found = TREE_CHAIN (found)) + if (comp_template_args (TREE_PURPOSE (found), arglist)) + break; - pop_from_top_level (); - } - else - { - tree type_ctx = TYPE_CONTEXT (TREE_TYPE (template)); - tree args = tsubst (CLASSTYPE_TI_ARGS (type_ctx), arglist, in_decl); - tree ctx = lookup_template_class (type_ctx, args, - in_decl, NULL_TREE); - id = d1; - arglist = CLASSTYPE_TI_ARGS (ctx); - - if (TYPE_BEING_DEFINED (ctx) && ctx == current_class_type) - { - int save_temp = processing_template_decl; - processing_template_decl = 0; - t = xref_tag_from_type (TREE_TYPE (template), id, 0); - processing_template_decl = save_temp; + if (found) + found = TREE_VALUE (found); } - else + + if (found) { - t = lookup_nested_type_by_name (ctx, id); - my_friendly_assert (t != NULL_TREE, 42); + if (can_free (&permanent_obstack, arglist)) + obstack_free (&permanent_obstack, arglist); + return found; } - } - /* Seems to be wanted. */ - CLASSTYPE_GOT_SEMICOLON (t) = 1; + /* Since we didn't find the type, we'll have to create it. + Since we'll be saving this type on the + DECL_TEMPLATE_INSTANTIATIONS list, it must be permanent. */ + push_obstacks (&permanent_obstack, &permanent_obstack); + + /* Create the type. */ + t = make_lang_type (TREE_CODE (template_type)); + CLASSTYPE_DECLARED_CLASS (t) + = CLASSTYPE_DECLARED_CLASS (template_type); + 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); + DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t); + 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; + + /* We're done with the permanent obstack, now. */ + pop_obstacks (); + + /* Seems to be wanted. */ + CLASSTYPE_GOT_SEMICOLON (t) = 1; - if (! CLASSTYPE_TEMPLATE_INFO (t)) - { + /* Set up the template information. */ arglist = copy_to_permanent (arglist); CLASSTYPE_TEMPLATE_INFO (t) = perm_tree_cons (template, arglist, NULL_TREE); DECL_TEMPLATE_INSTANTIATIONS (template) = perm_tree_cons (arglist, t, DECL_TEMPLATE_INSTANTIATIONS (template)); - TI_USES_TEMPLATE_PARMS (DECL_TEMPLATE_INSTANTIATIONS (template)) - = uses_template_parms (arglist); - SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t); - /* We need to set this again after CLASSTYPE_TEMPLATE_INFO is set up. */ - DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t)) = id; + /* Reset the name of the type, now that CLASSTYPE_TEMPLATE_INFO + is set up. */ + DECL_NAME (type_decl) = classtype_mangled_name (t); + DECL_ASSEMBLER_NAME (type_decl) = DECL_NAME (type_decl); if (! uses_template_parms (arglist)) - DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t)) - = get_identifier (build_overload_name (t, 1, 1)); - - if (flag_external_templates && ! uses_template_parms (arglist) - && CLASSTYPE_INTERFACE_KNOWN (TREE_TYPE (template)) - && ! CLASSTYPE_INTERFACE_ONLY (TREE_TYPE (template))) - add_pending_template (t); - - if (uses_template_parms (arglist)) + { + DECL_ASSEMBLER_NAME (type_decl) + = get_identifier (build_overload_name (t, 1, 1)); + + if (flag_external_templates + && CLASSTYPE_INTERFACE_KNOWN (TREE_TYPE (template)) + && ! CLASSTYPE_INTERFACE_ONLY (TREE_TYPE (template))) + add_pending_template (t); + } + else /* If the type makes use of template parameters, the code that generates debugging information will crash. */ DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1; - } - return t; + return t; + } } -/* Should be defined in parse.h. */ -extern int yychar; - /* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, or TEMPLATE_PARM_INDEX in T, call FN with the parameter and the DATA. If FN returns non-zero, the iteration is terminated, and @@ -3626,32 +3661,26 @@ tsubst_friend_function (decl, args) tree template_id; tree new_args; tree tmpl; - tree tinfo; template_id = lookup_template_function (tsubst_expr (DECL_TI_TEMPLATE (decl), args, NULL_TREE), tsubst (DECL_TI_ARGS (decl), args, NULL_TREE)); - - /* Temporarily remove the DECL_TEMPLATE_INFO so as not to - confuse tsubst. */ - tinfo = DECL_TEMPLATE_INFO (decl); - DECL_TEMPLATE_INFO (decl) = NULL_TREE; + /* FIXME: The decl we create via the next tsubst be created on a + temporary obstack. */ new_friend = tsubst (decl, args, NULL_TREE); - DECL_TEMPLATE_INFO (decl) = tinfo; - - tmpl = determine_specialization (template_id, - new_friend, - &new_args, - 0, 1); + tmpl = determine_specialization (template_id, new_friend, + &new_args, + /*need_member_template=*/0, + /*complain=*/1); new_friend = instantiate_template (tmpl, new_args); goto done; } - else - new_friend = tsubst (decl, args, NULL_TREE); + + new_friend = tsubst (decl, args, NULL_TREE); - /* The new_friend will look like an instantiation, to the + /* The NEW_FRIEND will look like an instantiation, to the compiler, but is not an instantiation from the point of view of the language. For example, we might have had: @@ -3664,15 +3693,110 @@ tsubst_friend_function (decl, args) DECL_USE_TEMPLATE (new_friend) = 0; if (TREE_CODE (decl) == TEMPLATE_DECL) DECL_USE_TEMPLATE (DECL_TEMPLATE_RESULT (new_friend)) = 0; - + + /* The mangled name for the NEW_FRIEND is incorrect. The call to + tsubst will have resulted in a call to + set_mangled_name_for_template_decl. But, the function is not a + template instantiation and should not be mangled like one. + Therefore, we remangle the function name. We don't have to do + this if the NEW_FRIEND is a template since + set_mangled_name_for_template_decl doesn't do anything if the + function declaration still uses template arguments. */ + if (TREE_CODE (new_friend) != TEMPLATE_DECL) + { + set_mangled_name_for_decl (new_friend); + DECL_RTL (new_friend) = 0; + make_decl_rtl (new_friend, NULL_PTR, 1); + } + if (DECL_NAMESPACE_SCOPE_P (new_friend)) { + tree old_decl; + tree new_friend_args; + if (TREE_CODE (new_friend) == TEMPLATE_DECL) /* This declaration is a `primary' template. */ - TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (new_friend)) - = new_friend; + DECL_PRIMARY_TEMPLATE (new_friend) = new_friend; + + /* We must save the DECL_TI_ARGS for NEW_FRIEND here because + pushdecl may call duplicate_decls which will free NEW_FRIEND + if possible. */ + new_friend_args = DECL_TI_ARGS (new_friend); + old_decl = pushdecl_namespace_level (new_friend); + + if (old_decl != new_friend) + { + /* This new friend declaration matched an existing + declaration. For example, given: + + template void f(T); + template class C { + template friend void f(T) {} + }; + + the friend declaration actually provides the definition + of `f', once C has been instantiated for some type. So, + old_decl will be the out-of-class template declaration, + while new_friend is the in-class definition. + + But, if `f' was called before this point, the + instantiation of `f' will have DECL_TI_ARGS corresponding + to `T' but not to `U', references to which might appear + in the definition of `f'. Previously, the most general + template for an instantiation of `f' was the out-of-class + version; now it is the in-class version. Therefore, we + run through all specialization of `f', adding to their + DECL_TI_ARGS appropriately. In particular, they need a + new set of outer arguments, corresponding to the + arguments for this class instantiation. + + The same situation can arise with something like this: + + friend void f(int); + template class C { + friend void f(T) {} + }; + + when `C' is instantiated. Now, `f(int)' is defined + in the class. */ + + if (TREE_CODE (old_decl) != TEMPLATE_DECL) + /* duplicate_decls will take care of this case. */ + ; + else + { + tree t; + + for (t = DECL_TEMPLATE_SPECIALIZATIONS (old_decl); + t != NULL_TREE; + t = TREE_CHAIN (t)) + { + tree spec = TREE_VALUE (t); + + DECL_TI_ARGS (spec) + = add_outermost_template_args (new_friend_args, + DECL_TI_ARGS (spec)); + DECL_TI_ARGS (spec) + = copy_to_permanent (DECL_TI_ARGS (spec)); + } - new_friend = pushdecl_namespace_level (new_friend); + /* Now, since specializations are always supposed to + hang off of the most general template, we must move + them. */ + t = most_general_template (old_decl); + if (t != old_decl) + { + DECL_TEMPLATE_SPECIALIZATIONS (t) + = chainon (DECL_TEMPLATE_SPECIALIZATIONS (t), + DECL_TEMPLATE_SPECIALIZATIONS (old_decl)); + DECL_TEMPLATE_SPECIALIZATIONS (old_decl) = NULL_TREE; + } + } + + /* The information from NEW_FRIEND has been merged into OLD_DECL + by duplicate_decls. */ + new_friend = old_decl; + } } else if (TYPE_SIZE (DECL_CONTEXT (new_friend))) { @@ -3709,9 +3833,15 @@ tsubst_friend_class (friend_tmpl, args) if (tmpl != NULL_TREE && DECL_CLASS_TEMPLATE_P (tmpl)) { /* The friend template has already been declared. Just - check to see that the declarations match. */ - redeclare_class_template (TREE_TYPE (tmpl), - DECL_TEMPLATE_PARMS (friend_tmpl)); + check to see that the declarations match, and install any new + default parameters. We must tsubst the default parameters, + of course. We only need the innermost template parameters + because that is all that redeclare_class_template will look + at. */ + tree parms + = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_tmpl), + args); + redeclare_class_template (TREE_TYPE (tmpl), parms); friend_type = TREE_TYPE (tmpl); } else @@ -3740,32 +3870,19 @@ tree instantiate_class_template (type) tree type; { - tree template, template_info, args, pattern, t, *field_chain; - tree typedecl, outer_args; + tree template, args, pattern, t, *field_chain; + tree typedecl; if (type == error_mark_node) return error_mark_node; - template_info = CLASSTYPE_TEMPLATE_INFO (type); - if (TYPE_BEING_DEFINED (type) || TYPE_SIZE (type)) return type; - template = TI_TEMPLATE (template_info); + template = most_general_template (CLASSTYPE_TI_TEMPLATE (type)); + args = CLASSTYPE_TI_ARGS (type); my_friendly_assert (TREE_CODE (template) == TEMPLATE_DECL, 279); - args = TI_ARGS (template_info); - - if (DECL_TEMPLATE_INFO (template)) - { - outer_args = DECL_TI_ARGS (template); - while (DECL_TEMPLATE_INFO (template)) - template = DECL_TI_TEMPLATE (template); - } - else - outer_args = NULL_TREE; - - t = most_specialized_class - (DECL_TEMPLATE_SPECIALIZATIONS (template), args, outer_args); + t = most_specialized_class (template, args); if (t == error_mark_node) { @@ -3774,7 +3891,7 @@ instantiate_class_template (type) for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t; t = TREE_CHAIN (t)) { if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), - args, outer_args)) + args)) { cp_error_at ("%s %+#T", str, TREE_TYPE (t)); str = " "; @@ -3792,8 +3909,32 @@ instantiate_class_template (type) return type; if (t) - args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), - args, outer_args); + { + /* This TYPE is actually a instantiation of of a partial + specialization. We replace the innermost set of ARGS with + the arguments appropriate for substitution. For example, + given: + + template struct S {}; + template struct S {}; + + and supposing that we are instantiating S, ARGS will + present be {int*} but we need {int}. */ + tree inner_args + = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), + args); + + /* If there were multiple levels in ARGS, replacing the + innermost level would alter CLASSTYPE_TI_ARGS, which we don't + want, so we make a copy first. */ + if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)) + { + args = copy_node (args); + SET_TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args), inner_args); + } + else + args = inner_args; + } if (pedantic && uses_template_parms (args)) /* If there are still template parameters amongst the args, then @@ -3802,11 +3943,6 @@ instantiate_class_template (type) value that results in a specialization being used. */ return type; - /* We must copy the arguments to the permanent obstack since - during the tsubst'ing below they may wind up in the - DECL_TI_ARGS of some instantiated member template. */ - args = copy_to_permanent (args); - TYPE_BEING_DEFINED (type) = 1; if (! push_tinst_level (type)) @@ -3815,8 +3951,10 @@ instantiate_class_template (type) maybe_push_to_top_level (uses_template_parms (type)); pushclass (type, 0); - if (outer_args) - args = add_to_template_args (outer_args, args); + /* We must copy the arguments to the permanent obstack since + during the tsubst'ing below they may wind up in the + DECL_TI_ARGS of some instantiated member template. */ + args = copy_to_permanent (args); if (flag_external_templates) { @@ -3936,11 +4074,12 @@ instantiate_class_template (type) for (t = CLASSTYPE_TAGS (pattern); t; t = TREE_CHAIN (t)) { tree tag = TREE_VALUE (t); + tree name = TYPE_IDENTIFIER (tag); + tree newtag; - /* These will add themselves to CLASSTYPE_TAGS for the new type. */ if (TREE_CODE (tag) == ENUMERAL_TYPE) { - (void) tsubst_enum (tag, args, field_chain); + newtag = tsubst_enum (tag, args, field_chain); while (*field_chain) { DECL_FIELD_CONTEXT (*field_chain) = type; @@ -3948,7 +4087,14 @@ instantiate_class_template (type) } } else - tsubst (tag, args, NULL_TREE); + newtag = tsubst (tag, args, NULL_TREE); + + /* Now, we call pushtag to put this NEWTAG into the scope of + TYPE. We first set up the IDENTIFIER_TYPE_VALUE to avoid + pushtag calling push_template_decl. */ + if (name) + SET_IDENTIFIER_TYPE_VALUE (name, newtag); + pushtag (name, newtag, /*globalize=*/0); } /* Don't replace enum constants here. */ @@ -4014,14 +4160,16 @@ instantiate_class_template (type) tree friend_type = TREE_VALUE (t); tree new_friend_type; - if (TREE_CODE (friend_type) != TEMPLATE_DECL) + if (TREE_CODE (friend_type) == TEMPLATE_DECL) + new_friend_type = tsubst_friend_class (friend_type, args); + else if (uses_template_parms (friend_type)) + new_friend_type = tsubst (friend_type, args, NULL_TREE); + else /* The call to xref_tag_from_type does injection for friend classes. */ new_friend_type = - xref_tag_from_type (tsubst (friend_type, args, NULL_TREE), - NULL_TREE, 1); - else - new_friend_type = tsubst_friend_class (friend_type, args); + xref_tag_from_type (friend_type, NULL_TREE, 1); + if (TREE_CODE (friend_type) == TEMPLATE_DECL) /* Trick make_friend_class into realizing that the friend @@ -4138,20 +4286,14 @@ maybe_fold_nontype_arg (arg) } /* Return the TREE_VEC with the arguments for the innermost template header, - where ARGS is either that or the VEC of VECs for all the arguments. - - If is_spec, then we are dealing with a specialization of a member - template, and want the second-innermost args, the innermost ones that - are instantiated. */ + where ARGS is either that or the VEC of VECs for all the + arguments. */ tree -innermost_args (args, is_spec) +innermost_args (args) tree args; - int is_spec; { - if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)) - return TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1 - is_spec); - return args; + return TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args)); } /* Substitute ARGS into the vector of template arguments T. */ @@ -4189,6 +4331,121 @@ tsubst_template_arg_vector (t, args) return t; } +/* Return the result of substituting ARGS into the template parameters + given by PARMS. If there are m levels of ARGS and m + n levels of + PARMS, then the result will contain n levels of PARMS. For + example, if PARMS is `template template + template ' and ARGS is {{int}, {double}} then the + result will be `template '. */ + +tree +tsubst_template_parms (parms, args) + tree parms; + tree args; +{ + tree r; + tree* new_parms = &r; + + for (new_parms = &r; + TMPL_PARMS_DEPTH (parms) > TMPL_ARGS_DEPTH (args); + new_parms = &(TREE_CHAIN (*new_parms)), + parms = TREE_CHAIN (parms)) + { + tree new_vec = + make_tree_vec (TREE_VEC_LENGTH (TREE_VALUE (parms))); + int i; + + for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i) + { + tree default_value = + TREE_PURPOSE (TREE_VEC_ELT (TREE_VALUE (parms), i)); + tree parm_decl = + TREE_VALUE (TREE_VEC_ELT (TREE_VALUE (parms), i)); + + TREE_VEC_ELT (new_vec, i) + = build_tree_list (tsubst (default_value, args, NULL_TREE), + tsubst (parm_decl, args, NULL_TREE)); + + } + + *new_parms = + tree_cons (build_int_2 (0, (TMPL_PARMS_DEPTH (parms) + - TMPL_ARGS_DEPTH (args))), + new_vec, NULL_TREE); + } + + return r; +} + +/* Substitute the ARGS into the indicated aggregate type T. If T is + not an aggregate type, it is handled as if by tsubst. IN_DECL is + as for tsubst. If ENTERING_SCOPE is non-zero, T is the context for + a template which we are presently tsubst'ing. Return the + subsituted value. */ + +tree +tsubst_aggr_type (t, args, in_decl, entering_scope) + tree t; + tree args; + tree in_decl; + int entering_scope; +{ + if (t == NULL_TREE) + return NULL_TREE; + + switch (TREE_CODE (t)) + { + case RECORD_TYPE: + if (TYPE_PTRMEMFUNC_P (t)) + { + tree r = build_ptrmemfunc_type + (tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, in_decl)); + return cp_build_type_variant (r, TYPE_READONLY (t), + TYPE_VOLATILE (t)); + } + + /* else fall through */ + case UNION_TYPE: + if (uses_template_parms (t)) + { + tree argvec; + tree context; + tree r; + + /* First, determine the context for the type we are looking + up. */ + if (TYPE_CONTEXT (t) != NULL_TREE) + context = tsubst_aggr_type (TYPE_CONTEXT (t), args, + in_decl, /*entering_scope=*/1); + else + context = NULL_TREE; + + /* Then, figure out what arguments are appropriate for the + type we are trying to find. For example, given: + + template struct S; + template void f(T, U) { S su; } + + and supposing that we are instantiating f, + then our ARGS will be {int, double}, but, when looking up + S we only want {double}. */ + argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl); + + r = lookup_template_class (t, argvec, in_decl, context, + entering_scope); + + return cp_build_type_variant (r, TYPE_READONLY (t), + TYPE_VOLATILE (t)); + } + else + /* This is not a template type, so there's nothing to do. */ + return t; + + default: + return tsubst (t, args, in_decl); + } +} + /* Take the tree structure T and replace template parameters used therein with the argument vector ARGS. IN_DECL is an associated decl for diagnostics. @@ -4226,52 +4483,9 @@ tsubst (t, args, in_decl) switch (TREE_CODE (t)) { case RECORD_TYPE: - if (TYPE_PTRMEMFUNC_P (t)) - { - tree r = build_ptrmemfunc_type - (tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, in_decl)); - return cp_build_type_variant (r, TYPE_READONLY (t), - TYPE_VOLATILE (t)); - } - - /* else fall through */ case UNION_TYPE: - if (uses_template_parms (t)) - { - tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl); - tree context; - tree r; + return tsubst_aggr_type (t, args, in_decl, /*entering_scope=*/0); - if (TYPE_CONTEXT (t) != NULL_TREE) - { - context = tsubst (TYPE_CONTEXT (t), args, in_decl); - - if (TREE_CODE (context) != FUNCTION_DECL - && TREE_CODE (context) != NAMESPACE_DECL) - { - /* For a member class template, we need all the - template arguments. */ - if (CLASSTYPE_IS_TEMPLATE (TYPE_CONTEXT (t))) - argvec = - add_to_template_args (CLASSTYPE_TI_ARGS (context), - argvec); - - if (CLASSTYPE_TEMPLATE_INFO (context)) - argvec = - complete_template_args (CLASSTYPE_TI_TEMPLATE (context), - argvec, 0); - } - } - else - context = NULL_TREE; - - r = lookup_template_class (t, argvec, in_decl, context); - - return cp_build_type_variant (r, TYPE_READONLY (t), - TYPE_VOLATILE (t)); - } - - /* else fall through */ case ERROR_MARK: case IDENTIFIER_NODE: case OP_IDENTIFIER: @@ -4287,7 +4501,8 @@ tsubst (t, args, in_decl) case ENUMERAL_TYPE: { - tree ctx = tsubst (TYPE_CONTEXT (t), args, in_decl); + tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, in_decl, + /*entering_scope=*/1); if (ctx == NULL_TREE || TREE_CODE (ctx) == NAMESPACE_DECL) return t; else if (ctx == current_function_decl) @@ -4345,19 +4560,9 @@ tsubst (t, args, in_decl) { tree arg = NULL_TREE; - if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)) - { - levels = TREE_VEC_LENGTH (args); - if (level <= levels) - arg = TREE_VEC_ELT - (TREE_VEC_ELT (args, level - 1), idx); - } - else - { - levels = 1; - if (level == 1) - arg = TREE_VEC_ELT (args, idx); - } + levels = TMPL_ARGS_DEPTH (args); + if (level <= levels) + arg = TMPL_ARG (args, level, idx); if (arg != NULL_TREE) { @@ -4385,7 +4590,8 @@ tsubst (t, args, in_decl) r = lookup_template_class (DECL_NAME (arg), argvec, in_decl, - DECL_CONTEXT (arg)); + DECL_CONTEXT (arg), + /*entering_scope=*/0); return cp_build_type_variant (r, TYPE_READONLY (t), TYPE_VOLATILE (t)); } @@ -4453,8 +4659,21 @@ tsubst (t, args, in_decl) if (!is_template_template_parm) { - /* We might already have an instance of this template. */ - spec = retrieve_specialization (t, args); + /* We might already have an instance of this template. + The ARGS are for the surrounding class type, so the + full args contain the tsubst'd args for the context, + plus the innermost args from the template decl. */ + tree tmpl_args = DECL_CLASS_TEMPLATE_P (t) + ? CLASSTYPE_TI_ARGS (TREE_TYPE (t)) + : DECL_TI_ARGS (DECL_RESULT (t)); + tree full_args = tsubst (tmpl_args, args, in_decl); + + /* tsubst_template_arg_vector doesn't copy the vector if + nothing changed. But, *something* should have + changed. */ + my_friendly_assert (full_args != tmpl_args, 0); + + spec = retrieve_specialization (t, full_args); if (spec != NULL_TREE) return spec; } @@ -4477,10 +4696,12 @@ tsubst (t, args, in_decl) return tmpl; } - DECL_CONTEXT (tmpl) = tsubst (DECL_CONTEXT (t), - args, in_decl); - DECL_CLASS_CONTEXT (tmpl) = tsubst (DECL_CLASS_CONTEXT (t), - args, in_decl); + DECL_CONTEXT (tmpl) + = tsubst_aggr_type (DECL_CONTEXT (t), args, in_decl, + /*entering_scope=*/1); + DECL_CLASS_CONTEXT (tmpl) + = tsubst_aggr_type (DECL_CLASS_CONTEXT (t), args, in_decl, + /*entering_scope=*/1); DECL_TEMPLATE_INFO (tmpl) = build_tree_list (t, args); if (TREE_CODE (decl) == TYPE_DECL) @@ -4489,6 +4710,7 @@ tsubst (t, args, in_decl) TREE_TYPE (tmpl) = new_type; CLASSTYPE_TI_TEMPLATE (new_type) = tmpl; DECL_RESULT (tmpl) = TYPE_MAIN_DECL (new_type); + DECL_TI_ARGS (tmpl) = CLASSTYPE_TI_ARGS (new_type); } else { @@ -4496,44 +4718,18 @@ tsubst (t, args, in_decl) DECL_RESULT (tmpl) = new_decl; DECL_TI_TEMPLATE (new_decl) = tmpl; TREE_TYPE (tmpl) = TREE_TYPE (new_decl); + DECL_TI_ARGS (tmpl) = DECL_TI_ARGS (new_decl); } - DECL_TEMPLATE_INSTANTIATIONS (tmpl) = NULL_TREE; SET_DECL_IMPLICIT_INSTANTIATION (tmpl); + DECL_TEMPLATE_INSTANTIATIONS (tmpl) = NULL_TREE; + DECL_TEMPLATE_SPECIALIZATIONS (tmpl) = NULL_TREE; /* The template parameters for this new template are all the template parameters for the old template, except the outermost level of parameters. */ - for (new_parms = &DECL_TEMPLATE_PARMS (tmpl), - parms = DECL_TEMPLATE_PARMS (t); - TREE_CHAIN (parms) != NULL_TREE; - new_parms = &(TREE_CHAIN (*new_parms)), - parms = TREE_CHAIN (parms)) - { - tree new_vec = - make_tree_vec (TREE_VEC_LENGTH (TREE_VALUE (parms))); - int i; - - for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i) - { - tree default_value = - TREE_PURPOSE (TREE_VEC_ELT (TREE_VALUE (parms), i)); - tree parm_decl = - TREE_VALUE (TREE_VEC_ELT (TREE_VALUE (parms), i)); - - TREE_VEC_ELT (new_vec, i) - = build_tree_list (tsubst (default_value, args, in_decl), - tsubst (parm_decl, args, in_decl)); - - } - - *new_parms = - tree_cons (build_int_2 (0, - TREE_INT_CST_HIGH - (TREE_PURPOSE (parms)) - 1), - new_vec, - NULL_TREE); - } + DECL_TEMPLATE_PARMS (tmpl) + = tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args); if (PRIMARY_TEMPLATE_P (t)) DECL_PRIMARY_TEMPLATE (tmpl) = tmpl; @@ -4542,12 +4738,6 @@ tsubst (t, args, in_decl) if (TREE_CODE (decl) == TYPE_DECL) return tmpl; - /* What should we do with the specializations of this member - template? Are they specializations of this new template, - or instantiations of the templates they previously were? - this new template? And where should their - DECL_TI_TEMPLATES point? */ - DECL_TEMPLATE_SPECIALIZATIONS (tmpl) = NULL_TREE; for (spec = DECL_TEMPLATE_SPECIALIZATIONS (t); spec != NULL_TREE; spec = TREE_CHAIN (spec)) @@ -4588,17 +4778,22 @@ tsubst (t, args, in_decl) no concern to us. */ continue; - spec_args = tsubst (DECL_TI_ARGS (fn), args, - in_decl); - new_fn = tsubst (DECL_RESULT (fn), args, - in_decl); - DECL_TEMPLATE_SPECIALIZATIONS (tmpl) = - perm_tree_cons (spec_args, new_fn, - DECL_TEMPLATE_SPECIALIZATIONS (tmpl)); + if (TREE_CODE (fn) != TEMPLATE_DECL) + /* A full specialization. There's no need to record + that here. */ + continue; + + spec_args = tsubst (DECL_TI_ARGS (fn), args, in_decl); + new_fn = tsubst (DECL_RESULT (most_general_template (fn)), + spec_args, in_decl); + DECL_TI_TEMPLATE (new_fn) = fn; + register_specialization (new_fn, tmpl, + innermost_args (spec_args)); } /* Record this partial instantiation. */ - register_specialization (tmpl, t, args); + register_specialization (tmpl, t, + DECL_TI_ARGS (DECL_RESULT (tmpl))); return tmpl; } @@ -4608,16 +4803,53 @@ tsubst (t, args, in_decl) tree r = NULL_TREE; tree ctx; tree argvec; - tree tmpl = NULL_TREE; + tree gen_tmpl; int member; + /* Nobody should be tsubst'ing into non-template functions. */ + my_friendly_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE, 0); + + if (TREE_CODE (DECL_TI_TEMPLATE (t)) == TEMPLATE_DECL) + { + tree spec; + + /* Calculate the most general template of which R is a + specialization, and the complete set of arguments used to + specialize R. */ + gen_tmpl = most_general_template (DECL_TI_TEMPLATE (t)); + argvec = tsubst (DECL_TI_ARGS (t), args, in_decl); + + /* Check to see if we already have this specialization. */ + spec = retrieve_specialization (gen_tmpl, argvec); + if (spec) + return spec; + } + else + { + /* This special case arises when we have something like this: + + template struct S { + friend void f(int, double); + }; + + Here, the DECL_TI_TEMPLATE for the friend declaration + will be a LOOKUP_EXPR. We are being called from + tsubst_friend_function, and we want only to create a + new decl (R) with appropriate types so that we can call + determine_specialization. */ + my_friendly_assert (TREE_CODE (DECL_TI_TEMPLATE (t)) + == LOOKUP_EXPR, 0); + gen_tmpl = NULL_TREE; + } + if (DECL_CLASS_SCOPE_P (t)) { if (DECL_NAME (t) == constructor_name (DECL_CONTEXT (t))) member = 2; else member = 1; - ctx = tsubst (DECL_CLASS_CONTEXT (t), args, t); + ctx = tsubst_aggr_type (DECL_CLASS_CONTEXT (t), args, t, + /*entering_scope=*/1); } else { @@ -4626,28 +4858,6 @@ tsubst (t, args, in_decl) } type = tsubst (type, args, in_decl); - /* If we are instantiating a specialization, get the other args. */ - if (DECL_TEMPLATE_INFO (t) != NULL_TREE) - { - tree spec; - - tmpl = DECL_TI_TEMPLATE (t); - - /* Start by getting the innermost args. */ - if (DECL_TEMPLATE_SPECIALIZATION (tmpl)) - argvec = args; - else - argvec = tsubst (DECL_TI_ARGS (t), args, in_decl); - - if (DECL_TEMPLATE_INFO (tmpl)) - argvec = complete_template_args (tmpl, argvec, 0); - - /* Do we already have this instantiation? */ - spec = retrieve_specialization (tmpl, argvec); - if (spec) - return spec; - } - /* We do NOT check for matching decls pushed separately at this point, as they may not represent instantiations of this template, and in any case are considered separate under the @@ -4659,7 +4869,7 @@ tsubst (t, args, in_decl) TREE_TYPE (r) = type; DECL_CONTEXT (r) - = tsubst (DECL_CONTEXT (t), args, t); + = tsubst_aggr_type (DECL_CONTEXT (t), args, t, /*entering_scope=*/1); DECL_CLASS_CONTEXT (r) = ctx; if (member && !strncmp (OPERATOR_TYPENAME_FORMAT, @@ -4693,122 +4903,48 @@ tsubst (t, args, in_decl) if (IDENTIFIER_OPNAME_P (DECL_NAME (r))) grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r)); - if (DECL_DESTRUCTOR_P (t)) - DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx); - else + /* Set up the DECL_TEMPLATE_INFO for R and compute its mangled + name. There's no need to do this in the special friend + case mentioned above where GEN_TMPL is NULL. */ + if (gen_tmpl) { - /* Instantiations of template functions must be mangled - specially, in order to conform to 14.5.5.1 - [temp.over.link]. We use in_decl below rather than - DECL_TI_TEMPLATE (r) because the latter is set to - NULL_TREE in instantiate_decl. */ - tree tmpl; - tree arg_types; - - if (DECL_TEMPLATE_INFO (r)) - tmpl = DECL_TI_TEMPLATE (r); - else - tmpl = in_decl; - - /* tmpl will be NULL if this is a specialization of a - member function of a template class. */ - if (name_mangling_version < 1 - || tmpl == NULL_TREE - || (member && !is_member_template (tmpl) - && !DECL_TEMPLATE_INFO (tmpl))) + DECL_TEMPLATE_INFO (r) + = perm_tree_cons (gen_tmpl, argvec, NULL_TREE); + SET_DECL_IMPLICIT_INSTANTIATION (r); + register_specialization (r, gen_tmpl, argvec); + + /* Set the mangled name for R. */ + if (DECL_DESTRUCTOR_P (t)) + DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx); + else { - arg_types = TYPE_ARG_TYPES (type); - if (member && TREE_CODE (type) == FUNCTION_TYPE) - arg_types = hash_tree_chain - (build_pointer_type (DECL_CONTEXT (r)), - arg_types); + /* Instantiations of template functions must be mangled + specially, in order to conform to 14.5.5.1 + [temp.over.link]. */ + tree tmpl = DECL_TI_TEMPLATE (t); - DECL_ASSEMBLER_NAME (r) - = build_decl_overload (DECL_NAME (r), arg_types, - member); - } - else - { - tree tparms; - tree targs; - - if (!DECL_TEMPLATE_SPECIALIZATION (tmpl)) - { - /* We pass the outermost template parameters to - build_template_decl_overload, since the innermost - template parameters are still just template - parameters; there are no corresponding subsitution - arguments. Levels of parms that have been bound - before are not represented in DECL_TEMPLATE_PARMS. */ - tparms = DECL_TEMPLATE_PARMS (tmpl); - while (tparms && TREE_CHAIN (tparms) != NULL_TREE) - tparms = TREE_CHAIN (tparms); - - targs = innermost_args (args, 0); - } + /* TMPL will be NULL if this is a specialization of a + member function of a template class. */ + if (name_mangling_version < 1 + || tmpl == NULL_TREE + || (member && !is_member_template (tmpl) + && !DECL_TEMPLATE_INFO (tmpl))) + set_mangled_name_for_decl (r); else - { - /* If the template is a specialization, then it is - a member template specialization. We have - something like: - - template struct S { - template void f(); - template <> void f<7>(); - }; - - and now we are forming S::f<7>. - Therefore, the template parameters of interest - are those that are specialized by the template - (i.e., the int), not those we are using to - instantiate the template, i.e. the double. */ - tparms = DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (tmpl)); - targs = DECL_TI_ARGS (tmpl); - } - - my_friendly_assert (tparms != NULL_TREE - && TREE_CODE (tparms) == TREE_LIST, - 0); - tparms = TREE_VALUE (tparms); - - arg_types = TYPE_ARG_TYPES (TREE_TYPE (tmpl)); - if (member && TREE_CODE (type) == FUNCTION_TYPE) - arg_types = hash_tree_chain - (build_pointer_type (DECL_CONTEXT (r)), - arg_types); - - DECL_ASSEMBLER_NAME (r) - = build_template_decl_overload - (r, arg_types, TREE_TYPE (TREE_TYPE (tmpl)), - tparms, targs, member); + set_mangled_name_for_template_decl (r); } + + DECL_RTL (r) = 0; + make_decl_rtl (r, NULL_PTR, 1); + + /* Like grokfndecl. If we don't do this, pushdecl will + mess up our TREE_CHAIN because it doesn't find a + previous decl. Sigh. */ + if (member + && (IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r)) + == NULL_TREE)) + SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r); } - DECL_RTL (r) = 0; - make_decl_rtl (r, NULL_PTR, 1); - - if (DECL_TEMPLATE_INFO (t) != NULL_TREE) - { - DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE); - - /* If we're not using ANSI overloading, then we might have - called duplicate_decls above, and gotten back an - preexisting version of this function. We treat such a - function as a specialization. Otherwise, we cleared - both TREE_STATIC and DECL_TEMPLATE_SPECIALIZATION, so - this condition will be false. */ - if (TREE_STATIC (r) || DECL_TEMPLATE_SPECIALIZATION (r)) - SET_DECL_TEMPLATE_SPECIALIZATION (r); - else - SET_DECL_IMPLICIT_INSTANTIATION (r); - - register_specialization (r, tmpl, argvec); - } - - /* Like grokfndecl. If we don't do this, pushdecl will mess up our - TREE_CHAIN because it doesn't find a previous decl. Sigh. */ - if (member - && IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r)) == NULL_TREE) - SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r); return r; } @@ -4861,18 +4997,25 @@ tsubst (t, args, in_decl) case VAR_DECL: { tree r; - tree ctx = tsubst_copy (DECL_CONTEXT (t), args, in_decl); - - /* Do we already have this instantiation? */ - if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)) - { - tree tmpl = DECL_TI_TEMPLATE (t); - tree decls = DECL_TEMPLATE_INSTANTIATIONS (tmpl); + tree argvec; + tree gen_tmpl; + tree spec; + tree tmpl; + tree ctx = tsubst_aggr_type (DECL_CONTEXT (t), args, in_decl, + /*entering_scope=*/1); + + /* Nobody should be tsubst'ing into non-template variables. */ + my_friendly_assert (DECL_LANG_SPECIFIC (t) + && DECL_TEMPLATE_INFO (t) != NULL_TREE, 0); - for (; decls; decls = TREE_CHAIN (decls)) - if (DECL_CONTEXT (TREE_VALUE (decls)) == ctx) - return TREE_VALUE (decls); - } + /* 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, in_decl); + spec = retrieve_specialization (gen_tmpl, argvec); + + if (spec) + return spec; r = copy_node (t); TREE_TYPE (r) = type; @@ -4884,26 +5027,15 @@ tsubst (t, args, in_decl) /* Don't try to expand the initializer until someone tries to use this variable; otherwise we run into circular dependencies. */ DECL_INITIAL (r) = NULL_TREE; - DECL_RTL (r) = 0; DECL_SIZE (r) = 0; + copy_lang_decl (r); + DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r); - if (DECL_LANG_SPECIFIC (r)) - { - copy_lang_decl (r); - DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r); - } - - if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)) - { - tree tmpl = DECL_TI_TEMPLATE (t); - tree *declsp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl); - tree argvec = tsubst (DECL_TI_ARGS (t), args, in_decl); + DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE); + SET_DECL_IMPLICIT_INSTANTIATION (r); + register_specialization (r, gen_tmpl, argvec); - DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE); - *declsp = perm_tree_cons (argvec, r, *declsp); - SET_DECL_IMPLICIT_INSTANTIATION (r); - } TREE_CHAIN (r) = NULL_TREE; if (TREE_CODE (type) == VOID_TYPE) cp_error_at ("instantiation of `%D' as type void", r); @@ -5136,7 +5268,8 @@ tsubst (t, args, in_decl) case TYPENAME_TYPE: { - tree ctx = tsubst (TYPE_CONTEXT (t), args, in_decl); + tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, in_decl, + /*entering_scope=*/1); tree f = tsubst_copy (TYPENAME_TYPE_FULLNAME (t), args, in_decl); f = make_typename_type (ctx, f); return cp_build_type_variant @@ -5234,7 +5367,8 @@ tsubst_copy (t, args, in_decl) if (TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL) return lookup_name (DECL_NAME (t), 0); - ctx = tsubst (DECL_CONTEXT (t), args, in_decl); + ctx = tsubst_aggr_type (DECL_CONTEXT (t), args, in_decl, + /*entering_scope=*/1); if (ctx != DECL_CONTEXT (t)) return lookup_field (ctx, DECL_NAME (t), 0, 0); } @@ -5709,58 +5843,77 @@ tsubst_expr (t, args, in_decl) return NULL_TREE; } +/* Instantiate the indicated variable of function template TMPL with + the template arguments in TARG_PTR. */ + tree instantiate_template (tmpl, targ_ptr) tree tmpl, targ_ptr; { tree fndecl; + tree gen_tmpl; + tree spec; int i, len; struct obstack *old_fmp_obstack; extern struct obstack *function_maybepermanent_obstack; + tree inner_args; if (tmpl == error_mark_node) return error_mark_node; my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283); - /* Check to see if we already have this specialization. This does work - for member template specializations; the list is set up from the - tsubst TEMPLATE_DECL case when the containing class is instantiated. */ - if (DECL_FUNCTION_TEMPLATE_P (tmpl)) + /* Check to see if we already have this specialization. */ + spec = retrieve_specialization (tmpl, targ_ptr); + if (spec != NULL_TREE) + return spec; + + if (DECL_TEMPLATE_INFO (tmpl)) { - tree spec = retrieve_specialization (tmpl, targ_ptr); - + /* The TMPL is a partial instantiation. To get a full set of + arguments we must add the arguments used to perform the + partial instantiation. */ + targ_ptr = add_outermost_template_args (DECL_TI_ARGS (tmpl), + targ_ptr); + gen_tmpl = most_general_template (tmpl); + + /* Check to see if we already have this specialization. */ + spec = retrieve_specialization (gen_tmpl, targ_ptr); if (spec != NULL_TREE) return spec; } + else + gen_tmpl = tmpl; push_obstacks (&permanent_obstack, &permanent_obstack); old_fmp_obstack = function_maybepermanent_obstack; function_maybepermanent_obstack = &permanent_obstack; - len = DECL_NTPARMS (tmpl); - + len = DECL_NTPARMS (gen_tmpl); + inner_args = innermost_args (targ_ptr); i = len; while (i--) { - tree t = TREE_VEC_ELT (targ_ptr, i); + tree t = TREE_VEC_ELT (inner_args, i); if (TREE_CODE_CLASS (TREE_CODE (t)) == 't') { tree nt = target_type (t); if (IS_AGGR_TYPE (nt) && decl_function_context (TYPE_MAIN_DECL (nt))) { cp_error ("type `%T' composed from a local class is not a valid template-argument", t); - cp_error (" trying to instantiate `%D'", tmpl); + cp_error (" trying to instantiate `%D'", gen_tmpl); fndecl = error_mark_node; goto out; } } - TREE_VEC_ELT (targ_ptr, i) = copy_to_permanent (t); } targ_ptr = copy_to_permanent (targ_ptr); /* substitute template parameters */ - fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr, tmpl); + fndecl = tsubst (DECL_RESULT (gen_tmpl), targ_ptr, gen_tmpl); + /* The DECL_TI_TEMPLATE should always be the immediate parent + template, not the most general template. */ + DECL_TI_TEMPLATE (fndecl) = tmpl; if (flag_external_templates) add_pending_template (fndecl); @@ -6682,15 +6835,11 @@ more_specialized (pat1, pat2, explicit_args) targs = get_bindings_overload (pat1, pat2, explicit_args); if (targs) - { - --winner; - } + --winner; targs = get_bindings_overload (pat2, pat1, explicit_args); if (targs) - { - ++winner; - } + ++winner; return winner; } @@ -6708,15 +6857,13 @@ more_specialized_class (pat1, pat2) tree targs; int winner = 0; - targs = get_class_bindings - (TREE_VALUE (pat1), TREE_PURPOSE (pat1), - TREE_PURPOSE (pat2), NULL_TREE); + targs = get_class_bindings (TREE_VALUE (pat1), TREE_PURPOSE (pat1), + TREE_PURPOSE (pat2)); if (targs) --winner; - targs = get_class_bindings - (TREE_VALUE (pat2), TREE_PURPOSE (pat2), - TREE_PURPOSE (pat1), NULL_TREE); + targs = get_class_bindings (TREE_VALUE (pat2), TREE_PURPOSE (pat2), + TREE_PURPOSE (pat1)); if (targs) ++winner; @@ -6771,8 +6918,7 @@ get_bindings_real (fn, decl, explicit_args, check_rettype) if (check_rettype) { /* Check to see that the resulting return type is also OK. */ - tree t = tsubst (TREE_TYPE (TREE_TYPE (fn)), - complete_template_args (fn, targs, 1), + tree t = tsubst (TREE_TYPE (TREE_TYPE (fn)), targs, NULL_TREE); if (!comptypes (t, TREE_TYPE (TREE_TYPE (decl)), 1)) @@ -6800,18 +6946,29 @@ get_bindings_overload (fn, decl, explicit_args) return get_bindings_real (fn, decl, explicit_args, 0); } +/* Return the innermost template arguments that, when applied to a + template specialization whose innermost template parameters are + TPARMS, and whose specialization arguments are ARGS, yield the + ARGS. + + For example, suppose we have: + + template struct S {}; + template struct S {}; + + Then, suppose we want to get `S'. The TPARMS will be + {T}, the PARMS will be {T*, int} and the ARGS will be {double*, + int}. The resulting vector will be {double}, indicating that `T' + is bound to `double'. */ + static tree -get_class_bindings (tparms, parms, args, outer_args) - tree tparms, parms, args, outer_args; +get_class_bindings (tparms, parms, args) + tree tparms, parms, args; { int i, ntparms = TREE_VEC_LENGTH (tparms); tree vec = make_temp_vec (ntparms); - if (outer_args) - { - tparms = tsubst (tparms, outer_args, NULL_TREE); - parms = tsubst (parms, outer_args, NULL_TREE); - } + args = innermost_args (args); for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) { @@ -6841,27 +6998,25 @@ tree most_specialized (fns, decl, explicit_args) tree fns, decl, explicit_args; { - tree fn, champ, args, *p; + tree candidates = NULL_TREE; + tree fn, champ, args; int fate; - for (p = &fns; *p; ) + for (fn = fns; fn; fn = TREE_CHAIN (fn)) { - args = get_bindings (TREE_VALUE (*p), decl, explicit_args); + tree candidate = TREE_VALUE (fn); + + args = get_bindings (candidate, decl, explicit_args); if (args) - { - p = &TREE_CHAIN (*p); - } - else - *p = TREE_CHAIN (*p); + candidates = scratch_tree_cons (NULL_TREE, candidate, + candidates); } - if (! fns) + if (!candidates) return NULL_TREE; - fn = fns; - champ = TREE_VALUE (fn); - fn = TREE_CHAIN (fn); - for (; fn; fn = TREE_CHAIN (fn)) + champ = TREE_VALUE (candidates); + for (fn = TREE_CHAIN (candidates); fn; fn = TREE_CHAIN (fn)) { fate = more_specialized (champ, TREE_VALUE (fn), explicit_args); if (fate == 1) @@ -6878,7 +7033,7 @@ most_specialized (fns, decl, explicit_args) } } - for (fn = fns; fn && TREE_VALUE (fn) != champ; fn = TREE_CHAIN (fn)) + for (fn = candidates; fn && TREE_VALUE (fn) != champ; fn = TREE_CHAIN (fn)) { fate = more_specialized (champ, TREE_VALUE (fn), explicit_args); if (fate != 1) @@ -6888,21 +7043,50 @@ most_specialized (fns, decl, explicit_args) return champ; } -/* Return the most specialized of the class template specializations in - SPECS that can produce an instantiation matching ARGS. */ +/* If DECL is a specialization of some template, return the most + general such template. For example, given: + + template struct S { template void f(U); }; + + if TMPL is `template void S::f(U)' this will return + the full template. This function will not trace past partial + specializations, however. For example, given in addition: + + template struct S { template void f(U); }; + + if TMPL is `template void S::f(U)' this will return + `template template S::f(U)'. */ tree -most_specialized_class (specs, mainargs, outer_args) - tree specs, mainargs, outer_args; +most_general_template (decl) + tree decl; { - tree list = NULL_TREE, t, args, champ; + while (DECL_TEMPLATE_INFO (decl)) + decl = DECL_TI_TEMPLATE (decl); + + return decl; +} + +/* Return the most specialized of the class template specializations + of TMPL which can produce an instantiation matching ARGS, or + error_mark_node if the choice is ambiguous. */ + +tree +most_specialized_class (tmpl, args) + tree tmpl; + tree args; +{ + tree list = NULL_TREE; + tree t; + tree champ; int fate; - for (t = specs; t; t = TREE_CHAIN (t)) + tmpl = most_general_template (tmpl); + for (t = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); t; t = TREE_CHAIN (t)) { - args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), - mainargs, outer_args); - if (args) + tree spec_args + = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args); + if (spec_args) { list = decl_tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list); TREE_TYPE (list) = TREE_TYPE (t); @@ -7108,9 +7292,10 @@ do_type_instantiation (t, storage) } } -/* Given a function DECL, which is a specialization of TEMP, modify - DECL to be a re-instantiation of TEMPL with the same template - arguments. +/* Given a function DECL, which is a specialization of TMPL, modify + DECL to be a re-instantiation of TMPL with the same template + arguments. TMPL should be the template into which tsubst'ing + should occur for DECL, not the most general template. One reason for doing this is a scenario like this: @@ -7136,18 +7321,27 @@ regenerate_decl_from_template (decl, tmpl) tree save_ti; tree code_pattern; tree new_decl; + tree gen_tmpl; + int unregistered; args = DECL_TI_ARGS (decl); code_pattern = DECL_TEMPLATE_RESULT (tmpl); - /* Trick tsubst into giving us a new decl. CODE_PATTERN must be the - most distant ancestor of DECL, since that's the one that will - actually be altered by a redefinition. */ - save_ti = DECL_TEMPLATE_INFO (code_pattern); - DECL_TEMPLATE_INFO (code_pattern) = NULL_TREE; + /* Unregister the specialization so that when we tsubst we will not + just return DECL. We don't have to unregister DECL from TMPL + because if would only be registered there if it were a partial + instantiation of a specialization, which it isn't: it's a full + instantiation. */ + gen_tmpl = most_general_template (tmpl); + unregistered = unregister_specialization (decl, gen_tmpl); + + /* If the DECL was not unregistered then something peculiar is + happening: we created a specialization but did not call + register_specialization for it. */ + my_friendly_assert (unregistered, 0); + + /* Do the substitution to get the new declaration. */ new_decl = tsubst (code_pattern, args, NULL_TREE); - SET_DECL_IMPLICIT_INSTANTIATION (new_decl); - DECL_TEMPLATE_INFO (code_pattern) = save_ti; if (TREE_CODE (decl) == VAR_DECL) { @@ -7160,21 +7354,29 @@ regenerate_decl_from_template (decl, tmpl) } if (TREE_CODE (decl) == FUNCTION_DECL) - { - /* Convince duplicate_decls to use the DECL_ARGUMENTS from the - new decl. */ - DECL_INITIAL (new_decl) = error_mark_node; - - if (DECL_TEMPLATE_SPECIALIZATION (new_decl) - && !DECL_TEMPLATE_INFO (new_decl)) - /* Set up the information about what is being specialized. */ - DECL_TEMPLATE_INFO (new_decl) = DECL_TEMPLATE_INFO (decl); - } - + /* Convince duplicate_decls to use the DECL_ARGUMENTS from the + new decl. */ + DECL_INITIAL (new_decl) = error_mark_node; + + /* The immediate parent of the new template is still whatever it was + before, even though tsubst sets DECL_TI_TEMPLATE up as the most + general template. We also reset the DECL_ASSEMBLER_NAME since + tsubst always calculates the name as if the function in question + were really a template instance, and sometimes, with friend + functions, this is not so. See tsubst_friend_function for + details. */ + DECL_TI_TEMPLATE (new_decl) = DECL_TI_TEMPLATE (decl); + DECL_ASSEMBLER_NAME (new_decl) = DECL_ASSEMBLER_NAME (decl); + DECL_RTL (new_decl) = DECL_RTL (decl); + + /* Call duplicate decls to merge the old and new declarations. */ duplicate_decls (new_decl, decl); if (TREE_CODE (decl) == FUNCTION_DECL) DECL_INITIAL (new_decl) = NULL_TREE; + + /* Now, re-register the specialization. */ + register_specialization (decl, gen_tmpl, args); } /* Produce the definition of D, a _DECL generated from a template. */ @@ -7183,17 +7385,41 @@ tree instantiate_decl (d) tree d; { - tree ti = DECL_TEMPLATE_INFO (d); - tree tmpl = TI_TEMPLATE (ti); - tree args = TI_ARGS (ti); + tree tmpl = DECL_TI_TEMPLATE (d); + tree args = DECL_TI_ARGS (d); tree td; - tree decl_pattern, code_pattern; + tree code_pattern; + tree spec; + tree gen_tmpl; int nested = in_function_p (); - int d_defined; int pattern_defined; int line = lineno; char *file = input_filename; + /* This function should only be used to instantiate templates for + functions and static member variables. */ + my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL + || TREE_CODE (d) == VAR_DECL, 0); + + if ((TREE_CODE (d) == FUNCTION_DECL && DECL_INITIAL (d)) + || (TREE_CODE (d) == VAR_DECL && !DECL_IN_AGGR_P (d))) + /* D has already been instantiated. */ + return d; + + /* If we already have a specialization of this declaration, then + there's no reason to instantiate it. Note that + retrieve_specialization gives us both instantiations and + specializations, so we must explicitly check + DECL_TEMPLATE_SPECIALIZATION. */ + gen_tmpl = most_general_template (tmpl); + spec = retrieve_specialization (gen_tmpl, args); + if (spec != NULL_TREE && DECL_TEMPLATE_SPECIALIZATION (spec)) + return spec; + + /* This needs to happen before any tsubsting. */ + if (! push_tinst_level (d)) + return d; + for (td = tmpl; DECL_TEMPLATE_INSTANTIATION (td) /* This next clause handles friend templates defined inside @@ -7205,38 +7431,12 @@ instantiate_decl (d) ) td = DECL_TI_TEMPLATE (td); - /* In the case of a member template, decl_pattern is the partially - instantiated declaration (in the instantiated class), and code_pattern - is the original template definition. */ - decl_pattern = DECL_TEMPLATE_RESULT (tmpl); code_pattern = DECL_TEMPLATE_RESULT (td); if (TREE_CODE (d) == FUNCTION_DECL) - { - d_defined = (DECL_INITIAL (d) != NULL_TREE); - pattern_defined = (DECL_INITIAL (code_pattern) != NULL_TREE); - } + pattern_defined = (DECL_INITIAL (code_pattern) != NULL_TREE); else - { - d_defined = ! DECL_IN_AGGR_P (d); - pattern_defined = ! DECL_IN_AGGR_P (code_pattern); - } - - if (d_defined) - return d; - - if (TREE_CODE (d) == FUNCTION_DECL) - { - tree spec = retrieve_specialization (tmpl, args); - - if (spec != NULL_TREE - && DECL_TEMPLATE_SPECIALIZATION (spec)) - return spec; - } - - /* This needs to happen before any tsubsting. */ - if (! push_tinst_level (d)) - return d; + pattern_defined = ! DECL_IN_AGGR_P (code_pattern); push_to_top_level (); lineno = DECL_SOURCE_LINE (d); @@ -7481,3 +7681,148 @@ tsubst_enum (tag, args, field_chain) return newtag; } + +/* Set the DECL_ASSEMBLER_NAME for DECL, which is a FUNCTION_DECL that + is either an instantiation or specialization of a template + function. */ + +static void +set_mangled_name_for_template_decl (decl) + tree decl; +{ + tree saved_namespace; + tree context; + tree fn_type; + tree ret_type; + tree parm_types; + tree tparms; + tree targs; + tree tmpl; + int parm_depth; + + my_friendly_assert (TREE_CODE (decl) == FUNCTION_DECL, 0); + my_friendly_assert (DECL_TEMPLATE_INFO (decl) != NULL_TREE, 0); + + /* The names of template functions must be mangled so as to indicate + what template is being specialized with what template arguments. + For example, each of the following three functions must get + different mangled names: + + void f(int); + template <> void f<7>(int); + template <> void f<8>(int); */ + + targs = DECL_TI_ARGS (decl); + if (uses_template_parms (targs)) + /* This DECL is for a partial instantiation. There's no need to + mangle the name of such an entity. */ + return; + + tmpl = most_general_template (DECL_TI_TEMPLATE (decl)); + tparms = DECL_TEMPLATE_PARMS (tmpl); + parm_depth = TMPL_PARMS_DEPTH (tparms); + + /* There should be as many levels of arguments as there are levels + of parameters. */ + my_friendly_assert (parm_depth == TMPL_ARGS_DEPTH (targs), 0); + + /* We now compute the PARMS and RET_TYPE to give to + build_decl_overload_real. The PARMS and RET_TYPE are the + parameter and return types of the template, after all but the + innermost template arguments have been substituted, not the + parameter and return types of the function DECL. For example, + given: + + template T f(T); + + both PARMS and RET_TYPE should be `T' even if DECL is `int f(int)'. + A more subtle example is: + + template struct S { template void f(T, U); } + + Here, if DECL is `void S::f(int, double)', PARMS should be + {int, U}. Thus, the args that we want to subsitute into the + return and parameter type for the function are those in TARGS, + with the innermost level omitted. */ + fn_type = TREE_TYPE (tmpl); + if (DECL_STATIC_FUNCTION_P (decl)) + context = DECL_CLASS_CONTEXT (decl); + + if (parm_depth == 1) + /* No substitution is necessary. */ + ; + else + { + int i; + tree partial_args; + + /* Replace the innermost level of the TARGS with NULL_TREEs to + let tsubst know not to subsitute for those parameters. */ + partial_args = make_temp_vec (TREE_VEC_LENGTH (targs)); + for (i = 1; i < TMPL_ARGS_DEPTH (targs); ++i) + SET_TMPL_ARGS_LEVEL (partial_args, i, + TMPL_ARGS_LEVEL (targs, i)); + SET_TMPL_ARGS_LEVEL (partial_args, + TMPL_ARGS_DEPTH (targs), + make_temp_vec (DECL_NTPARMS (tmpl))); + + /* Now, do the (partial) substitution to figure out the + appropriate function type. */ + fn_type = tsubst (fn_type, partial_args, NULL_TREE); + if (DECL_STATIC_FUNCTION_P (decl)) + context = tsubst (context, partial_args, NULL_TREE); + + /* Substitute into the template parameters to obtain the real + innermost set of parameters. This step is important if the + innermost set of template parameters contains value + parameters whose types depend on outer template parameters. */ + TREE_VEC_LENGTH (partial_args)--; + tparms = tsubst_template_parms (tparms, partial_args); + } + + /* Now, get the innermost parameters and arguments, and figure out + the parameter and return types. */ + tparms = INNERMOST_TEMPLATE_PARMS (tparms); + targs = innermost_args (targs); + ret_type = TREE_TYPE (fn_type); + parm_types = TYPE_ARG_TYPES (fn_type); + + /* For a static member function, we generate a fake `this' pointer, + for the purposes of mangling. This indicates of which class the + function is a member. Because of: + + [class.static] + + There shall not be a static and a nonstatic member function + with the same name and the same parameter types + + we don't have to worry that this will result in a clash with a + non-static member function. */ + if (DECL_STATIC_FUNCTION_P (decl)) + parm_types = hash_tree_chain (build_pointer_type (context), parm_types); + + /* There should be the same number of template parameters as + template arguments. */ + my_friendly_assert (TREE_VEC_LENGTH (tparms) == TREE_VEC_LENGTH (targs), + 0); + + /* If the template is in a namespace, we need to put that into the + mangled name. Unfortunately, build_decl_overload_real does not + get the decl to mangle, so it relies on the current + namespace. Therefore, we set that here temporarily. */ + my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 980702); + saved_namespace = current_namespace; + current_namespace = CP_DECL_CONTEXT (decl); + + /* Actually set the DCL_ASSEMBLER_NAME. */ + DECL_ASSEMBLER_NAME (decl) + = build_decl_overload_real (DECL_NAME (decl), parm_types, ret_type, + tparms, targs, + DECL_FUNCTION_MEMBER_P (decl) + + DECL_CONSTRUCTOR_P (decl)); + + /* Restore the previously active namespace. */ + current_namespace = saved_namespace; +} + + diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 50685129e08..a6d03e1a256 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1235,18 +1235,7 @@ begin_class_definition (t) push_template_decl (TYPE_STUB_DECL (t)); pushclass (t, 0); TYPE_BEING_DEFINED (t) = 1; - if (IS_AGGR_TYPE (t) && CLASSTYPE_USE_TEMPLATE (t)) - { - if (CLASSTYPE_IMPLICIT_INSTANTIATION (t) - && TYPE_SIZE (t) == NULL_TREE) - { - SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t); - if (processing_template_decl) - push_template_decl (TYPE_MAIN_DECL (t)); - } - else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t)) - cp_error ("specialization after instantiation of `%T'", t); - } + maybe_process_partial_specialization (t); /* Reset the interface data, at the earliest possible moment, as it might have been set via a class foo; before. */ @@ -1378,6 +1367,15 @@ finish_member_class_template (parms, types) tree parms; tree types; { + tree t; + + /* If there are declared, but undefined, partial specializations + mixed in with the typespecs they will not yet have passed through + maybe_process_partial_specialization, so we do that here. */ + for (t = types; t != NULL_TREE; t = TREE_CHAIN (t)) + if (IS_AGGR_TYPE_CODE (TREE_CODE (TREE_VALUE (t)))) + maybe_process_partial_specialization (TREE_VALUE (t)); + note_list_got_semicolon (types); grok_x_components (types, NULL_TREE); if (TYPE_CONTEXT (TREE_VALUE (types)) != current_class_type) @@ -1391,3 +1389,37 @@ finish_member_class_template (parms, types) component_decls. */ return NULL_TREE; } + +/* Finish processsing a complete template declaration. The PARMS are + the template parameters. */ + +void +finish_template_decl (parms) + tree parms; +{ + if (parms) + end_template_decl (); + else + end_specialization (); +} + +/* Finish processing a a template-id (which names a type) of the form + NAME < ARGS >. Return the TYPE_DECL for the type named by the + template-id. If ENTERING_SCOPE is non-zero we are about to enter + the scope of template-id indicated. */ + +tree +finish_template_type (name, args, entering_scope) + tree name; + tree args; + int entering_scope; +{ + tree decl; + + decl = lookup_template_class (name, args, + NULL_TREE, NULL_TREE, entering_scope); + if (decl != error_mark_node) + decl = TYPE_STUB_DECL (decl); + + return decl; +} diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index a1c1394d17b..0ae703b2d32 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -587,7 +587,10 @@ common_type (t1, t2) else if (binfo_or_else (t2, t1)) return build_type_attribute_variant (t2, attributes); else - compiler_error ("common_type called with uncommon aggregate types"); + { + compiler_error ("common_type called with uncommon aggregate types"); + return error_mark_node; + } case METHOD_TYPE: if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2))) diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash56.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash56.C index 7b470678a78..b5e997cc6ee 100644 --- a/gcc/testsuite/g++.old-deja/g++.brendan/crash56.C +++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash56.C @@ -1,5 +1,7 @@ // Build don't link: // GROUPS passed old-abort +// Special g++ Options: + const bool FALSE = 0; const bool TRUE = 1; class ListDProto { @@ -41,8 +43,8 @@ public: enum Action { NORMAL, REMOVE_CURRENT }; Vix first() const; void first(Vix& x) const; - void next(Vix& x) const;// ERROR - candidate for call - void next(Vix& x, Action a = NORMAL);// ERROR - list of candidates + void next(Vix& x) const; + void next(Vix& x, Action a = NORMAL); Vix last() const; void last(Vix& x) const; void prev(Vix& x) const; diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash8.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash8.C index 2b5dece65c1..8990c465677 100644 --- a/gcc/testsuite/g++.old-deja/g++.brendan/crash8.C +++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash8.C @@ -6,7 +6,7 @@ class Elvis } ; template -class Elvis<0>// ERROR - .* -{ // ERROR - +class Elvis<0> +{ // ERROR - incorrect number of parameters int geta() { return a ; } } ; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash11.C b/gcc/testsuite/g++.old-deja/g++.pt/crash11.C new file mode 100644 index 00000000000..30c72a679f2 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/crash11.C @@ -0,0 +1,13 @@ +// Build don't link: + +class A +{ + class A_impl; + public: + A(){} +}; + + +template class A::A_impl +{ // ERROR - does not declare a template +}; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash13.C b/gcc/testsuite/g++.old-deja/g++.pt/crash13.C new file mode 100644 index 00000000000..f3de38e6be1 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/crash13.C @@ -0,0 +1,6 @@ +// Build don't link: + +template struct A {}; +template struct A; // ERROR - does not specialize args +template const struct A; // ERROR - parse error +template template A; // ERROR - .* diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash14.C b/gcc/testsuite/g++.old-deja/g++.pt/crash14.C new file mode 100644 index 00000000000..f698316b511 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/crash14.C @@ -0,0 +1,5 @@ +// Build don't link: + +template struct A {}; +template struct A; +A ai; // ERROR - incomplete type diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash8.C b/gcc/testsuite/g++.old-deja/g++.pt/crash8.C new file mode 100644 index 00000000000..2fd687ac819 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/crash8.C @@ -0,0 +1,34 @@ +// Build don't link: + +template +class TestClass1 { +public: + TestClass1() { } +}; + +template +class TestClass2 { +public: + TestClass2() { } + T operator()(int) { } +}; + +template +void doit(T x) { + TestClass1 q1; + q1 = TestClass1(); + TestClass2 q2; + q2 = TestClass2(); + + TestClass1 p1; + p1 = TestClass1(); // ERROR - template used as expression + + TestClass2 p2; + p2 = TestClass2(); // ERROR - template used as expression +} + +main() { + double x; + doit(x); +} + diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend21.C b/gcc/testsuite/g++.old-deja/g++.pt/friend21.C index c724f8c992f..c89fe1dc1d2 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/friend21.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/friend21.C @@ -13,7 +13,7 @@ template class B template class C { template - friend class A; + friend class A; static int i; }; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend22.C b/gcc/testsuite/g++.old-deja/g++.pt/friend22.C new file mode 100644 index 00000000000..ed459d71fe2 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/friend22.C @@ -0,0 +1,10 @@ +// Build don't link: + +template +struct S +{ + template + friend class S; +}; + +template struct S; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend23.C b/gcc/testsuite/g++.old-deja/g++.pt/friend23.C new file mode 100644 index 00000000000..efb24b1d551 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/friend23.C @@ -0,0 +1,10 @@ +// Build don't link: + +template // ERROR - original definition +struct S +{ + template + friend class S; +}; + +template struct S; // ERROR - redefinition of default arg diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend24.C b/gcc/testsuite/g++.old-deja/g++.pt/friend24.C new file mode 100644 index 00000000000..d312b3854ea --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/friend24.C @@ -0,0 +1,18 @@ +// Build don't link: + +template +struct S +{ + template + friend class S; + + void f(T); +}; + +template struct S; + +void g() +{ + S<> s; + s.f(3); +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend25.C b/gcc/testsuite/g++.old-deja/g++.pt/friend25.C new file mode 100644 index 00000000000..f93e73bc396 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/friend25.C @@ -0,0 +1,15 @@ +// Build don't link: + +template struct A; + +struct B +{ + template + friend class A; // ERROR - does not specialize any args +}; + +struct C +{ + template + friend class A; // ERROR - partial specialization +}; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend26.C b/gcc/testsuite/g++.old-deja/g++.pt/friend26.C new file mode 100644 index 00000000000..a426f8b775f --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/friend26.C @@ -0,0 +1,6 @@ +// Build don't link: + +struct S +{ + friend void f<>(int); // ERROR - does not match any template +}; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend27.C b/gcc/testsuite/g++.old-deja/g++.pt/friend27.C new file mode 100644 index 00000000000..0f11a49c060 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/friend27.C @@ -0,0 +1,7 @@ +// Build don't link: + +class S +{ + friend void f<>(int); // ERROR - does not match any template + int i; +}; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memclass13.C b/gcc/testsuite/g++.old-deja/g++.pt/memclass13.C new file mode 100644 index 00000000000..7eddc278b25 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/memclass13.C @@ -0,0 +1,16 @@ +// Build don't link: + +template +struct Inner; + +template +struct S +{ + template + struct Inner + { + }; +}; + + +S::Inner si; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memclass14.C b/gcc/testsuite/g++.old-deja/g++.pt/memclass14.C new file mode 100644 index 00000000000..ad1b2b4b5ac --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/memclass14.C @@ -0,0 +1,15 @@ +// Build don't link: + +template +struct Inner; + +struct S +{ + template + struct Inner + { + }; +}; + + +S::Inner si; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memclass15.C b/gcc/testsuite/g++.old-deja/g++.pt/memclass15.C new file mode 100644 index 00000000000..52f92bf5221 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/memclass15.C @@ -0,0 +1,27 @@ +// Build don't link: + +template +struct S1 +{ + template + struct S2 {}; + + template + void f(X, Y, Z) + { + S2 s2z; + } + + template + void g(X, Z) + { + S2 s2z; + } +}; + + +void h() +{ + S1 si; + si.g(3, 4); +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C b/gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C new file mode 100644 index 00000000000..e6f62cfa38d --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/memtemp77.C @@ -0,0 +1,25 @@ +extern "C" int strcmp(const char*, const char*); + +template +struct S3 +{ + template + static char* h(U); +}; + +template +template <> +char* S3::h(int) { return __PRETTY_FUNCTION__; } + +template <> +template <> +char* S3::h(int) { return __PRETTY_FUNCTION__; } + +int main() +{ + if (strcmp (S3::h(7), + "static char * S3::h(int)") == 0) + return 0; + else + return 1; +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp52.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp52.C index 3a0fb5941f3..fb841b96ea7 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/ttp52.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/ttp52.C @@ -12,7 +12,7 @@ class base // specialization template -class base > // ERROR - mymap<...> is not a template -{ // ERROR - Bad class name +class base > +{ // ERROR - type/value mismatch }; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename3.C b/gcc/testsuite/g++.old-deja/g++.pt/typename3.C index 4a8f05b08e3..0b19d54723e 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/typename3.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/typename3.C @@ -1,4 +1,5 @@ // Build don't link: +// Special g++ Options: template struct A diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename4.C b/gcc/testsuite/g++.old-deja/g++.pt/typename4.C index 67ac939b58a..6f9362fe8e7 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/typename4.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/typename4.C @@ -1,4 +1,5 @@ // Build don't link: +// Special g++ Options: template struct A diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename5.C b/gcc/testsuite/g++.old-deja/g++.pt/typename5.C index 202dadf12b6..e967d143f37 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/typename5.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/typename5.C @@ -1,4 +1,5 @@ // Build don't link: +// Special g++ Options: template struct A diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename6.C b/gcc/testsuite/g++.old-deja/g++.pt/typename6.C index 4a8f05b08e3..0b19d54723e 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/typename6.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/typename6.C @@ -1,4 +1,5 @@ // Build don't link: +// Special g++ Options: template struct A diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb125.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb125.C index b940f01237f..5faa28087c8 100644 --- a/gcc/testsuite/g++.old-deja/g++.robertl/eb125.C +++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb125.C @@ -7,7 +7,7 @@ void test (test_box *); // ERROR - illegal code class test_square { - friend void test (test_box *); + friend void test (test_box *); // ERROR - does not match } diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb49.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb49.C index eb69dfd0715..f41ead5313f 100644 --- a/gcc/testsuite/g++.old-deja/g++.robertl/eb49.C +++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb49.C @@ -1,5 +1,5 @@ // Build don't link: -// excess errors test - XFAIL *-*-* +// excess errors test // Here we declare ::S typedef struct s1 *S; -- 2.30.2