Commit 36a117a5 by Mark Mitchell Committed by Mark Mitchell

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
parent 0167ae91
1998-07-27 Mark Mitchell <mark@markmitchell.com>
* 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 <jason@yorick.cygnus.com> 1998-07-27 Jason Merrill <jason@yorick.cygnus.com>
* typeck2.c (build_functional_cast): Handle default-initialization. * typeck2.c (build_functional_cast): Handle default-initialization.
......
...@@ -215,7 +215,7 @@ parse.o : $(PARSE_C) $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h lex.h \ ...@@ -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) \ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
`echo $(PARSE_C) | sed 's,^\./,,'` `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_H) : $(PARSE_C)
$(PARSE_C) : $(srcdir)/parse.y $(PARSE_C) : $(srcdir)/parse.y
@echo $(CONFLICTS) @echo $(CONFLICTS)
......
...@@ -4458,49 +4458,21 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon) ...@@ -4458,49 +4458,21 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
/* Now, figure out which member templates we're specializing. */ /* Now, figure out which member templates we're specializing. */
for (x = specializations; x != NULL_TREE; x = TREE_CHAIN (x)) for (x = specializations; x != NULL_TREE; x = TREE_CHAIN (x))
{ {
tree spec_args;
tree fn;
int pending_specialization; 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 pending_specialization
= TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (fn)); = TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (x));
check_explicit_specialization check_explicit_specialization
(lookup_template_function (DECL_NAME (fn), spec_args), (lookup_template_function (DECL_NAME (x), DECL_TI_ARGS (x)),
fn, 0, 1 | (8 * pending_specialization)); x, 0, 1 | (8 * pending_specialization));
TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (fn)) = 0; TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (x)) = 0;
/* Now, the assembler name will be correct for fn, so we /* Now, the assembler name will be correct for fn, so we
make its RTL. */ make its RTL. */
DECL_RTL (fn) = 0;
make_decl_rtl (fn, NULL_PTR, 1);
if (x != fn)
{
DECL_RTL (x) = 0; DECL_RTL (x) = 0;
make_decl_rtl (x, NULL_PTR, 1); 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) if (current_class_type)
......
...@@ -27,7 +27,6 @@ Boston, MA 02111-1307, USA. */ ...@@ -27,7 +27,6 @@ Boston, MA 02111-1307, USA. */
/* Usage of TREE_LANG_FLAG_?: /* Usage of TREE_LANG_FLAG_?:
0: TREE_NONLOCAL_FLAG (in TREE_LIST or _TYPE). 0: TREE_NONLOCAL_FLAG (in TREE_LIST or _TYPE).
BINFO_MARKED (BINFO nodes). BINFO_MARKED (BINFO nodes).
TI_USES_TEMPLATE_PARMS.
COMPOUND_STMT_NO_SCOPE (in COMPOUND_STMT). COMPOUND_STMT_NO_SCOPE (in COMPOUND_STMT).
NEW_EXPR_USE_GLOBAL (in NEW_EXPR). NEW_EXPR_USE_GLOBAL (in NEW_EXPR).
DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR). DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR).
...@@ -1250,13 +1249,35 @@ struct lang_decl ...@@ -1250,13 +1249,35 @@ struct lang_decl
#define TI_TEMPLATE(NODE) (TREE_PURPOSE (NODE)) #define TI_TEMPLATE(NODE) (TREE_PURPOSE (NODE))
#define TI_ARGS(NODE) (TREE_VALUE (NODE)) #define TI_ARGS(NODE) (TREE_VALUE (NODE))
#define TI_SPEC_INFO(NODE) (TREE_CHAIN (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) #define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
/* TI_PENDING_SPECIALIZATION_FLAG on a template-info node indicates /* TI_PENDING_SPECIALIZATION_FLAG on a template-info node indicates
that the template is a specialization of a member template, but that the template is a specialization of a member template, but
that we don't yet know which one. */ that we don't yet know which one. */
#define TI_PENDING_SPECIALIZATION_FLAG(NODE) TREE_LANG_FLAG_1 (NODE) #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 <class T> struct S { template <class U> void f(U); }
the FUNCTION_DECL for S<int>::f<double> will have, as its
DECL_TI_TEMPLATE, `template <class U> S<int>::f<U>'.
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 <class T> struct S { friend void f<int>(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)) #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 DECL_TI_ARGS(NODE) TI_ARGS (DECL_TEMPLATE_INFO (NODE))
#define CLASSTYPE_TI_TEMPLATE(NODE) TI_TEMPLATE (CLASSTYPE_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)) #define CLASSTYPE_TI_ARGS(NODE) TI_ARGS (CLASSTYPE_TEMPLATE_INFO (NODE))
...@@ -1528,25 +1549,80 @@ extern int flag_new_for_scope; ...@@ -1528,25 +1549,80 @@ extern int flag_new_for_scope;
/* Accessor macros for C++ template decl nodes. */ /* Accessor macros for C++ template decl nodes. */
/* The DECL_TEMPLATE_PARMS are a list. The TREE_PURPOSE of each node /* The DECL_TEMPLATE_PARMS are a list. The TREE_PURPOSE of each node
indicates the level of the template parameters, with 1 being the is a INT_CST whose TREE_INT_CST_HIGH indicates the level of the
outermost set of template parameters. The TREE_VALUE is a vector, template parameters, with 1 being the outermost set of template
whose elements are the template parameters at each level. Each parameters. The TREE_VALUE is a vector, whose elements are the
element in the vector is a TREE_LIST, whose TREE_VALUE is a template parameters at each level. Each element in the vector is a
PARM_DECL (if the parameter is a non-type parameter), or a TREE_LIST, whose TREE_VALUE is a PARM_DECL (if the parameter is a
TYPE_DECL (if the parameter is a type parameter). The TREE_PURPOSE non-type parameter), or a TYPE_DECL (if the parameter is a type
is the default value, if any. The TEMPLATE_PARM_INDEX for the parameter). The TREE_PURPOSE is the default value, if any. The
parameter is avilable as the DECL_INITIAL (for a PARM_DECL) or as TEMPLATE_PARM_INDEX for the parameter is avilable as the
the TREE_TYPE (for a TYPE_DECL). */ 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_TEMPLATE_PARMS(NODE) DECL_ARGUMENTS(NODE)
#define DECL_INNERMOST_TEMPLATE_PARMS(NODE) \ #define DECL_INNERMOST_TEMPLATE_PARMS(NODE) \
INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (NODE)) INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (NODE))
#define DECL_NTPARMS(NODE) \ #define DECL_NTPARMS(NODE) \
TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (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. */ /* For function, method, class-data templates. */
#define DECL_TEMPLATE_RESULT(NODE) DECL_RESULT(NODE) #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 <class T> struct S1 {
template <class U> struct S2 {};
template <class U> struct S2<U*> {};
};
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 <class T> template
<class U> struct S1<T>::S2'.
This list is not used for function templates. */
#define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE) #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 <class T> struct S {
template <class U> void f(U);
template <> void f(T);
};
the `S<int>::f<int>(int)' function will appear on the
DECL_TEMPLATE_SPECIALIZATIONS list for both `template <class T>
template <class U> void S<T>::f(U)' and `template <class T> void
S<int>::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
<class T> struct S<T*, int>' 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) #define DECL_TEMPLATE_INJECT(NODE) DECL_INITIAL(NODE)
/* Nonzero for TEMPLATE_DECL nodes that represents template template /* Nonzero for TEMPLATE_DECL nodes that represents template template
...@@ -2649,7 +2725,9 @@ extern void do_inline_function_hair PROTO((tree, tree)); ...@@ -2649,7 +2725,9 @@ extern void do_inline_function_hair PROTO((tree, tree));
extern char *build_overload_name PROTO((tree, int, int)); extern char *build_overload_name PROTO((tree, int, int));
extern tree build_static_name PROTO((tree, tree)); extern tree build_static_name PROTO((tree, tree));
extern tree build_decl_overload PROTO((tree, tree, int)); 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_typename_overload PROTO((tree));
extern tree build_overload_with_type PROTO((tree, tree)); extern tree build_overload_with_type PROTO((tree, tree));
extern tree build_destructor_name PROTO((tree)); extern tree build_destructor_name PROTO((tree));
...@@ -2661,7 +2739,7 @@ extern void synthesize_method PROTO((tree)); ...@@ -2661,7 +2739,7 @@ extern void synthesize_method PROTO((tree));
extern tree get_id_2 PROTO((char *, tree)); extern tree get_id_2 PROTO((char *, tree));
/* in pt.c */ /* 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 PROTO ((tree, tree, tree));
extern tree tsubst_expr PROTO ((tree, tree, tree)); extern tree tsubst_expr PROTO ((tree, tree, tree));
extern tree tsubst_copy PROTO ((tree, tree, tree)); extern tree tsubst_copy PROTO ((tree, tree, tree));
...@@ -2684,7 +2762,7 @@ extern tree current_template_args PROTO((void)); ...@@ -2684,7 +2762,7 @@ extern tree current_template_args PROTO((void));
extern tree push_template_decl PROTO((tree)); extern tree push_template_decl PROTO((tree));
extern tree push_template_decl_real PROTO((tree, int)); extern tree push_template_decl_real PROTO((tree, int));
extern void redeclare_class_template PROTO((tree, tree)); 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 tree lookup_template_function PROTO((tree, tree));
extern int uses_template_parms PROTO((tree)); extern int uses_template_parms PROTO((tree));
extern tree instantiate_class_template PROTO((tree)); extern tree instantiate_class_template PROTO((tree));
...@@ -2708,8 +2786,6 @@ extern void begin_tree PROTO((void)); ...@@ -2708,8 +2786,6 @@ extern void begin_tree PROTO((void));
extern void end_tree PROTO((void)); extern void end_tree PROTO((void));
extern void add_maybe_template PROTO((tree, tree)); extern void add_maybe_template PROTO((tree, tree));
extern void pop_tinst_level PROTO((void)); 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 int more_specialized_class PROTO((tree, tree));
extern void do_pushlevel PROTO((void)); extern void do_pushlevel PROTO((void));
extern int is_member_template PROTO((tree)); extern int is_member_template PROTO((tree));
...@@ -2717,6 +2793,7 @@ extern int comp_template_parms PROTO((tree, tree)); ...@@ -2717,6 +2793,7 @@ extern int comp_template_parms PROTO((tree, tree));
extern int template_class_depth PROTO((tree)); extern int template_class_depth PROTO((tree));
extern int is_specialization_of PROTO((tree, tree)); extern int is_specialization_of PROTO((tree, tree));
extern int comp_template_args 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_specialization;
extern int processing_explicit_instantiation; extern int processing_explicit_instantiation;
...@@ -2839,6 +2916,8 @@ extern tree finish_class_definition PROTO((tree, tree, tree, int)); ...@@ -2839,6 +2916,8 @@ extern tree finish_class_definition PROTO((tree, tree, tree, int));
extern void finish_default_args PROTO((void)); extern void finish_default_args PROTO((void));
extern void begin_inline_definitions PROTO((void)); extern void begin_inline_definitions PROTO((void));
extern tree finish_member_class_template PROTO((tree, tree)); 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 */ /* in sig.c */
extern tree build_signature_pointer_type PROTO((tree, int, int)); extern tree build_signature_pointer_type PROTO((tree, int, int));
......
...@@ -2339,8 +2339,8 @@ pushtag (name, type, globalize) ...@@ -2339,8 +2339,8 @@ pushtag (name, type, globalize)
class scope. In the friend case, push_template_decl class scope. In the friend case, push_template_decl
will already have put the friend into global scope, will already have put the friend into global scope,
if appropriate. */ if appropriate. */
if (!globalize && b->pseudo_global && if (!globalize && b->pseudo_global
b->level_chain->parm_flag == 2) && b->level_chain->parm_flag == 2)
{ {
pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type), pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
b->level_chain); b->level_chain);
...@@ -4455,6 +4455,9 @@ lookup_tag (form, name, binding_level, thislevel_only) ...@@ -4455,6 +4455,9 @@ lookup_tag (form, name, binding_level, thislevel_only)
int thislevel_only; int thislevel_only;
{ {
register struct binding_level *level; 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) for (level = binding_level; level; level = level->level_chain)
{ {
...@@ -4472,7 +4475,19 @@ lookup_tag (form, name, binding_level, thislevel_only) ...@@ -4472,7 +4475,19 @@ lookup_tag (form, name, binding_level, thislevel_only)
/* XXX: is this a real lookup, considering using-directives etc. ??? */ /* XXX: is this a real lookup, considering using-directives etc. ??? */
for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail)) 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 /* If it has an original type, it is a typedef, and we
should not return it. */ should not return it. */
if (old && DECL_ORIGINAL_TYPE (TYPE_NAME (old))) if (old && DECL_ORIGINAL_TYPE (TYPE_NAME (old)))
...@@ -4509,15 +4524,23 @@ lookup_tag (form, name, binding_level, thislevel_only) ...@@ -4509,15 +4524,23 @@ lookup_tag (form, name, binding_level, thislevel_only)
} }
if (thislevel_only && ! level->tag_transparent) if (thislevel_only && ! level->tag_transparent)
{ {
if (level->pseudo_global) if (level->pseudo_global && allow_pseudo_global)
{ {
tree t = IDENTIFIER_CLASS_VALUE (name); /* We must deal with cases like this:
if (t && DECL_CLASS_TEMPLATE_P (t))
return TREE_TYPE (t); template <class T> struct S;
t = IDENTIFIER_NAMESPACE_VALUE (name); template <class T> struct S {};
if (t && DECL_CLASS_TEMPLATE_P (t))
return TREE_TYPE (t); 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;
} }
else
return NULL_TREE; return NULL_TREE;
} }
if (current_class_type && level->level_chain->namespace_p) if (current_class_type && level->level_chain->namespace_p)
...@@ -4730,7 +4753,8 @@ make_typename_type (context, name) ...@@ -4730,7 +4753,8 @@ make_typename_type (context, name)
} }
return lookup_template_class (t, TREE_OPERAND (fullname, 1), return lookup_template_class (t, TREE_OPERAND (fullname, 1),
NULL_TREE, context); NULL_TREE, context,
/*entering_scope=*/0);
} }
else else
{ {
...@@ -6207,18 +6231,7 @@ shadow_tag (declspecs) ...@@ -6207,18 +6231,7 @@ shadow_tag (declspecs)
{ {
my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261); my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
if (IS_AGGR_TYPE (value) && CLASSTYPE_USE_TEMPLATE (value)) maybe_process_partial_specialization (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);
}
t = value; t = value;
ok_code = code; ok_code = code;
...@@ -10241,9 +10254,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -10241,9 +10254,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{ {
tree t = NULL_TREE; tree t = NULL_TREE;
if (decl && DECL_NAME (decl)) if (decl && DECL_NAME (decl))
{
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, t = do_friend (ctype, declarator, decl,
last_function_parms, flags, quals, last_function_parms, flags, quals,
funcdef_flag); funcdef_flag);
}
if (t && funcdef_flag) if (t && funcdef_flag)
return t; return t;
...@@ -11321,12 +11341,39 @@ xref_tag (code_type_node, name, binfo, globalize) ...@@ -11321,12 +11341,39 @@ xref_tag (code_type_node, name, binfo, globalize)
if (t && TYPE_CONTEXT (t) && got_type) if (t && TYPE_CONTEXT (t) && got_type)
ref = t; ref = t;
else else
{
/* If we know we are defining this tag, only look it up in /* 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. */ this scope and don't try to find it as a type. */
ref = lookup_tag (code, name, b, 1); ref = lookup_tag (code, name, b, 1);
} }
} else
{
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 <class X>
struct S1
template <class U>
struct S2
{ template <class V>
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 <class V = U> friend struct S1;
say, when we should tsubst into `U' when instantiating S2. */
ref = NULL_TREE;
else else
{ {
if (t) if (t)
...@@ -11336,7 +11383,8 @@ xref_tag (code_type_node, name, binfo, globalize) ...@@ -11336,7 +11383,8 @@ xref_tag (code_type_node, name, binfo, globalize)
if (! ref) if (! ref)
{ {
/* Try finding it as a type declaration. If that wins, use it. */ /* Try finding it as a type declaration. If that wins,
use it. */
ref = lookup_name (name, 1); ref = lookup_name (name, 1);
if (ref != NULL_TREE if (ref != NULL_TREE
...@@ -11354,6 +11402,7 @@ xref_tag (code_type_node, name, binfo, globalize) ...@@ -11354,6 +11402,7 @@ xref_tag (code_type_node, name, binfo, globalize)
ref = NULL_TREE; ref = NULL_TREE;
} }
} }
}
push_obstacks_nochange (); push_obstacks_nochange ();
...@@ -12121,13 +12170,24 @@ start_function (declspecs, declarator, attrs, pre_parsed_p) ...@@ -12121,13 +12170,24 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
(This does not mean `static' in the C sense!) */ (This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1; TREE_STATIC (decl1) = 1;
/* Record the decl so that the function name is defined. /* Set up current_class_type, and enter the scope of the class, if
If we already have a decl for this name, and it is a FUNCTION_DECL, appropriate. */
use the old decl. */ 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) if (processing_template_decl)
decl1 = push_template_decl (decl1); decl1 = push_template_decl (decl1);
else if (pre_parsed_p == 0)
/* 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 && pre_parsed_p == 0)
{ {
/* A specialization is not used to guide overload resolution. */ /* A specialization is not used to guide overload resolution. */
if ((flag_guiding_decls if ((flag_guiding_decls
...@@ -12207,8 +12267,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p) ...@@ -12207,8 +12267,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
if (ctype) if (ctype)
{ {
push_nested_class (ctype, 1);
/* If we're compiling a friend function, neither of the variables /* If we're compiling a friend function, neither of the variables
current_class_ptr nor current_class_type will have values. */ current_class_ptr nor current_class_type will have values. */
if (! doing_friend) if (! doing_friend)
...@@ -12241,10 +12299,8 @@ start_function (declspecs, declarator, attrs, pre_parsed_p) ...@@ -12241,10 +12299,8 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
} }
else else
{ {
if (DECL_STATIC_FUNCTION_P (decl1)) if (!DECL_STATIC_FUNCTION_P (decl1))
push_nested_class (DECL_CONTEXT (decl1), 2); push_memoized_context (NULL_TREE, 1);
else
push_memoized_context (0, 1);
current_class_ptr = current_class_ref = NULL_TREE; current_class_ptr = current_class_ref = NULL_TREE;
} }
...@@ -13185,7 +13241,8 @@ start_method (declspecs, declarator) ...@@ -13185,7 +13241,8 @@ start_method (declspecs, declarator)
if (flag_default_inline) if (flag_default_inline)
DECL_INLINE (fndecl) = 1; 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); fndecl = push_template_decl (fndecl);
/* We read in the parameters on the maybepermanent_obstack, /* We read in the parameters on the maybepermanent_obstack,
......
...@@ -912,34 +912,29 @@ grok_x_components (specs, components) ...@@ -912,34 +912,29 @@ grok_x_components (specs, components)
break; break;
case RECORD_TYPE: case RECORD_TYPE:
/* This code may be needed for UNION_TYPEs as case UNION_TYPE:
well. */ if (TREE_CODE (t) == UNION_TYPE)
tcode = union_type_node;
else
tcode = record_type_node; tcode = record_type_node;
if (CLASSTYPE_DECLARED_CLASS (t)) if (CLASSTYPE_DECLARED_CLASS (t))
tcode = class_type_node; tcode = class_type_node;
else if (IS_SIGNATURE (t)) else if (IS_SIGNATURE (t))
tcode = signature_type_node; tcode = signature_type_node;
if (TYPE_LANG_SPECIFIC (t)
&& CLASSTYPE_USE_TEMPLATE (t))
/* We have already looked up this type. */
;
else
{
if (CLASSTYPE_IS_TEMPLATE (t)) if (CLASSTYPE_IS_TEMPLATE (t))
/* In this case, the TYPE_IDENTIFIER will be something
like S<T>, rather than S, so to get the correct name we
look at the template. */
x = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t)); x = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
else else
x = TYPE_IDENTIFIER (t); x = TYPE_IDENTIFIER (t);
t = xref_tag (tcode, x, NULL_TREE, 0); 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;
else
tcode = enum_type_node;
t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
if (ANON_UNION_TYPE_P (t)) if (ANON_UNION_TYPE_P (t))
{ {
/* See also shadow_tag. */ /* See also shadow_tag. */
...@@ -972,11 +967,17 @@ grok_x_components (specs, components) ...@@ -972,11 +967,17 @@ grok_x_components (specs, components)
for (; *p; *p = (*p)->next) for (; *p; *p = (*p)->next)
if (DECL_CONTEXT ((*p)->fndecl) != t) if (DECL_CONTEXT ((*p)->fndecl) != t)
break; break;
return x;
} }
else if (TREE_CODE (t) == ENUMERAL_TYPE)
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); x = grok_enum_decls (NULL_TREE);
else
x = NULL_TREE;
return x; return x;
break; break;
...@@ -1132,16 +1133,7 @@ grokclassfn (ctype, cname, function, flags, quals) ...@@ -1132,16 +1133,7 @@ grokclassfn (ctype, cname, function, flags, quals)
TYPE_HAS_DESTRUCTOR (ctype) = 1; TYPE_HAS_DESTRUCTOR (ctype) = 1;
} }
else else
{ set_mangled_name_for_decl (function);
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));
}
} }
/* Work on the expr used by alignof (this is only called by the parser). */ /* Work on the expr used by alignof (this is only called by the parser). */
...@@ -4299,7 +4291,7 @@ arg_assoc_class (k, type) ...@@ -4299,7 +4291,7 @@ arg_assoc_class (k, type)
/* Process template arguments. */ /* Process template arguments. */
if (CLASSTYPE_TEMPLATE_INFO (type)) 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) for (i = 0; i < TREE_VEC_LENGTH (list); ++i)
arg_assoc (k, TREE_VEC_ELT (list, i)); arg_assoc (k, TREE_VEC_ELT (list, i));
} }
...@@ -4690,13 +4682,21 @@ mark_used (decl) ...@@ -4690,13 +4682,21 @@ mark_used (decl)
if (processing_template_decl) if (processing_template_decl)
return; return;
assemble_external (decl); assemble_external (decl);
/* Is it a synthesized method that needs to be synthesized? */ /* Is it a synthesized method that needs to be synthesized? */
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CLASS_CONTEXT (decl) if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CLASS_CONTEXT (decl)
&& DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl) && DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
/* Kludge: don't synthesize for default args. */ /* Kludge: don't synthesize for default args. */
&& current_function_decl) && current_function_decl)
synthesize_method (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); instantiate_decl (decl);
} }
......
...@@ -1042,29 +1042,14 @@ dump_function_name (t) ...@@ -1042,29 +1042,14 @@ dump_function_name (t)
else else
dump_decl (name, 0); 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; tree args = DECL_TEMPLATE_INFO (t) ? DECL_TI_ARGS (t) : NULL_TREE;
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 <class T> struct S { void f(); };
and we are printing S<int>::f(). This is a template
instantiation, but we don't print anything after the f. */
;
else
{
OB_PUTC ('<'); OB_PUTC ('<');
/* Be careful only to print things when we have them, so as not /* Be careful only to print things when we have them, so as not
...@@ -1127,7 +1112,6 @@ dump_function_name (t) ...@@ -1127,7 +1112,6 @@ dump_function_name (t)
} }
OB_PUTC ('>'); OB_PUTC ('>');
} }
}
} }
static void static void
......
...@@ -70,22 +70,23 @@ is_friend (type, supplicant) ...@@ -70,22 +70,23 @@ is_friend (type, supplicant)
if (TREE_VALUE (friends) == NULL_TREE) if (TREE_VALUE (friends) == NULL_TREE)
continue; continue;
if (TREE_CODE (TREE_VALUE (friends)) == TEMPLATE_DECL) if (supplicant == TREE_VALUE (friends))
{
if (is_specialization_of (supplicant,
TREE_VALUE (friends)))
return 1; return 1;
continue; /* With -fguiding-decls we are more lenient about
} friendship. This is bogus in general since two
specializations of a template with non-type
/* FIXME: The use of comptypes here is bogus, since template parameters may have the same type, but
two specializations of a template with non-type be different. */
parameters may have the same type, but be if (flag_guiding_decls
different. */ && comptypes (TREE_TYPE (supplicant),
if (comptypes (TREE_TYPE (supplicant),
TREE_TYPE (TREE_VALUE (friends)), 1)) TREE_TYPE (TREE_VALUE (friends)), 1))
return 1; return 1;
if (TREE_CODE (TREE_VALUE (friends)) == TEMPLATE_DECL
&& is_specialization_of (supplicant,
TREE_VALUE (friends)))
return 1;
} }
break; break;
} }
...@@ -253,6 +254,21 @@ make_friend_class (type, friend_type) ...@@ -253,6 +254,21 @@ make_friend_class (type, friend_type)
IDENTIFIER_POINTER (TYPE_IDENTIFIER (friend_type))); IDENTIFIER_POINTER (TYPE_IDENTIFIER (friend_type)));
return; 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 (processing_template_decl > template_class_depth (type))
/* If the TYPE is a template then it makes sense for it to be /* If the TYPE is a template then it makes sense for it to be
friends with itself; this means that each instantiation is friends with itself; this means that each instantiation is
...@@ -407,9 +423,7 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag) ...@@ -407,9 +423,7 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
Note that because classes all wind up being top-level Note that because classes all wind up being top-level
in their scope, their friend wind up in top-level scope as well. */ in their scope, their friend wind up in top-level scope as well. */
DECL_ASSEMBLER_NAME (decl) set_mangled_name_for_decl (decl);
= build_decl_overload (declarator, TYPE_ARG_TYPES (TREE_TYPE (decl)),
TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
DECL_ARGUMENTS (decl) = parmdecls; DECL_ARGUMENTS (decl) = parmdecls;
if (funcdef_flag) if (funcdef_flag)
DECL_CLASS_CONTEXT (decl) = current_class_type; DECL_CLASS_CONTEXT (decl) = current_class_type;
...@@ -417,20 +431,17 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag) ...@@ -417,20 +431,17 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
if (! DECL_USE_TEMPLATE (decl)) if (! DECL_USE_TEMPLATE (decl))
{ {
/* We can call pushdecl here, because the TREE_CHAIN of this /* We can call pushdecl here, because the TREE_CHAIN of this
FUNCTION_DECL is not needed for other purposes. Don't do this FUNCTION_DECL is not needed for other purposes. Don't do
for a template instantiation. */ this for a template instantiation. However, we don't
if (!is_friend_template) call pushdecl() for a friend function of a template
{ class, since in general, such a declaration depends on
/* However, we don't call pushdecl() for a friend template parameters. Instead, we call pushdecl when the
function of a template class, since in general,
such a declaration depends on template
parameters. Instead, we call pushdecl when the
class is instantiated. */ class is instantiated. */
if (template_class_depth (current_class_type) == 0) if (!is_friend_template
&& template_class_depth (current_class_type) == 0)
decl = pushdecl (decl); decl = pushdecl (decl);
}
else else
decl = push_template_decl (decl); decl = push_template_decl_real (decl, /*is_friend=*/1);
if (! funcdef_flag && ! flag_guiding_decls && ! is_friend_template if (! funcdef_flag && ! flag_guiding_decls && ! is_friend_template
&& current_template_parms && uses_template_parms (decl)) && current_template_parms && uses_template_parms (decl))
......
...@@ -71,8 +71,6 @@ static void process_overload_item PROTO((tree,int)); ...@@ -71,8 +71,6 @@ static void process_overload_item PROTO((tree,int));
static void do_build_assign_ref PROTO((tree)); static void do_build_assign_ref PROTO((tree));
static void do_build_copy_constructor PROTO((tree)); static void do_build_copy_constructor PROTO((tree));
static tree largest_union_member 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_template_parm_names PROTO((tree));
static void build_template_parm_names PROTO((tree, tree)); static void build_template_parm_names PROTO((tree, tree));
static void build_underscore_int PROTO((int)); static void build_underscore_int PROTO((int));
...@@ -922,7 +920,7 @@ build_overload_identifier (name) ...@@ -922,7 +920,7 @@ build_overload_identifier (name)
/* NAME is the TYPE_DECL for a template specialization. */ /* NAME is the TYPE_DECL for a template specialization. */
tree template, parmlist, arglist, tname; tree template, parmlist, arglist, tname;
template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name)); template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name));
arglist = innermost_args (TREE_VALUE (template), 0); arglist = innermost_args (TREE_VALUE (template));
template = TREE_PURPOSE (template); template = TREE_PURPOSE (template);
tname = DECL_NAME (template); tname = DECL_NAME (template);
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template); parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
...@@ -1499,7 +1497,10 @@ build_static_name (context, name) ...@@ -1499,7 +1497,10 @@ build_static_name (context, name)
return get_identifier ((char *)obstack_base (&scratch_obstack)); 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, build_decl_overload_real (dname, parms, ret_type, tparms, targs,
for_method) for_method)
tree dname; tree dname;
...@@ -1660,38 +1661,32 @@ build_decl_overload (dname, parms, for_method) ...@@ -1660,38 +1661,32 @@ build_decl_overload (dname, parms, for_method)
NULL_TREE, for_method); NULL_TREE, for_method);
} }
/* Set the mangled name (DECL_ASSEMBLER_NAME) for DECL. */
/* Like build_decl_overload, but for template functions. */
tree tree
build_template_decl_overload (decl, parms, ret_type, tparms, targs, set_mangled_name_for_decl (decl)
for_method)
tree 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, if (DECL_STATIC_FUNCTION_P (decl))
tparms, targs, for_method); parm_types =
hash_tree_chain (build_pointer_type (DECL_CLASS_CONTEXT (decl)),
current_namespace = saved_ctx; parm_types);
return res; 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. */ /* Build an overload name for the type expression TYPE. */
tree tree
......
...@@ -267,7 +267,7 @@ empty_parms () ...@@ -267,7 +267,7 @@ empty_parms ()
%type <ttype> named_class_head_sans_basetype_defn %type <ttype> named_class_head_sans_basetype_defn
%type <ttype> identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN %type <ttype> identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN
%type <ttype> self_template_type %type <ttype> self_template_type .finish_template_type
%token NSNAME %token NSNAME
%type <ttype> NSNAME %type <ttype> NSNAME
...@@ -556,22 +556,38 @@ template_parm: ...@@ -556,22 +556,38 @@ template_parm:
; ;
template_def: template_def:
template_header template_header template_extdef
extdef { finish_template_decl ($1); }
{ | template_header error %prec EMPTY
if ($1) { finish_template_decl ($1); }
end_template_decl (); ;
else
end_specialization (); template_extdef:
} fndef eat_saved_input
| template_header { if (pending_inlines) do_pending_inlines (); }
error %prec EMPTY | template_datadef
{ { if (pending_inlines) do_pending_inlines (); }
if ($1) | template_def
end_template_decl (); { if (pending_inlines) do_pending_inlines (); }
else | extern_lang_string .hush_warning fndef .warning_ok eat_saved_input
end_specialization (); { 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 = $<itype>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: datadef:
...@@ -579,9 +595,7 @@ datadef: ...@@ -579,9 +595,7 @@ datadef:
| declmods notype_initdecls ';' | declmods notype_initdecls ';'
{} {}
| typed_declspecs initdecls ';' | typed_declspecs initdecls ';'
{ { note_list_got_semicolon ($1.t); }
note_list_got_semicolon ($1.t);
}
| declmods ';' | declmods ';'
{ pedwarn ("empty declaration"); } { pedwarn ("empty declaration"); }
| explicit_instantiation ';' | explicit_instantiation ';'
...@@ -870,28 +884,28 @@ end_explicit_instantiation: ...@@ -870,28 +884,28 @@ end_explicit_instantiation:
template_type: template_type:
PTYPENAME '<' template_arg_list_opt template_close_bracket PTYPENAME '<' template_arg_list_opt template_close_bracket
{ .finish_template_type
$$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE); { $$ = $5; }
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
| TYPENAME '<' template_arg_list_opt template_close_bracket | TYPENAME '<' template_arg_list_opt template_close_bracket
{ .finish_template_type
$$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE); { $$ = $5; }
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
| self_template_type | self_template_type
; ;
self_template_type: self_template_type:
SELFNAME '<' template_arg_list_opt template_close_bracket SELFNAME '<' template_arg_list_opt template_close_bracket
.finish_template_type
{ $$ = $5; }
;
.finish_template_type:
{ {
$$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE); if (yychar == YYEMPTY)
if ($$ != error_mark_node) yychar = YYLEX;
$$ = TYPE_STUB_DECL ($$);
$$ = finish_template_type ($<ttype>-3, $<ttype>-1,
yychar == SCOPE);
} }
;
template_close_bracket: template_close_bracket:
'>' '>'
...@@ -2193,18 +2207,7 @@ named_class_head: ...@@ -2193,18 +2207,7 @@ named_class_head:
cp_pedwarn ("non-`union' tag used in declaring `%#T'", $$); cp_pedwarn ("non-`union' tag used in declaring `%#T'", $$);
if ($2) if ($2)
{ {
if (IS_AGGR_TYPE ($$) && CLASSTYPE_USE_TEMPLATE ($$)) maybe_process_partial_specialization ($$);
{
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'", $$);
}
xref_basetypes (current_aggr, $1, $$, $2); xref_basetypes (current_aggr, $1, $$, $2);
} }
} }
......
...@@ -80,29 +80,29 @@ static int unify PROTO((tree, tree, tree, tree, int, int*)); ...@@ -80,29 +80,29 @@ static int unify PROTO((tree, tree, tree, tree, int, int*));
static void add_pending_template PROTO((tree)); static void add_pending_template PROTO((tree));
static int push_tinst_level PROTO((tree)); static int push_tinst_level PROTO((tree));
static tree classtype_mangled_name 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 tree tsubst_expr_values PROTO((tree, tree));
static int list_eq 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 coerce_template_parms PROTO((tree, tree, tree, int, int));
static tree tsubst_enum PROTO((tree, tree, tree *)); static tree tsubst_enum PROTO((tree, tree, tree *));
static tree add_to_template_args PROTO((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*, static void maybe_adjust_types_for_deduction PROTO((unification_kind_t, tree*,
tree*)); tree*));
static int type_unification_real PROTO((tree, tree, tree, tree, static int type_unification_real PROTO((tree, tree, tree, tree,
int, unification_kind_t, int, int*)); int, unification_kind_t, int, int*));
static tree complete_template_args PROTO((tree, tree, int));
static void note_template_header PROTO((int)); static void note_template_header PROTO((int));
static tree maybe_fold_nontype_arg PROTO((tree)); static tree maybe_fold_nontype_arg PROTO((tree));
static tree convert_nontype_argument PROTO((tree, tree)); static tree convert_nontype_argument PROTO((tree, tree));
static tree get_bindings_overload PROTO((tree, tree, tree)); static tree get_bindings_overload PROTO((tree, tree, tree));
static int for_each_template_parm PROTO((tree, tree_fn_t, void*)); 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 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 int inline_needs_template_parms PROTO((tree));
static void push_inline_template_parms_recursive PROTO((tree, int)); static void push_inline_template_parms_recursive PROTO((tree, int));
static tree retrieve_specialization PROTO((tree, tree)); 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 void print_candidates PROTO((tree));
static tree reduce_template_parm_level PROTO((tree, tree, int)); static tree reduce_template_parm_level PROTO((tree, tree, int));
static tree build_template_decl PROTO((tree, tree)); static tree build_template_decl PROTO((tree, tree));
...@@ -114,10 +114,41 @@ static int template_decl_level PROTO((tree)); ...@@ -114,10 +114,41 @@ static int template_decl_level PROTO((tree));
static tree maybe_get_template_decl_from_type_decl 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 int check_cv_quals_for_unify PROTO((int, tree, tree));
static tree tsubst_template_arg_vector PROTO((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 void regenerate_decl_from_template PROTO((tree, tree));
static int is_member_template_class PROTO((tree)); static int is_member_template_class PROTO((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)
/* Nonzero if ARGVEC contains multiple levels of template arguments. */ /* Non-zero if the template arguments is actually a vector of vectors,
rather than just a vector. */
#define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE) \ #define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE) \
(NODE != NULL_TREE \ (NODE != NULL_TREE \
&& TREE_CODE (NODE) == TREE_VEC \ && TREE_CODE (NODE) == TREE_VEC \
...@@ -125,6 +156,30 @@ static int is_member_template_class PROTO((tree)); ...@@ -125,6 +156,30 @@ static int is_member_template_class PROTO((tree));
&& TREE_VEC_ELT (NODE, 0) != NULL_TREE \ && TREE_VEC_ELT (NODE, 0) != NULL_TREE \
&& TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC) && 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 /* Do any processing required when DECL (a member template declaration
using TEMPLATE_PARAMETERS as its innermost parameter list) is using TEMPLATE_PARAMETERS as its innermost parameter list) is
finished. Returns the TEMPLATE_DECL corresponding to DECL, unless finished. Returns the TEMPLATE_DECL corresponding to DECL, unless
...@@ -135,10 +190,7 @@ finish_member_template_decl (template_parameters, decl) ...@@ -135,10 +190,7 @@ finish_member_template_decl (template_parameters, decl)
tree template_parameters; tree template_parameters;
tree decl; tree decl;
{ {
if (template_parameters) finish_template_decl (template_parameters);
end_template_decl ();
else
end_specialization ();
if (decl == NULL_TREE || decl == void_type_node) if (decl == NULL_TREE || decl == void_type_node)
return NULL_TREE; return NULL_TREE;
...@@ -203,18 +255,6 @@ template_class_depth (type) ...@@ -203,18 +255,6 @@ template_class_depth (type)
return depth; 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 /* Returns 1 if processing DECL as part of do_pending_inlines
needs us to push template parms. */ needs us to push template parms. */
...@@ -225,7 +265,7 @@ inline_needs_template_parms (decl) ...@@ -225,7 +265,7 @@ inline_needs_template_parms (decl)
if (! DECL_TEMPLATE_INFO (decl)) if (! DECL_TEMPLATE_INFO (decl))
return 0; 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))); > (processing_template_decl + DECL_TEMPLATE_SPECIALIZATION (decl)));
} }
...@@ -293,9 +333,9 @@ maybe_begin_member_template_processing (decl) ...@@ -293,9 +333,9 @@ maybe_begin_member_template_processing (decl)
if (! inline_needs_template_parms (decl)) if (! inline_needs_template_parms (decl))
return; 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)) if (DECL_TEMPLATE_SPECIALIZATION (decl))
{ {
...@@ -371,7 +411,7 @@ is_member_template (t) ...@@ -371,7 +411,7 @@ is_member_template (t)
/* If there are more levels of template parameters than /* If there are more levels of template parameters than
there are template classes surrounding the declaration, there are template classes surrounding the declaration,
then we have a member template. */ then we have a member template. */
&& (list_length (DECL_TEMPLATE_PARMS (tmpl)) > && (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)) >
template_class_depth (DECL_CLASS_CONTEXT (t)))) template_class_depth (DECL_CLASS_CONTEXT (t))))
return 1; return 1;
} }
...@@ -400,146 +440,58 @@ is_member_template_class (t) ...@@ -400,146 +440,58 @@ is_member_template_class (t)
/* If there are more levels of template parameters than there are /* If there are more levels of template parameters than there are
template classes surrounding the declaration, then we have a template classes surrounding the declaration, then we have a
member template. */ member template. */
return (list_length (DECL_TEMPLATE_PARMS (t)) > return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) >
template_class_depth (DECL_CONTEXT (t))); template_class_depth (DECL_CONTEXT (t)));
} }
/* Return a new template argument vector which contains all of ARGS /* Return a new template argument vector which contains all of ARGS,
for all outer templates TMPL is contained in, but has as its but has as its innermost set of arguments the EXTRA_ARGS. The
innermost set of arguments the EXTRA_ARGS. If UNBOUND_ONLY, we resulting vector will be built on a temporary obstack, and so must
are only interested in unbound template arguments, not arguments from be explicitly copied to the permanent obstack, if required. */
enclosing templates that have been instantiated already. */
static tree static tree
complete_template_args (tmpl, extra_args, unbound_only) add_to_template_args (args, extra_args)
tree tmpl, extra_args; tree args;
int unbound_only; tree extra_args;
{ {
/* depth is the number of levels of enclosing args we're adding. */ tree new_args;
int depth, i; int extra_depth;
tree args, new_args, spec_args = NULL_TREE; int i;
int extra_arg_depth; int j;
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) extra_depth = TMPL_ARGS_DEPTH (extra_args);
{ new_args = make_temp_vec (TMPL_ARGS_DEPTH (args) + extra_depth);
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);
}
}
}
}
if (extra_arg_depth == 1) for (i = 1; i <= TMPL_ARGS_DEPTH (args); ++i)
TREE_VEC_ELT (new_args, depth++) = extra_args; SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (args, i));
else
for (i = 0; i < extra_arg_depth; ++i)
TREE_VEC_ELT (new_args, depth++) = TREE_VEC_ELT (extra_args, i);
if (spec_args) for (j = 1; j <= extra_depth; ++j, ++i)
TREE_VEC_ELT (new_args, depth) = spec_args; SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (extra_args, j));
return new_args; return new_args;
} }
/* Return a new template argument vector which contains all of ARGS, /* Like add_to_template_args, but only the outermost ARGS are added to
but has as its innermost set of arguments the EXTRA_ARGS. */ 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 static tree
add_to_template_args (args, extra_args) add_outermost_template_args (args, extra_args)
tree args; tree args;
tree extra_args; tree extra_args;
{ {
tree new_args; tree new_args;
if (!TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)) /* For the moment, we make ARGS look like it contains fewer levels. */
{ TREE_VEC_LENGTH (args) -= TMPL_ARGS_DEPTH (extra_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 (i = 0; i < TREE_VEC_LENGTH (args); ++i) new_args = add_to_template_args (args, extra_args);
TREE_VEC_ELT (new_args, i) = TREE_VEC_ELT (args, i);
}
TREE_VEC_ELT (new_args, /* Now, we restore ARGS to its full dimensions. */
TREE_VEC_LENGTH (new_args) - 1) = extra_args; TREE_VEC_LENGTH (args) += TMPL_ARGS_DEPTH (extra_args);
return new_args; return new_args;
} }
...@@ -625,6 +577,27 @@ end_explicit_instantiation () ...@@ -625,6 +577,27 @@ end_explicit_instantiation ()
--processing_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 /* Retrieve the specialization (in the sense of [temp.spec] - a
specialization is either an instantiation or an explicit specialization is either an instantiation or an explicit
specialization) of TMPL for the given template ARGS. If there is specialization) of TMPL for the given template ARGS. If there is
...@@ -641,6 +614,12 @@ retrieve_specialization (tmpl, args) ...@@ -641,6 +614,12 @@ retrieve_specialization (tmpl, args)
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0); 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); for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
s != NULL_TREE; s != NULL_TREE;
s = TREE_CHAIN (s)) s = TREE_CHAIN (s))
...@@ -684,9 +663,10 @@ is_specialization_of (decl, tmpl) ...@@ -684,9 +663,10 @@ is_specialization_of (decl, tmpl)
} }
/* Register the specialization SPEC as a specialization of TMPL with /* 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) register_specialization (spec, tmpl, args)
tree spec; tree spec;
tree tmpl; tree tmpl;
...@@ -696,13 +676,26 @@ register_specialization (spec, tmpl, args) ...@@ -696,13 +676,26 @@ register_specialization (spec, tmpl, args)
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0); my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
if (TREE_CODE (spec) != TEMPLATE_DECL if (TREE_CODE (spec) == FUNCTION_DECL
&& list_length (DECL_TEMPLATE_PARMS (tmpl)) > 1) && uses_template_parms (DECL_TI_ARGS (spec)))
/* Avoid registering function declarations as /* This is the FUNCTION_DECL for a partial instantiation. Don't
specializations of member templates, as would otherwise register it; we want the corresponding TEMPLATE_DECL instead.
happen with out-of-class specializations of member We use `uses_template_parms (DECL_TI_ARGS (spec))' rather than
templates. */ the more obvious `uses_template_parms (spec)' to avoid problems
return; with default function arguments. In particular, given
something like this:
template <class T> 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); for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
s != NULL_TREE; s != NULL_TREE;
...@@ -720,7 +713,7 @@ register_specialization (spec, tmpl, args) ...@@ -720,7 +713,7 @@ register_specialization (spec, tmpl, args)
{ {
cp_error ("specialization of %D after instantiation", cp_error ("specialization of %D after instantiation",
fn); fn);
return; return spec;
} }
else else
{ {
...@@ -729,10 +722,22 @@ register_specialization (spec, tmpl, args) ...@@ -729,10 +722,22 @@ register_specialization (spec, tmpl, args)
the second is an explicit specialization, and the second is an explicit specialization, and
the implicit instantiation has not yet been the implicit instantiation has not yet been
used. That situation can occur if we have used. That situation can occur if we have
implicitly instantiated a member function of implicitly instantiated a member function and
class type, and then specialized it later. */ then specialized it later.
TREE_VALUE (s) = spec;
return; We can also wind up here if a friend
declaration that looked like an instantiation
turns out to be a specialization:
template <class T> 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)) else if (DECL_TEMPLATE_SPECIALIZATION (fn))
...@@ -741,13 +746,38 @@ register_specialization (spec, tmpl, args) ...@@ -741,13 +746,38 @@ register_specialization (spec, tmpl, args)
cp_error ("duplicate specialization of %D", fn); cp_error ("duplicate specialization of %D", fn);
TREE_VALUE (s) = spec; TREE_VALUE (s) = spec;
return; return spec;
} }
} }
} }
DECL_TEMPLATE_SPECIALIZATIONS (tmpl) DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
= perm_tree_cons (args, 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. */ /* Print the list of candidate FNS in an error message. */
...@@ -856,13 +886,26 @@ determine_specialization (template_id, decl, targs_out, ...@@ -856,13 +886,26 @@ determine_specialization (template_id, decl, targs_out,
if (decl != NULL_TREE) if (decl != NULL_TREE)
{ {
tree tmpl = most_specialized (templates, decl, targs_in); tree tmpl = most_specialized (templates, decl, targs_in);
tree inner_args;
tree tmpl_args;
if (tmpl == error_mark_node) if (tmpl == error_mark_node)
goto ambiguous; goto ambiguous;
else if (tmpl == NULL_TREE) else if (tmpl == NULL_TREE)
goto no_match; 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; return tmpl;
} }
...@@ -927,8 +970,7 @@ determine_specialization (template_id, decl, targs_out, ...@@ -927,8 +970,7 @@ determine_specialization (template_id, decl, targs_out,
template <class T> struct S {}; template <class T> struct S {};
template <> struct S<int> { void f(); } template <> struct S<int> { void f(); }
template <> template <> void S<int>::f();
void S<int>::f();
the TEMPLATE_COUNT would be 0. (Note that this declaration is the TEMPLATE_COUNT would be 0. (Note that this declaration is
illegal; there should be no template <>.) illegal; there should be no template <>.)
...@@ -1018,7 +1060,8 @@ check_explicit_specialization (declarator, decl, template_count, flags) ...@@ -1018,7 +1060,8 @@ check_explicit_specialization (declarator, decl, template_count, flags)
} }
else if (ctype != NULL_TREE else if (ctype != NULL_TREE
&& !TYPE_BEING_DEFINED (ctype) && !TYPE_BEING_DEFINED (ctype)
&& CLASSTYPE_TEMPLATE_INSTANTIATION (ctype)) && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype)
&& !is_friend)
{ {
/* This case catches outdated code that looks like this: /* This case catches outdated code that looks like this:
...@@ -1049,15 +1092,23 @@ check_explicit_specialization (declarator, decl, template_count, flags) ...@@ -1049,15 +1092,23 @@ check_explicit_specialization (declarator, decl, template_count, flags)
} }
else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR) else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
{ {
/* This case handles bogus declarations like if (is_friend)
template <> template <class T> /* This could be something like:
void f<int>(); */
template <class T> void f(T);
class S { friend void f<>(int); } */
specialization = 1;
else
{
/* This case handles bogus declarations like template <>
template <class T> void f<int>(); */
cp_error ("template-id `%D' in declaration of primary template", cp_error ("template-id `%D' in declaration of primary template",
declarator); declarator);
return decl; return decl;
} }
} }
}
if (specialization || member_specialization) if (specialization || member_specialization)
{ {
...@@ -1073,6 +1124,7 @@ check_explicit_specialization (declarator, decl, template_count, flags) ...@@ -1073,6 +1124,7 @@ check_explicit_specialization (declarator, decl, template_count, flags)
if (specialization || member_specialization || explicit_instantiation) if (specialization || member_specialization || explicit_instantiation)
{ {
tree gen_tmpl;
tree tmpl = NULL_TREE; tree tmpl = NULL_TREE;
tree targs = NULL_TREE; tree targs = NULL_TREE;
...@@ -1172,9 +1224,10 @@ check_explicit_specialization (declarator, decl, template_count, flags) ...@@ -1172,9 +1224,10 @@ check_explicit_specialization (declarator, decl, template_count, flags)
Note that for an explicit instantiation, even one for a Note that for an explicit instantiation, even one for a
member function, we cannot tell apriori whether the member function, we cannot tell apriori whether the
instantiation is for a member template, or just a member instantiation is for a member template, or just a member
function of a template class. In particular, even in if the function of a template class. Even if a member template is
instantiation is for a member template, the template being instantiated, the member template arguments may be
arguments could be deduced from the declaration. */ elided if they can be deduced from the rest of the
declaration. */
tmpl = determine_specialization (declarator, decl, tmpl = determine_specialization (declarator, decl,
&targs, &targs,
member_specialization, member_specialization,
...@@ -1182,9 +1235,11 @@ check_explicit_specialization (declarator, decl, template_count, flags) ...@@ -1182,9 +1235,11 @@ check_explicit_specialization (declarator, decl, template_count, flags)
if (tmpl && tmpl != error_mark_node) if (tmpl && tmpl != error_mark_node)
{ {
gen_tmpl = most_general_template (tmpl);
if (explicit_instantiation) if (explicit_instantiation)
{ {
decl = instantiate_template (tmpl, targs); decl = instantiate_template (tmpl, innermost_args (targs));
if (!DECL_TEMPLATE_SPECIALIZATION (decl)) if (!DECL_TEMPLATE_SPECIALIZATION (decl))
/* There doesn't seem to be anything in the draft to /* There doesn't seem to be anything in the draft to
prevent a specialization from being explicitly prevent a specialization from being explicitly
...@@ -1194,72 +1249,49 @@ check_explicit_specialization (declarator, decl, template_count, flags) ...@@ -1194,72 +1249,49 @@ check_explicit_specialization (declarator, decl, template_count, flags)
SET_DECL_EXPLICIT_INSTANTIATION (decl); SET_DECL_EXPLICIT_INSTANTIATION (decl);
return decl; return decl;
} }
else if (DECL_STATIC_FUNCTION_P (tmpl)
/* 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)) && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
{ {
revert_static_member_fn (&decl, 0, 0); revert_static_member_fn (&decl, 0, 0);
last_function_parms = TREE_CHAIN (last_function_parms); 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 /* Mangle the function name appropriately. Note that we do
not mangle specializations of non-template member not mangle specializations of non-template member
functions of template classes, e.g. with functions of template classes, e.g. with
template <class T> struct S { void f(); } template <class T> struct S { void f(); }
and given the specialization and given the specialization
template <> void S<int>::f() {} template <> void S<int>::f() {}
we do not mangle S<int>::f() here. That's because it's we do not mangle S<int>::f() here. That's because it's
just an ordinary member function and doesn't need special 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) if ((is_member_template (tmpl) || ctype == NULL_TREE)
&& name_mangling_version >= 1) && name_mangling_version >= 1)
{ set_mangled_name_for_template_decl (decl);
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);
}
if (is_friend && !have_def) if (is_friend && !have_def)
{
/* This is not really a declaration of a specialization. /* This is not really a declaration of a specialization.
It's just the name of an instantiation. But, it's not It's just the name of an instantiation. But, it's not
a request for an instantiation, either. */ a request for an instantiation, either. */
SET_DECL_IMPLICIT_INSTANTIATION (decl); 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; return decl;
} }
...@@ -1521,26 +1553,34 @@ end_template_decl () ...@@ -1521,26 +1553,34 @@ end_template_decl ()
(void) get_pending_sizes (); /* Why? */ (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 tree
current_template_args () current_template_args ()
{ {
tree header = current_template_parms; tree header;
int length = list_length (header); tree args;
tree args = make_tree_vec (length); int length = TMPL_PARMS_DEPTH (current_template_parms);
int l = length; 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)); tree a = copy_node (TREE_VALUE (header));
int i = TREE_VEC_LENGTH (a); int i;
TREE_TYPE (a) = NULL_TREE; TREE_TYPE (a) = NULL_TREE;
while (i--) for (i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i)
{ {
tree t = TREE_VEC_ELT (a, 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 begin/end_template_parm_list pair, but a vector directly
if within a begin/end_member_template_processing pair. */ if within a begin/end_member_template_processing pair. */
if (TREE_CODE (t) == TREE_LIST) if (TREE_CODE (t) == TREE_LIST)
...@@ -1552,18 +1592,19 @@ current_template_args () ...@@ -1552,18 +1592,19 @@ current_template_args ()
t = TREE_TYPE (t); t = TREE_TYPE (t);
else else
t = DECL_INITIAL (t); t = DECL_INITIAL (t);
}
TREE_VEC_ELT (a, i) = t; TREE_VEC_ELT (a, i) = t;
} }
}
if (length > 1)
TREE_VEC_ELT (args, --l) = a; TREE_VEC_ELT (args, --l) = a;
header = TREE_CHAIN (header); else
args = a;
} }
return args; return args;
} }
/* Return a TEMPLATE_DECL corresponding to DECL, using the indicated /* Return a TEMPLATE_DECL corresponding to DECL, using the indicated
template PARMS. Used by push_template_decl below. */ template PARMS. Used by push_template_decl below. */
...@@ -1668,9 +1709,7 @@ push_template_decl_real (decl, is_friend) ...@@ -1668,9 +1709,7 @@ push_template_decl_real (decl, is_friend)
/* For determining whether this is a primary template or not, we're really /* For determining whether this is a primary template or not, we're really
interested in the lexical context, not the true context. */ interested in the lexical context, not the true context. */
if (is_friend) if (is_friend)
/* For a TYPE_DECL, there is no DECL_CLASS_CONTEXT. */ info = current_class_type;
info = TREE_CODE (decl) == FUNCTION_DECL
? DECL_CLASS_CONTEXT (decl) : current_class_type;
else else
info = ctx; info = ctx;
...@@ -1697,8 +1736,7 @@ push_template_decl_real (decl, is_friend) ...@@ -1697,8 +1736,7 @@ push_template_decl_real (decl, is_friend)
{ {
tree type = TREE_TYPE (decl); tree type = TREE_TYPE (decl);
tree maintmpl = CLASSTYPE_TI_TEMPLATE (type); tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
tree mainargs = CLASSTYPE_TI_ARGS (type); tree specargs = CLASSTYPE_TI_ARGS (type);
tree spec = DECL_TEMPLATE_SPECIALIZATIONS (maintmpl);
/* We check that each of the template parameters given in the /* We check that each of the template parameters given in the
partial specialization is used in the argument list to the partial specialization is used in the argument list to the
...@@ -1732,15 +1770,16 @@ push_template_decl_real (decl, is_friend) ...@@ -1732,15 +1770,16 @@ push_template_decl_real (decl, is_friend)
or some such would have been OK. */ or some such would have been OK. */
int i; int i;
struct template_parm_data tpd; 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; 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); tpd.parms = alloca (sizeof (int) * ntparms);
for (i = 0; i < ntparms; ++i) for (i = 0; i < ntparms; ++i)
tpd.parms[i] = 0; tpd.parms[i] = 0;
for (i = 0; i < TREE_VEC_LENGTH (mainargs); ++i) for (i = 0; i < TREE_VEC_LENGTH (specargs); ++i)
for_each_template_parm (TREE_VEC_ELT (mainargs, i), for_each_template_parm (TREE_VEC_ELT (specargs, i),
&mark_template_parm, &mark_template_parm,
&tpd); &tpd);
for (i = 0; i < ntparms; ++i) for (i = 0; i < ntparms; ++i)
...@@ -1760,16 +1799,22 @@ push_template_decl_real (decl, is_friend) ...@@ -1760,16 +1799,22 @@ push_template_decl_real (decl, is_friend)
i))); i)));
} }
for (; spec; spec = TREE_CHAIN (spec)) /* [temp.class.spec]
{
/* purpose: args to main template The argument list of the specialization shall not be
value: spec template */ identical to the implicit argument list of the primary
if (comp_template_args (TREE_PURPOSE (spec), mainargs)) 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; return decl;
}
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) = CLASSTYPE_TI_SPEC_INFO (type) 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)); DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type; TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
return decl; return decl;
...@@ -1857,7 +1902,7 @@ push_template_decl_real (decl, is_friend) ...@@ -1857,7 +1902,7 @@ push_template_decl_real (decl, is_friend)
return decl; return decl;
} }
a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1); a = innermost_args (args);
t = DECL_INNERMOST_TEMPLATE_PARMS (tmpl); t = DECL_INNERMOST_TEMPLATE_PARMS (tmpl);
if (TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a)) if (TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a))
{ {
...@@ -1865,15 +1910,15 @@ push_template_decl_real (decl, is_friend) ...@@ -1865,15 +1910,15 @@ push_template_decl_real (decl, is_friend)
TREE_VEC_LENGTH (a), decl); TREE_VEC_LENGTH (a), decl);
cp_error (" but %d required", TREE_VEC_LENGTH (t)); 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 /* Get the template parameters for the enclosing template
class. */ class. */
a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 2); a = TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args) - 1);
else else
a = NULL_TREE; a = NULL_TREE;
} }
else else
a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1); a = innermost_args (args);
t = NULL_TREE; t = NULL_TREE;
...@@ -1899,23 +1944,18 @@ push_template_decl_real (decl, is_friend) ...@@ -1899,23 +1944,18 @@ push_template_decl_real (decl, is_friend)
cp_error (" but `%#T' has %d", ctx, TREE_VEC_LENGTH (t)); 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; DECL_TEMPLATE_RESULT (tmpl) = decl;
TREE_TYPE (tmpl) = TREE_TYPE (decl); TREE_TYPE (tmpl) = TREE_TYPE (decl);
if (! ctx && !(is_friend && template_class_depth (info) > 0)) /* Push template declarations for global functions and types. Note
/* Note that we do not try to push a global template friend that we do not try to push a global template friend declared in a
declared in a template class; such a thing may well depend on template class; such a thing may well depend on the template
the template parameters of the class. */ 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); tmpl = pushdecl_namespace_level (tmpl);
if (primary) if (primary)
...@@ -2733,7 +2773,7 @@ comp_template_args (oldargs, newargs) ...@@ -2733,7 +2773,7 @@ comp_template_args (oldargs, newargs)
if (TREE_CODE (nt) == TREE_VEC) if (TREE_CODE (nt) == TREE_VEC)
{ {
/* For member templates */ /* For member templates */
if (comp_template_args (nt, ot)) if (comp_template_args (ot, nt))
continue; continue;
} }
else if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't') else if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't')
...@@ -2752,10 +2792,9 @@ comp_template_args (oldargs, newargs) ...@@ -2752,10 +2792,9 @@ comp_template_args (oldargs, newargs)
for the instantiation. */ for the instantiation. */
static char * static char *
mangle_class_name_for_template (name, parms, arglist, ctx) mangle_class_name_for_template (name, parms, arglist)
char *name; char *name;
tree parms, arglist; tree parms, arglist;
tree ctx;
{ {
static struct obstack scratch_obstack; static struct obstack scratch_obstack;
static char *scratch_firstobj; static char *scratch_firstobj;
...@@ -2767,37 +2806,13 @@ mangle_class_name_for_template (name, parms, arglist, ctx) ...@@ -2767,37 +2806,13 @@ mangle_class_name_for_template (name, parms, arglist, ctx)
obstack_free (&scratch_obstack, scratch_firstobj); obstack_free (&scratch_obstack, scratch_firstobj);
scratch_firstobj = obstack_alloc (&scratch_obstack, 1); 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 ccat(c) obstack_1grow (&scratch_obstack, (c));
#define advance
#define cat(s) obstack_grow (&scratch_obstack, (s), strlen (s)) #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); cat (name);
ccat ('<'); ccat ('<');
nparms = TREE_VEC_LENGTH (parms); nparms = TREE_VEC_LENGTH (parms);
arglist = innermost_args (arglist);
my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268); my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268);
for (i = 0; i < nparms; i++) for (i = 0; i < nparms; i++)
{ {
...@@ -2860,13 +2875,6 @@ mangle_class_name_for_template (name, parms, arglist, ctx) ...@@ -2860,13 +2875,6 @@ mangle_class_name_for_template (name, parms, arglist, ctx)
ccat ('>'); ccat ('>');
ccat ('\0'); ccat ('\0');
return (char *) obstack_base (&scratch_obstack); 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 static tree
...@@ -2874,22 +2882,18 @@ classtype_mangled_name (t) ...@@ -2874,22 +2882,18 @@ classtype_mangled_name (t)
tree t; tree t;
{ {
if (CLASSTYPE_TEMPLATE_INFO (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))) && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
{ {
tree name = DECL_NAME (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 char *mangled_name = mangle_class_name_for_template
(IDENTIFIER_POINTER (name), (IDENTIFIER_POINTER (name),
DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)), DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
CLASSTYPE_TI_ARGS (t), NULL_TREE); CLASSTYPE_TI_ARGS (t));
tree id = get_identifier (mangled_name); tree id = get_identifier (mangled_name);
IDENTIFIER_TEMPLATE (id) = name; IDENTIFIER_TEMPLATE (id) = name;
return id; return id;
...@@ -2967,21 +2971,28 @@ maybe_get_template_decl_from_type_decl (decl) ...@@ -2967,21 +2971,28 @@ maybe_get_template_decl_from_type_decl (decl)
parameters, find the desired type. parameters, find the desired type.
D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments. 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 (Actually ARGLIST may be either a TREE_LIST or a TREE_VEC. It will
to keep it from being reclaimed when the decl storage is reclaimed. 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 IN_DECL, if non-NULL, is the template declaration we are trying to
instantiate. 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 If the template class is really a local class in a template
function, then the FUNCTION_CONTEXT is the function in which it is function, then the FUNCTION_CONTEXT is the function in which it is
being instantiated. */ being instantiated. */
tree tree
lookup_template_class (d1, arglist, in_decl, context) lookup_template_class (d1, arglist, in_decl, context, entering_scope)
tree d1, arglist; tree d1, arglist;
tree in_decl; tree in_decl;
tree context; tree context;
int entering_scope;
{ {
tree template = NULL_TREE, parmlist; tree template = NULL_TREE, parmlist;
char *mangled_name; char *mangled_name;
...@@ -3070,56 +3081,116 @@ lookup_template_class (d1, arglist, in_decl, context) ...@@ -3070,56 +3081,116 @@ lookup_template_class (d1, arglist, in_decl, context)
TYPE_SIZE (parm) = 0; TYPE_SIZE (parm) = 0;
return parm; return parm;
} }
else if (PRIMARY_TEMPLATE_P (template) else
|| (TREE_CODE (TYPE_CONTEXT (TREE_TYPE (template)))
== FUNCTION_DECL))
{ {
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 <class T> struct S1 {
template <class U> struct S2 {};
template <class U> struct S2<U*> {};
};
we will be called with an ARGLIST of `U*', but the
TEMPLATE will be `template <class T> template
<class U> struct S1<T>::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);
}
my_friendly_assert (parm_depth == arg_depth, 0);
if (/* ARGLIST can be NULL_TREE if there are default arguments. */ /* Calculate the BOUND_ARGS. These will be the args that are
arglist != NULL_TREE actually tsubst'd into the definition to create the
&& TREE_CODE (arglist) == TREE_VEC instantiation. */
&& TREE_VEC_LENGTH (arglist) > 1 if (parm_depth > 1)
&& list_length (DECL_TEMPLATE_PARMS (template)) > 1)
{ {
/* We have multiple levels of arguments to coerce, at once. */ /* We have multiple levels of arguments to coerce, at once. */
tree new_args =
make_tree_vec (list_length (DECL_TEMPLATE_PARMS (template)));
int i; int i;
tree bound_args = make_tree_vec (parm_depth);
for (i = TREE_VEC_LENGTH (arglist) - 1, for (i = TREE_VEC_LENGTH (arglist) - 1,
t = DECL_TEMPLATE_PARMS (template); t = DECL_TEMPLATE_PARMS (template);
i >= 0 && t != NULL_TREE; i >= 0 && t != NULL_TREE;
--i, t = TREE_CHAIN (t)) --i, t = TREE_CHAIN (t))
TREE_VEC_ELT (new_args, i) = TREE_VEC_ELT (bound_args, i) =
coerce_template_parms (TREE_VALUE (t), coerce_template_parms (TREE_VALUE (t),
TREE_VEC_ELT (arglist, i), TREE_VEC_ELT (arglist, i),
template, 1, 1); template, 1, 1);
arglist = new_args; arglist = bound_args;
} }
else else
arglist = coerce_template_parms (parmlist, arglist
innermost_args (arglist, 0), = coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
innermost_args (arglist),
template, 1, 1); template, 1, 1);
if (arglist == error_mark_node) if (arglist == error_mark_node)
/* We were unable to bind the arguments. */
return error_mark_node; return error_mark_node;
if (uses_template_parms (arglist))
/* 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 T> class C { void f(C<T>); }
the `C<T>' 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))
{ {
tree found; found = template_type;
if (comp_template_args
(CLASSTYPE_TI_ARGS (TREE_TYPE (template)), arglist)) if (!entering_scope && PRIMARY_TEMPLATE_P (template))
found = TREE_TYPE (template); {
else 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 (!found)
{ {
for (found = DECL_TEMPLATE_INSTANTIATIONS (template); for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
found; found = TREE_CHAIN (found)) found; found = TREE_CHAIN (found))
{ if (comp_template_args (TREE_PURPOSE (found), arglist))
if (TI_USES_TEMPLATE_PARMS (found)
&& comp_template_args (TREE_PURPOSE (found), arglist))
break; break;
}
if (found) if (found)
found = TREE_VALUE (found); found = TREE_VALUE (found);
} }
...@@ -3130,101 +3201,65 @@ lookup_template_class (d1, arglist, in_decl, context) ...@@ -3130,101 +3201,65 @@ lookup_template_class (d1, arglist, in_decl, context)
obstack_free (&permanent_obstack, arglist); obstack_free (&permanent_obstack, arglist);
return found; return found;
} }
}
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)); /* Since we didn't find the type, we'll have to create it.
t = xref_tag_from_type (TREE_TYPE (template), id, 1); Since we'll be saving this type on the
DECL_TEMPLATE_INSTANTIATIONS list, it must be permanent. */
if (context != NULL_TREE) push_obstacks (&permanent_obstack, &permanent_obstack);
{
/* 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);
/* 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); 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));
}
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) /* Create a stub TYPE_DECL for it. */
{ type_decl = build_decl (TYPE_DECL, DECL_NAME (template), t);
int save_temp = processing_template_decl; SET_DECL_ARTIFICIAL (type_decl);
processing_template_decl = 0; DECL_CONTEXT (type_decl) = TYPE_CONTEXT (t);
t = xref_tag_from_type (TREE_TYPE (template), id, 0); DECL_SOURCE_FILE (type_decl)
processing_template_decl = save_temp; = DECL_SOURCE_FILE (TYPE_STUB_DECL (template_type));
} DECL_SOURCE_LINE (type_decl)
else = DECL_SOURCE_LINE (TYPE_STUB_DECL (template_type));
{ TYPE_STUB_DECL (t) = TYPE_NAME (t) = type_decl;
t = lookup_nested_type_by_name (ctx, id);
my_friendly_assert (t != NULL_TREE, 42); /* We're done with the permanent obstack, now. */
} pop_obstacks ();
}
/* Seems to be wanted. */ /* Seems to be wanted. */
CLASSTYPE_GOT_SEMICOLON (t) = 1; CLASSTYPE_GOT_SEMICOLON (t) = 1;
if (! CLASSTYPE_TEMPLATE_INFO (t)) /* Set up the template information. */
{
arglist = copy_to_permanent (arglist); arglist = copy_to_permanent (arglist);
CLASSTYPE_TEMPLATE_INFO (t) CLASSTYPE_TEMPLATE_INFO (t)
= perm_tree_cons (template, arglist, NULL_TREE); = perm_tree_cons (template, arglist, NULL_TREE);
DECL_TEMPLATE_INSTANTIATIONS (template) = perm_tree_cons DECL_TEMPLATE_INSTANTIATIONS (template) = perm_tree_cons
(arglist, t, DECL_TEMPLATE_INSTANTIATIONS (template)); (arglist, t, DECL_TEMPLATE_INSTANTIATIONS (template));
TI_USES_TEMPLATE_PARMS (DECL_TEMPLATE_INSTANTIATIONS (template))
= uses_template_parms (arglist);
SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t); SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
/* We need to set this again after CLASSTYPE_TEMPLATE_INFO is set up. */ /* Reset the name of the type, now that CLASSTYPE_TEMPLATE_INFO
DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t)) = id; 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)) if (! uses_template_parms (arglist))
DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t)) {
DECL_ASSEMBLER_NAME (type_decl)
= get_identifier (build_overload_name (t, 1, 1)); = get_identifier (build_overload_name (t, 1, 1));
if (flag_external_templates && ! uses_template_parms (arglist) if (flag_external_templates
&& CLASSTYPE_INTERFACE_KNOWN (TREE_TYPE (template)) && CLASSTYPE_INTERFACE_KNOWN (TREE_TYPE (template))
&& ! CLASSTYPE_INTERFACE_ONLY (TREE_TYPE (template))) && ! CLASSTYPE_INTERFACE_ONLY (TREE_TYPE (template)))
add_pending_template (t); add_pending_template (t);
}
if (uses_template_parms (arglist)) else
/* If the type makes use of template parameters, the /* If the type makes use of template parameters, the
code that generates debugging information will crash. */ code that generates debugging information will crash. */
DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1; 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 /* For each TEMPLATE_TYPE_PARM, TEMPLATE_TEMPLATE_PARM, or
TEMPLATE_PARM_INDEX in T, call FN with the parameter and the DATA. TEMPLATE_PARM_INDEX in T, call FN with the parameter and the DATA.
If FN returns non-zero, the iteration is terminated, and If FN returns non-zero, the iteration is terminated, and
...@@ -3626,32 +3661,26 @@ tsubst_friend_function (decl, args) ...@@ -3626,32 +3661,26 @@ tsubst_friend_function (decl, args)
tree template_id; tree template_id;
tree new_args; tree new_args;
tree tmpl; tree tmpl;
tree tinfo;
template_id template_id
= lookup_template_function (tsubst_expr (DECL_TI_TEMPLATE (decl), = lookup_template_function (tsubst_expr (DECL_TI_TEMPLATE (decl),
args, NULL_TREE), args, NULL_TREE),
tsubst (DECL_TI_ARGS (decl), tsubst (DECL_TI_ARGS (decl),
args, NULL_TREE)); args, NULL_TREE));
/* FIXME: The decl we create via the next tsubst be created on a
/* Temporarily remove the DECL_TEMPLATE_INFO so as not to temporary obstack. */
confuse tsubst. */
tinfo = DECL_TEMPLATE_INFO (decl);
DECL_TEMPLATE_INFO (decl) = NULL_TREE;
new_friend = tsubst (decl, args, NULL_TREE); new_friend = tsubst (decl, args, NULL_TREE);
DECL_TEMPLATE_INFO (decl) = tinfo; tmpl = determine_specialization (template_id, new_friend,
tmpl = determine_specialization (template_id,
new_friend,
&new_args, &new_args,
0, 1); /*need_member_template=*/0,
/*complain=*/1);
new_friend = instantiate_template (tmpl, new_args); new_friend = instantiate_template (tmpl, new_args);
goto done; 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 compiler, but is not an instantiation from the point of view of
the language. For example, we might have had: the language. For example, we might have had:
...@@ -3665,18 +3694,113 @@ tsubst_friend_function (decl, args) ...@@ -3665,18 +3694,113 @@ tsubst_friend_function (decl, args)
if (TREE_CODE (decl) == TEMPLATE_DECL) if (TREE_CODE (decl) == TEMPLATE_DECL)
DECL_USE_TEMPLATE (DECL_TEMPLATE_RESULT (new_friend)) = 0; 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)) if (DECL_NAMESPACE_SCOPE_P (new_friend))
{ {
tree old_decl;
tree new_friend_args;
if (TREE_CODE (new_friend) == TEMPLATE_DECL) if (TREE_CODE (new_friend) == TEMPLATE_DECL)
/* This declaration is a `primary' template. */ /* This declaration is a `primary' template. */
TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (new_friend)) DECL_PRIMARY_TEMPLATE (new_friend) = new_friend;
= new_friend;
new_friend = pushdecl_namespace_level (new_friend); /* We must save the DECL_TI_ARGS for NEW_FRIEND here because
} pushdecl may call duplicate_decls which will free NEW_FRIEND
else if (TYPE_SIZE (DECL_CONTEXT (new_friend))) if possible. */
new_friend_args = DECL_TI_ARGS (new_friend);
old_decl = pushdecl_namespace_level (new_friend);
if (old_decl != new_friend)
{ {
/* Check to see that the declaration is really present, and, /* This new friend declaration matched an existing
declaration. For example, given:
template <class T> void f(T);
template <class U> class C {
template <class T> 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 T> class C {
friend void f(T) {}
};
when `C<int>' 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));
}
/* 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)))
{
/* Check to see that the declaration is really present, and,
possibly obtain an improved declaration. */ possibly obtain an improved declaration. */
tree fn = check_classfn (DECL_CONTEXT (new_friend), tree fn = check_classfn (DECL_CONTEXT (new_friend),
new_friend); new_friend);
...@@ -3709,9 +3833,15 @@ tsubst_friend_class (friend_tmpl, args) ...@@ -3709,9 +3833,15 @@ tsubst_friend_class (friend_tmpl, args)
if (tmpl != NULL_TREE && DECL_CLASS_TEMPLATE_P (tmpl)) if (tmpl != NULL_TREE && DECL_CLASS_TEMPLATE_P (tmpl))
{ {
/* The friend template has already been declared. Just /* The friend template has already been declared. Just
check to see that the declarations match. */ check to see that the declarations match, and install any new
redeclare_class_template (TREE_TYPE (tmpl), default parameters. We must tsubst the default parameters,
DECL_TEMPLATE_PARMS (friend_tmpl)); 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); friend_type = TREE_TYPE (tmpl);
} }
else else
...@@ -3740,32 +3870,19 @@ tree ...@@ -3740,32 +3870,19 @@ tree
instantiate_class_template (type) instantiate_class_template (type)
tree type; tree type;
{ {
tree template, template_info, args, pattern, t, *field_chain; tree template, args, pattern, t, *field_chain;
tree typedecl, outer_args; tree typedecl;
if (type == error_mark_node) if (type == error_mark_node)
return error_mark_node; return error_mark_node;
template_info = CLASSTYPE_TEMPLATE_INFO (type);
if (TYPE_BEING_DEFINED (type) || TYPE_SIZE (type)) if (TYPE_BEING_DEFINED (type) || TYPE_SIZE (type))
return 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); my_friendly_assert (TREE_CODE (template) == TEMPLATE_DECL, 279);
args = TI_ARGS (template_info); t = most_specialized_class (template, args);
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);
if (t == error_mark_node) if (t == error_mark_node)
{ {
...@@ -3774,7 +3891,7 @@ instantiate_class_template (type) ...@@ -3774,7 +3891,7 @@ instantiate_class_template (type)
for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t; t = TREE_CHAIN (t)) for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t; t = TREE_CHAIN (t))
{ {
if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
args, outer_args)) args))
{ {
cp_error_at ("%s %+#T", str, TREE_TYPE (t)); cp_error_at ("%s %+#T", str, TREE_TYPE (t));
str = " "; str = " ";
...@@ -3792,8 +3909,32 @@ instantiate_class_template (type) ...@@ -3792,8 +3909,32 @@ instantiate_class_template (type)
return type; return type;
if (t) 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 <class T> struct S {};
template <class T> struct S<T*> {};
and supposing that we are instantiating S<int*>, 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 (pedantic && uses_template_parms (args))
/* If there are still template parameters amongst the args, then /* If there are still template parameters amongst the args, then
...@@ -3802,11 +3943,6 @@ instantiate_class_template (type) ...@@ -3802,11 +3943,6 @@ instantiate_class_template (type)
value that results in a specialization being used. */ value that results in a specialization being used. */
return type; 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; TYPE_BEING_DEFINED (type) = 1;
if (! push_tinst_level (type)) if (! push_tinst_level (type))
...@@ -3815,8 +3951,10 @@ instantiate_class_template (type) ...@@ -3815,8 +3951,10 @@ instantiate_class_template (type)
maybe_push_to_top_level (uses_template_parms (type)); maybe_push_to_top_level (uses_template_parms (type));
pushclass (type, 0); pushclass (type, 0);
if (outer_args) /* We must copy the arguments to the permanent obstack since
args = add_to_template_args (outer_args, args); 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) if (flag_external_templates)
{ {
...@@ -3936,11 +4074,12 @@ instantiate_class_template (type) ...@@ -3936,11 +4074,12 @@ instantiate_class_template (type)
for (t = CLASSTYPE_TAGS (pattern); t; t = TREE_CHAIN (t)) for (t = CLASSTYPE_TAGS (pattern); t; t = TREE_CHAIN (t))
{ {
tree tag = TREE_VALUE (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) if (TREE_CODE (tag) == ENUMERAL_TYPE)
{ {
(void) tsubst_enum (tag, args, field_chain); newtag = tsubst_enum (tag, args, field_chain);
while (*field_chain) while (*field_chain)
{ {
DECL_FIELD_CONTEXT (*field_chain) = type; DECL_FIELD_CONTEXT (*field_chain) = type;
...@@ -3948,7 +4087,14 @@ instantiate_class_template (type) ...@@ -3948,7 +4087,14 @@ instantiate_class_template (type)
} }
} }
else 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. */ /* Don't replace enum constants here. */
...@@ -4014,14 +4160,16 @@ instantiate_class_template (type) ...@@ -4014,14 +4160,16 @@ instantiate_class_template (type)
tree friend_type = TREE_VALUE (t); tree friend_type = TREE_VALUE (t);
tree new_friend_type; 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 /* The call to xref_tag_from_type does injection for friend
classes. */ classes. */
new_friend_type = new_friend_type =
xref_tag_from_type (tsubst (friend_type, args, NULL_TREE), xref_tag_from_type (friend_type, NULL_TREE, 1);
NULL_TREE, 1);
else
new_friend_type = tsubst_friend_class (friend_type, args);
if (TREE_CODE (friend_type) == TEMPLATE_DECL) if (TREE_CODE (friend_type) == TEMPLATE_DECL)
/* Trick make_friend_class into realizing that the friend /* Trick make_friend_class into realizing that the friend
...@@ -4138,20 +4286,14 @@ maybe_fold_nontype_arg (arg) ...@@ -4138,20 +4286,14 @@ maybe_fold_nontype_arg (arg)
} }
/* Return the TREE_VEC with the arguments for the innermost template header, /* 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. 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. */
tree tree
innermost_args (args, is_spec) innermost_args (args)
tree args; tree args;
int is_spec;
{ {
if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)) return TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args));
return TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1 - is_spec);
return args;
} }
/* Substitute ARGS into the vector of template arguments T. */ /* Substitute ARGS into the vector of template arguments T. */
...@@ -4189,6 +4331,121 @@ tsubst_template_arg_vector (t, args) ...@@ -4189,6 +4331,121 @@ tsubst_template_arg_vector (t, args)
return t; 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 <class T> template <class U>
template <T*, U, class V>' and ARGS is {{int}, {double}} then the
result will be `template <int*, double, class V>'. */
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 <class T> struct S;
template <class T, class U> void f(T, U) { S<U> su; }
and supposing that we are instantiating f<int, double>,
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 /* Take the tree structure T and replace template parameters used therein
with the argument vector ARGS. IN_DECL is an associated decl for with the argument vector ARGS. IN_DECL is an associated decl for
diagnostics. diagnostics.
...@@ -4226,52 +4483,9 @@ tsubst (t, args, in_decl) ...@@ -4226,52 +4483,9 @@ tsubst (t, args, in_decl)
switch (TREE_CODE (t)) switch (TREE_CODE (t))
{ {
case RECORD_TYPE: 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: case UNION_TYPE:
if (uses_template_parms (t)) return tsubst_aggr_type (t, args, in_decl, /*entering_scope=*/0);
{
tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl);
tree context;
tree r;
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 ERROR_MARK:
case IDENTIFIER_NODE: case IDENTIFIER_NODE:
case OP_IDENTIFIER: case OP_IDENTIFIER:
...@@ -4287,7 +4501,8 @@ tsubst (t, args, in_decl) ...@@ -4287,7 +4501,8 @@ tsubst (t, args, in_decl)
case ENUMERAL_TYPE: 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) if (ctx == NULL_TREE || TREE_CODE (ctx) == NAMESPACE_DECL)
return t; return t;
else if (ctx == current_function_decl) else if (ctx == current_function_decl)
...@@ -4345,19 +4560,9 @@ tsubst (t, args, in_decl) ...@@ -4345,19 +4560,9 @@ tsubst (t, args, in_decl)
{ {
tree arg = NULL_TREE; tree arg = NULL_TREE;
if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)) levels = TMPL_ARGS_DEPTH (args);
{
levels = TREE_VEC_LENGTH (args);
if (level <= levels) if (level <= levels)
arg = TREE_VEC_ELT arg = TMPL_ARG (args, level, idx);
(TREE_VEC_ELT (args, level - 1), idx);
}
else
{
levels = 1;
if (level == 1)
arg = TREE_VEC_ELT (args, idx);
}
if (arg != NULL_TREE) if (arg != NULL_TREE)
{ {
...@@ -4385,7 +4590,8 @@ tsubst (t, args, in_decl) ...@@ -4385,7 +4590,8 @@ tsubst (t, args, in_decl)
r = lookup_template_class (DECL_NAME (arg), r = lookup_template_class (DECL_NAME (arg),
argvec, in_decl, argvec, in_decl,
DECL_CONTEXT (arg)); DECL_CONTEXT (arg),
/*entering_scope=*/0);
return cp_build_type_variant (r, TYPE_READONLY (t), return cp_build_type_variant (r, TYPE_READONLY (t),
TYPE_VOLATILE (t)); TYPE_VOLATILE (t));
} }
...@@ -4453,8 +4659,21 @@ tsubst (t, args, in_decl) ...@@ -4453,8 +4659,21 @@ tsubst (t, args, in_decl)
if (!is_template_template_parm) if (!is_template_template_parm)
{ {
/* We might already have an instance of this template. */ /* We might already have an instance of this template.
spec = retrieve_specialization (t, args); 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) if (spec != NULL_TREE)
return spec; return spec;
} }
...@@ -4477,10 +4696,12 @@ tsubst (t, args, in_decl) ...@@ -4477,10 +4696,12 @@ tsubst (t, args, in_decl)
return tmpl; return tmpl;
} }
DECL_CONTEXT (tmpl) = tsubst (DECL_CONTEXT (t), DECL_CONTEXT (tmpl)
args, in_decl); = tsubst_aggr_type (DECL_CONTEXT (t), args, in_decl,
DECL_CLASS_CONTEXT (tmpl) = tsubst (DECL_CLASS_CONTEXT (t), /*entering_scope=*/1);
args, in_decl); 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); DECL_TEMPLATE_INFO (tmpl) = build_tree_list (t, args);
if (TREE_CODE (decl) == TYPE_DECL) if (TREE_CODE (decl) == TYPE_DECL)
...@@ -4489,6 +4710,7 @@ tsubst (t, args, in_decl) ...@@ -4489,6 +4710,7 @@ tsubst (t, args, in_decl)
TREE_TYPE (tmpl) = new_type; TREE_TYPE (tmpl) = new_type;
CLASSTYPE_TI_TEMPLATE (new_type) = tmpl; CLASSTYPE_TI_TEMPLATE (new_type) = tmpl;
DECL_RESULT (tmpl) = TYPE_MAIN_DECL (new_type); DECL_RESULT (tmpl) = TYPE_MAIN_DECL (new_type);
DECL_TI_ARGS (tmpl) = CLASSTYPE_TI_ARGS (new_type);
} }
else else
{ {
...@@ -4496,44 +4718,18 @@ tsubst (t, args, in_decl) ...@@ -4496,44 +4718,18 @@ tsubst (t, args, in_decl)
DECL_RESULT (tmpl) = new_decl; DECL_RESULT (tmpl) = new_decl;
DECL_TI_TEMPLATE (new_decl) = tmpl; DECL_TI_TEMPLATE (new_decl) = tmpl;
TREE_TYPE (tmpl) = TREE_TYPE (new_decl); 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); 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 /* The template parameters for this new template are all the
template parameters for the old template, except the template parameters for the old template, except the
outermost level of parameters. */ outermost level of parameters. */
for (new_parms = &DECL_TEMPLATE_PARMS (tmpl), DECL_TEMPLATE_PARMS (tmpl)
parms = DECL_TEMPLATE_PARMS (t); = tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args);
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);
}
if (PRIMARY_TEMPLATE_P (t)) if (PRIMARY_TEMPLATE_P (t))
DECL_PRIMARY_TEMPLATE (tmpl) = tmpl; DECL_PRIMARY_TEMPLATE (tmpl) = tmpl;
...@@ -4542,12 +4738,6 @@ tsubst (t, args, in_decl) ...@@ -4542,12 +4738,6 @@ tsubst (t, args, in_decl)
if (TREE_CODE (decl) == TYPE_DECL) if (TREE_CODE (decl) == TYPE_DECL)
return tmpl; 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); for (spec = DECL_TEMPLATE_SPECIALIZATIONS (t);
spec != NULL_TREE; spec != NULL_TREE;
spec = TREE_CHAIN (spec)) spec = TREE_CHAIN (spec))
...@@ -4588,17 +4778,22 @@ tsubst (t, args, in_decl) ...@@ -4588,17 +4778,22 @@ tsubst (t, args, in_decl)
no concern to us. */ no concern to us. */
continue; continue;
spec_args = tsubst (DECL_TI_ARGS (fn), args, if (TREE_CODE (fn) != TEMPLATE_DECL)
in_decl); /* A full specialization. There's no need to record
new_fn = tsubst (DECL_RESULT (fn), args, that here. */
in_decl); continue;
DECL_TEMPLATE_SPECIALIZATIONS (tmpl) =
perm_tree_cons (spec_args, new_fn, spec_args = tsubst (DECL_TI_ARGS (fn), args, in_decl);
DECL_TEMPLATE_SPECIALIZATIONS (tmpl)); 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. */ /* Record this partial instantiation. */
register_specialization (tmpl, t, args); register_specialization (tmpl, t,
DECL_TI_ARGS (DECL_RESULT (tmpl)));
return tmpl; return tmpl;
} }
...@@ -4608,16 +4803,53 @@ tsubst (t, args, in_decl) ...@@ -4608,16 +4803,53 @@ tsubst (t, args, in_decl)
tree r = NULL_TREE; tree r = NULL_TREE;
tree ctx; tree ctx;
tree argvec; tree argvec;
tree tmpl = NULL_TREE; tree gen_tmpl;
int member; 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 <class T> struct S {
friend void f<int>(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_CLASS_SCOPE_P (t))
{ {
if (DECL_NAME (t) == constructor_name (DECL_CONTEXT (t))) if (DECL_NAME (t) == constructor_name (DECL_CONTEXT (t)))
member = 2; member = 2;
else else
member = 1; member = 1;
ctx = tsubst (DECL_CLASS_CONTEXT (t), args, t); ctx = tsubst_aggr_type (DECL_CLASS_CONTEXT (t), args, t,
/*entering_scope=*/1);
} }
else else
{ {
...@@ -4626,28 +4858,6 @@ tsubst (t, args, in_decl) ...@@ -4626,28 +4858,6 @@ tsubst (t, args, in_decl)
} }
type = tsubst (type, 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 /* We do NOT check for matching decls pushed separately at this
point, as they may not represent instantiations of this point, as they may not represent instantiations of this
template, and in any case are considered separate under the template, and in any case are considered separate under the
...@@ -4659,7 +4869,7 @@ tsubst (t, args, in_decl) ...@@ -4659,7 +4869,7 @@ tsubst (t, args, in_decl)
TREE_TYPE (r) = type; TREE_TYPE (r) = type;
DECL_CONTEXT (r) 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; DECL_CLASS_CONTEXT (r) = ctx;
if (member && !strncmp (OPERATOR_TYPENAME_FORMAT, if (member && !strncmp (OPERATOR_TYPENAME_FORMAT,
...@@ -4693,122 +4903,48 @@ tsubst (t, args, in_decl) ...@@ -4693,122 +4903,48 @@ tsubst (t, args, in_decl)
if (IDENTIFIER_OPNAME_P (DECL_NAME (r))) if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r)); grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
/* Set up the DECL_TEMPLATE_INFO for R and compute its mangled
name. There's no need to do this in the special friend
case mentioned above where GEN_TMPL is NULL. */
if (gen_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)) if (DECL_DESTRUCTOR_P (t))
DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx); DECL_ASSEMBLER_NAME (r) = build_destructor_name (ctx);
else else
{ {
/* Instantiations of template functions must be mangled /* Instantiations of template functions must be mangled
specially, in order to conform to 14.5.5.1 specially, in order to conform to 14.5.5.1
[temp.over.link]. We use in_decl below rather than [temp.over.link]. */
DECL_TI_TEMPLATE (r) because the latter is set to tree tmpl = DECL_TI_TEMPLATE (t);
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 /* TMPL will be NULL if this is a specialization of a
member function of a template class. */ member function of a template class. */
if (name_mangling_version < 1 if (name_mangling_version < 1
|| tmpl == NULL_TREE || tmpl == NULL_TREE
|| (member && !is_member_template (tmpl) || (member && !is_member_template (tmpl)
&& !DECL_TEMPLATE_INFO (tmpl))) && !DECL_TEMPLATE_INFO (tmpl)))
{ set_mangled_name_for_decl (r);
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);
DECL_ASSEMBLER_NAME (r)
= build_decl_overload (DECL_NAME (r), arg_types,
member);
}
else else
{ set_mangled_name_for_template_decl (r);
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);
}
else
{
/* If the template is a specialization, then it is
a member template specialization. We have
something like:
template <class T> struct S {
template <int i> void f();
template <> void f<7>();
};
and now we are forming S<double>::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);
}
}
DECL_RTL (r) = 0; DECL_RTL (r) = 0;
make_decl_rtl (r, NULL_PTR, 1); make_decl_rtl (r, NULL_PTR, 1);
if (DECL_TEMPLATE_INFO (t) != NULL_TREE) /* Like grokfndecl. If we don't do this, pushdecl will
{ mess up our TREE_CHAIN because it doesn't find a
DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE); previous decl. Sigh. */
/* 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 if (member
&& IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r)) == NULL_TREE) && (IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r))
== NULL_TREE))
SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r); SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
}
return r; return r;
} }
...@@ -4861,18 +4997,25 @@ tsubst (t, args, in_decl) ...@@ -4861,18 +4997,25 @@ tsubst (t, args, in_decl)
case VAR_DECL: case VAR_DECL:
{ {
tree r; tree r;
tree ctx = tsubst_copy (DECL_CONTEXT (t), args, in_decl); tree argvec;
tree gen_tmpl;
tree spec;
tree tmpl;
tree ctx = tsubst_aggr_type (DECL_CONTEXT (t), args, in_decl,
/*entering_scope=*/1);
/* Do we already have this instantiation? */ /* Nobody should be tsubst'ing into non-template variables. */
if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)) my_friendly_assert (DECL_LANG_SPECIFIC (t)
{ && DECL_TEMPLATE_INFO (t) != NULL_TREE, 0);
tree tmpl = DECL_TI_TEMPLATE (t);
tree decls = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
for (; decls; decls = TREE_CHAIN (decls)) /* Check to see if we already have this specialization. */
if (DECL_CONTEXT (TREE_VALUE (decls)) == ctx) tmpl = DECL_TI_TEMPLATE (t);
return TREE_VALUE (decls); 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); r = copy_node (t);
TREE_TYPE (r) = type; TREE_TYPE (r) = type;
...@@ -4884,26 +5027,15 @@ tsubst (t, args, in_decl) ...@@ -4884,26 +5027,15 @@ tsubst (t, args, in_decl)
/* Don't try to expand the initializer until someone tries to use /* Don't try to expand the initializer until someone tries to use
this variable; otherwise we run into circular dependencies. */ this variable; otherwise we run into circular dependencies. */
DECL_INITIAL (r) = NULL_TREE; DECL_INITIAL (r) = NULL_TREE;
DECL_RTL (r) = 0; DECL_RTL (r) = 0;
DECL_SIZE (r) = 0; DECL_SIZE (r) = 0;
if (DECL_LANG_SPECIFIC (r))
{
copy_lang_decl (r); copy_lang_decl (r);
DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (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); DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
*declsp = perm_tree_cons (argvec, r, *declsp);
SET_DECL_IMPLICIT_INSTANTIATION (r); SET_DECL_IMPLICIT_INSTANTIATION (r);
} register_specialization (r, gen_tmpl, argvec);
TREE_CHAIN (r) = NULL_TREE; TREE_CHAIN (r) = NULL_TREE;
if (TREE_CODE (type) == VOID_TYPE) if (TREE_CODE (type) == VOID_TYPE)
cp_error_at ("instantiation of `%D' as type void", r); cp_error_at ("instantiation of `%D' as type void", r);
...@@ -5136,7 +5268,8 @@ tsubst (t, args, in_decl) ...@@ -5136,7 +5268,8 @@ tsubst (t, args, in_decl)
case TYPENAME_TYPE: 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); tree f = tsubst_copy (TYPENAME_TYPE_FULLNAME (t), args, in_decl);
f = make_typename_type (ctx, f); f = make_typename_type (ctx, f);
return cp_build_type_variant return cp_build_type_variant
...@@ -5234,7 +5367,8 @@ tsubst_copy (t, args, in_decl) ...@@ -5234,7 +5367,8 @@ tsubst_copy (t, args, in_decl)
if (TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL) if (TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL)
return lookup_name (DECL_NAME (t), 0); 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)) if (ctx != DECL_CONTEXT (t))
return lookup_field (ctx, DECL_NAME (t), 0, 0); return lookup_field (ctx, DECL_NAME (t), 0, 0);
} }
...@@ -5709,58 +5843,77 @@ tsubst_expr (t, args, in_decl) ...@@ -5709,58 +5843,77 @@ tsubst_expr (t, args, in_decl)
return NULL_TREE; return NULL_TREE;
} }
/* Instantiate the indicated variable of function template TMPL with
the template arguments in TARG_PTR. */
tree tree
instantiate_template (tmpl, targ_ptr) instantiate_template (tmpl, targ_ptr)
tree tmpl, targ_ptr; tree tmpl, targ_ptr;
{ {
tree fndecl; tree fndecl;
tree gen_tmpl;
tree spec;
int i, len; int i, len;
struct obstack *old_fmp_obstack; struct obstack *old_fmp_obstack;
extern struct obstack *function_maybepermanent_obstack; extern struct obstack *function_maybepermanent_obstack;
tree inner_args;
if (tmpl == error_mark_node) if (tmpl == error_mark_node)
return error_mark_node; return error_mark_node;
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283); my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
/* Check to see if we already have this specialization. This does work /* Check to see if we already have this specialization. */
for member template specializations; the list is set up from the spec = retrieve_specialization (tmpl, targ_ptr);
tsubst TEMPLATE_DECL case when the containing class is instantiated. */ if (spec != NULL_TREE)
if (DECL_FUNCTION_TEMPLATE_P (tmpl)) 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) if (spec != NULL_TREE)
return spec; return spec;
} }
else
gen_tmpl = tmpl;
push_obstacks (&permanent_obstack, &permanent_obstack); push_obstacks (&permanent_obstack, &permanent_obstack);
old_fmp_obstack = function_maybepermanent_obstack; old_fmp_obstack = function_maybepermanent_obstack;
function_maybepermanent_obstack = &permanent_obstack; function_maybepermanent_obstack = &permanent_obstack;
len = DECL_NTPARMS (tmpl); len = DECL_NTPARMS (gen_tmpl);
inner_args = innermost_args (targ_ptr);
i = len; i = len;
while (i--) 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') if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
{ {
tree nt = target_type (t); tree nt = target_type (t);
if (IS_AGGR_TYPE (nt) && decl_function_context (TYPE_MAIN_DECL (nt))) 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 ("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; fndecl = error_mark_node;
goto out; goto out;
} }
} }
TREE_VEC_ELT (targ_ptr, i) = copy_to_permanent (t);
} }
targ_ptr = copy_to_permanent (targ_ptr); targ_ptr = copy_to_permanent (targ_ptr);
/* substitute template parameters */ /* 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) if (flag_external_templates)
add_pending_template (fndecl); add_pending_template (fndecl);
...@@ -6682,15 +6835,11 @@ more_specialized (pat1, pat2, explicit_args) ...@@ -6682,15 +6835,11 @@ more_specialized (pat1, pat2, explicit_args)
targs = get_bindings_overload (pat1, pat2, explicit_args); targs = get_bindings_overload (pat1, pat2, explicit_args);
if (targs) if (targs)
{
--winner; --winner;
}
targs = get_bindings_overload (pat2, pat1, explicit_args); targs = get_bindings_overload (pat2, pat1, explicit_args);
if (targs) if (targs)
{
++winner; ++winner;
}
return winner; return winner;
} }
...@@ -6708,15 +6857,13 @@ more_specialized_class (pat1, pat2) ...@@ -6708,15 +6857,13 @@ more_specialized_class (pat1, pat2)
tree targs; tree targs;
int winner = 0; int winner = 0;
targs = get_class_bindings targs = get_class_bindings (TREE_VALUE (pat1), TREE_PURPOSE (pat1),
(TREE_VALUE (pat1), TREE_PURPOSE (pat1), TREE_PURPOSE (pat2));
TREE_PURPOSE (pat2), NULL_TREE);
if (targs) if (targs)
--winner; --winner;
targs = get_class_bindings targs = get_class_bindings (TREE_VALUE (pat2), TREE_PURPOSE (pat2),
(TREE_VALUE (pat2), TREE_PURPOSE (pat2), TREE_PURPOSE (pat1));
TREE_PURPOSE (pat1), NULL_TREE);
if (targs) if (targs)
++winner; ++winner;
...@@ -6771,8 +6918,7 @@ get_bindings_real (fn, decl, explicit_args, check_rettype) ...@@ -6771,8 +6918,7 @@ get_bindings_real (fn, decl, explicit_args, check_rettype)
if (check_rettype) if (check_rettype)
{ {
/* Check to see that the resulting return type is also OK. */ /* Check to see that the resulting return type is also OK. */
tree t = tsubst (TREE_TYPE (TREE_TYPE (fn)), tree t = tsubst (TREE_TYPE (TREE_TYPE (fn)), targs,
complete_template_args (fn, targs, 1),
NULL_TREE); NULL_TREE);
if (!comptypes (t, TREE_TYPE (TREE_TYPE (decl)), 1)) if (!comptypes (t, TREE_TYPE (TREE_TYPE (decl)), 1))
...@@ -6800,18 +6946,29 @@ get_bindings_overload (fn, decl, explicit_args) ...@@ -6800,18 +6946,29 @@ get_bindings_overload (fn, decl, explicit_args)
return get_bindings_real (fn, decl, explicit_args, 0); 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 <class T, class U> struct S {};
template <class T> struct S<T*, int> {};
Then, suppose we want to get `S<double*, int>'. 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 static tree
get_class_bindings (tparms, parms, args, outer_args) get_class_bindings (tparms, parms, args)
tree tparms, parms, args, outer_args; tree tparms, parms, args;
{ {
int i, ntparms = TREE_VEC_LENGTH (tparms); int i, ntparms = TREE_VEC_LENGTH (tparms);
tree vec = make_temp_vec (ntparms); tree vec = make_temp_vec (ntparms);
if (outer_args) args = innermost_args (args);
{
tparms = tsubst (tparms, outer_args, NULL_TREE);
parms = tsubst (parms, outer_args, NULL_TREE);
}
for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
{ {
...@@ -6841,27 +6998,25 @@ tree ...@@ -6841,27 +6998,25 @@ tree
most_specialized (fns, decl, explicit_args) most_specialized (fns, decl, explicit_args)
tree fns, decl, explicit_args; tree fns, decl, explicit_args;
{ {
tree fn, champ, args, *p; tree candidates = NULL_TREE;
tree fn, champ, args;
int fate; 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) if (args)
{ candidates = scratch_tree_cons (NULL_TREE, candidate,
p = &TREE_CHAIN (*p); candidates);
}
else
*p = TREE_CHAIN (*p);
} }
if (! fns) if (!candidates)
return NULL_TREE; return NULL_TREE;
fn = fns; champ = TREE_VALUE (candidates);
champ = TREE_VALUE (fn); for (fn = TREE_CHAIN (candidates); fn; fn = TREE_CHAIN (fn))
fn = TREE_CHAIN (fn);
for (; fn; fn = TREE_CHAIN (fn))
{ {
fate = more_specialized (champ, TREE_VALUE (fn), explicit_args); fate = more_specialized (champ, TREE_VALUE (fn), explicit_args);
if (fate == 1) if (fate == 1)
...@@ -6878,7 +7033,7 @@ most_specialized (fns, decl, explicit_args) ...@@ -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); fate = more_specialized (champ, TREE_VALUE (fn), explicit_args);
if (fate != 1) if (fate != 1)
...@@ -6888,21 +7043,50 @@ most_specialized (fns, decl, explicit_args) ...@@ -6888,21 +7043,50 @@ most_specialized (fns, decl, explicit_args)
return champ; return champ;
} }
/* Return the most specialized of the class template specializations in /* If DECL is a specialization of some template, return the most
SPECS that can produce an instantiation matching ARGS. */ general such template. For example, given:
template <class T> struct S { template <class U> void f(U); };
if TMPL is `template <class U> void S<int>::f(U)' this will return
the full template. This function will not trace past partial
specializations, however. For example, given in addition:
template <class T> struct S<T*> { template <class U> void f(U); };
if TMPL is `template <class U> void S<int*>::f(U)' this will return
`template <class T> template <class U> S<T*>::f(U)'. */
tree
most_general_template (decl)
tree decl;
{
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 tree
most_specialized_class (specs, mainargs, outer_args) most_specialized_class (tmpl, args)
tree specs, mainargs, outer_args; tree tmpl;
tree args;
{ {
tree list = NULL_TREE, t, args, champ; tree list = NULL_TREE;
tree t;
tree champ;
int fate; 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), tree spec_args
mainargs, outer_args); = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args);
if (args) if (spec_args)
{ {
list = decl_tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list); list = decl_tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list);
TREE_TYPE (list) = TREE_TYPE (t); TREE_TYPE (list) = TREE_TYPE (t);
...@@ -7108,9 +7292,10 @@ do_type_instantiation (t, storage) ...@@ -7108,9 +7292,10 @@ do_type_instantiation (t, storage)
} }
} }
/* Given a function DECL, which is a specialization of TEMP, modify /* Given a function DECL, which is a specialization of TMPL, modify
DECL to be a re-instantiation of TEMPL with the same template DECL to be a re-instantiation of TMPL with the same template
arguments. 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: One reason for doing this is a scenario like this:
...@@ -7136,18 +7321,27 @@ regenerate_decl_from_template (decl, tmpl) ...@@ -7136,18 +7321,27 @@ regenerate_decl_from_template (decl, tmpl)
tree save_ti; tree save_ti;
tree code_pattern; tree code_pattern;
tree new_decl; tree new_decl;
tree gen_tmpl;
int unregistered;
args = DECL_TI_ARGS (decl); args = DECL_TI_ARGS (decl);
code_pattern = DECL_TEMPLATE_RESULT (tmpl); code_pattern = DECL_TEMPLATE_RESULT (tmpl);
/* Trick tsubst into giving us a new decl. CODE_PATTERN must be the /* Unregister the specialization so that when we tsubst we will not
most distant ancestor of DECL, since that's the one that will just return DECL. We don't have to unregister DECL from TMPL
actually be altered by a redefinition. */ because if would only be registered there if it were a partial
save_ti = DECL_TEMPLATE_INFO (code_pattern); instantiation of a specialization, which it isn't: it's a full
DECL_TEMPLATE_INFO (code_pattern) = NULL_TREE; 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); 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) if (TREE_CODE (decl) == VAR_DECL)
{ {
...@@ -7160,21 +7354,29 @@ regenerate_decl_from_template (decl, tmpl) ...@@ -7160,21 +7354,29 @@ regenerate_decl_from_template (decl, tmpl)
} }
if (TREE_CODE (decl) == FUNCTION_DECL) if (TREE_CODE (decl) == FUNCTION_DECL)
{
/* Convince duplicate_decls to use the DECL_ARGUMENTS from the /* Convince duplicate_decls to use the DECL_ARGUMENTS from the
new decl. */ new decl. */
DECL_INITIAL (new_decl) = error_mark_node; DECL_INITIAL (new_decl) = error_mark_node;
if (DECL_TEMPLATE_SPECIALIZATION (new_decl) /* The immediate parent of the new template is still whatever it was
&& !DECL_TEMPLATE_INFO (new_decl)) before, even though tsubst sets DECL_TI_TEMPLATE up as the most
/* Set up the information about what is being specialized. */ general template. We also reset the DECL_ASSEMBLER_NAME since
DECL_TEMPLATE_INFO (new_decl) = DECL_TEMPLATE_INFO (decl); 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); duplicate_decls (new_decl, decl);
if (TREE_CODE (decl) == FUNCTION_DECL) if (TREE_CODE (decl) == FUNCTION_DECL)
DECL_INITIAL (new_decl) = NULL_TREE; 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. */ /* Produce the definition of D, a _DECL generated from a template. */
...@@ -7183,17 +7385,41 @@ tree ...@@ -7183,17 +7385,41 @@ tree
instantiate_decl (d) instantiate_decl (d)
tree d; tree d;
{ {
tree ti = DECL_TEMPLATE_INFO (d); tree tmpl = DECL_TI_TEMPLATE (d);
tree tmpl = TI_TEMPLATE (ti); tree args = DECL_TI_ARGS (d);
tree args = TI_ARGS (ti);
tree td; tree td;
tree decl_pattern, code_pattern; tree code_pattern;
tree spec;
tree gen_tmpl;
int nested = in_function_p (); int nested = in_function_p ();
int d_defined;
int pattern_defined; int pattern_defined;
int line = lineno; int line = lineno;
char *file = input_filename; 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; for (td = tmpl;
DECL_TEMPLATE_INSTANTIATION (td) DECL_TEMPLATE_INSTANTIATION (td)
/* This next clause handles friend templates defined inside /* This next clause handles friend templates defined inside
...@@ -7205,38 +7431,12 @@ instantiate_decl (d) ...@@ -7205,38 +7431,12 @@ instantiate_decl (d)
) )
td = DECL_TI_TEMPLATE (td); 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); code_pattern = DECL_TEMPLATE_RESULT (td);
if (TREE_CODE (d) == FUNCTION_DECL) 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 else
{
d_defined = ! DECL_IN_AGGR_P (d);
pattern_defined = ! DECL_IN_AGGR_P (code_pattern); 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;
push_to_top_level (); push_to_top_level ();
lineno = DECL_SOURCE_LINE (d); lineno = DECL_SOURCE_LINE (d);
...@@ -7481,3 +7681,148 @@ tsubst_enum (tag, args, field_chain) ...@@ -7481,3 +7681,148 @@ tsubst_enum (tag, args, field_chain)
return newtag; 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 <class T> T f(T);
both PARMS and RET_TYPE should be `T' even if DECL is `int f(int)'.
A more subtle example is:
template <class T> struct S { template <class U> void f(T, U); }
Here, if DECL is `void S<int>::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;
}
...@@ -1235,18 +1235,7 @@ begin_class_definition (t) ...@@ -1235,18 +1235,7 @@ begin_class_definition (t)
push_template_decl (TYPE_STUB_DECL (t)); push_template_decl (TYPE_STUB_DECL (t));
pushclass (t, 0); pushclass (t, 0);
TYPE_BEING_DEFINED (t) = 1; TYPE_BEING_DEFINED (t) = 1;
if (IS_AGGR_TYPE (t) && CLASSTYPE_USE_TEMPLATE (t)) maybe_process_partial_specialization (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);
}
/* Reset the interface data, at the earliest possible /* Reset the interface data, at the earliest possible
moment, as it might have been set via a class foo; moment, as it might have been set via a class foo;
before. */ before. */
...@@ -1378,6 +1367,15 @@ finish_member_class_template (parms, types) ...@@ -1378,6 +1367,15 @@ finish_member_class_template (parms, types)
tree parms; tree parms;
tree types; 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); note_list_got_semicolon (types);
grok_x_components (types, NULL_TREE); grok_x_components (types, NULL_TREE);
if (TYPE_CONTEXT (TREE_VALUE (types)) != current_class_type) if (TYPE_CONTEXT (TREE_VALUE (types)) != current_class_type)
...@@ -1391,3 +1389,37 @@ finish_member_class_template (parms, types) ...@@ -1391,3 +1389,37 @@ finish_member_class_template (parms, types)
component_decls. */ component_decls. */
return NULL_TREE; 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;
}
...@@ -587,7 +587,10 @@ common_type (t1, t2) ...@@ -587,7 +587,10 @@ common_type (t1, t2)
else if (binfo_or_else (t2, t1)) else if (binfo_or_else (t2, t1))
return build_type_attribute_variant (t2, attributes); return build_type_attribute_variant (t2, attributes);
else 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: case METHOD_TYPE:
if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2))) if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2)))
......
// Build don't link: // Build don't link:
// GROUPS passed old-abort // GROUPS passed old-abort
// Special g++ Options:
const bool FALSE = 0; const bool FALSE = 0;
const bool TRUE = 1; const bool TRUE = 1;
class ListDProto { class ListDProto {
...@@ -41,8 +43,8 @@ public: ...@@ -41,8 +43,8 @@ public:
enum Action { NORMAL, REMOVE_CURRENT }; enum Action { NORMAL, REMOVE_CURRENT };
Vix first() const; Vix first() const;
void first(Vix& x) const; void first(Vix& x) const;
void next(Vix& x) const;// ERROR - candidate for call void next(Vix& x) const;
void next(Vix& x, Action a = NORMAL);// ERROR - list of candidates void next(Vix& x, Action a = NORMAL);
Vix last() const; Vix last() const;
void last(Vix& x) const; void last(Vix& x) const;
void prev(Vix& x) const; void prev(Vix& x) const;
......
...@@ -6,7 +6,7 @@ class Elvis ...@@ -6,7 +6,7 @@ class Elvis
} ; } ;
template<int a> template<int a>
class Elvis<0>// ERROR - .* class Elvis<0>
{ // ERROR - { // ERROR - incorrect number of parameters
int geta() { return a ; } int geta() { return a ; }
} ; } ;
// Build don't link:
class A
{
class A_impl;
public:
A(){}
};
template <class j> class A::A_impl
{ // ERROR - does not declare a template
};
// Build don't link:
template <class T> struct A {};
template <class T> struct A<T>; // ERROR - does not specialize args
template <class T> const struct A; // ERROR - parse error
template <class T> template A<int>; // ERROR - .*
// Build don't link:
template <class T> struct A {};
template <class T> struct A<T*>;
A<int*> ai; // ERROR - incomplete type
// Build don't link:
template<class T>
class TestClass1 {
public:
TestClass1() { }
};
template<class T>
class TestClass2 {
public:
TestClass2() { }
T operator()(int) { }
};
template<class T>
void doit(T x) {
TestClass1<T> q1;
q1 = TestClass1<T>();
TestClass2<T> q2;
q2 = TestClass2<T>();
TestClass1<T> p1;
p1 = TestClass1(); // ERROR - template used as expression
TestClass2<T> p2;
p2 = TestClass2(); // ERROR - template used as expression
}
main() {
double x;
doit(x);
}
...@@ -13,7 +13,7 @@ template <class T> class B ...@@ -13,7 +13,7 @@ template <class T> class B
template <class T> class C template <class T> class C
{ {
template <class U> template <class U>
friend class A<U>; friend class A;
static int i; static int i;
}; };
......
// Build don't link:
template <class T = int>
struct S
{
template <class U>
friend class S;
};
template struct S<int>;
// Build don't link:
template <class T = int> // ERROR - original definition
struct S
{
template <class U = int>
friend class S;
};
template struct S<int>; // ERROR - redefinition of default arg
// Build don't link:
template <class T>
struct S
{
template <class U = T>
friend class S;
void f(T);
};
template struct S<int>;
void g()
{
S<> s;
s.f(3);
}
// Build don't link:
template <class T> struct A;
struct B
{
template <class U>
friend class A<U>; // ERROR - does not specialize any args
};
struct C
{
template <class U>
friend class A<U*>; // ERROR - partial specialization
};
// Build don't link:
struct S
{
friend void f<>(int); // ERROR - does not match any template
};
// Build don't link:
class S
{
friend void f<>(int); // ERROR - does not match any template
int i;
};
// Build don't link:
template <class X, class Y>
struct Inner;
template <class T>
struct S
{
template <class U>
struct Inner
{
};
};
S<double>::Inner<int> si;
// Build don't link:
template <class X, class Y>
struct Inner;
struct S
{
template <class U>
struct Inner
{
};
};
S::Inner<int> si;
// Build don't link:
template <class T>
struct S1
{
template <class U>
struct S2 {};
template <class X, class Y, class Z>
void f(X, Y, Z)
{
S2<Z> s2z;
}
template <class X, class Z>
void g(X, Z)
{
S2<Z> s2z;
}
};
void h()
{
S1<int> si;
si.g(3, 4);
}
extern "C" int strcmp(const char*, const char*);
template <class T>
struct S3
{
template <class U>
static char* h(U);
};
template <class T>
template <>
char* S3<T>::h(int) { return __PRETTY_FUNCTION__; }
template <>
template <>
char* S3<char>::h(int) { return __PRETTY_FUNCTION__; }
int main()
{
if (strcmp (S3<double>::h(7),
"static char * S3<double>::h<int>(int)") == 0)
return 0;
else
return 1;
}
...@@ -12,7 +12,7 @@ class base ...@@ -12,7 +12,7 @@ class base
// specialization // specialization
template<class Key, class Value> template<class Key, class Value>
class base<Key, Value, mymap<int, int > > // ERROR - mymap<...> is not a template class base<Key, Value, mymap<int, int > >
{ // ERROR - Bad class name { // ERROR - type/value mismatch
}; };
// Build don't link: // Build don't link:
// Special g++ Options:
template <class T> template <class T>
struct A struct A
......
// Build don't link: // Build don't link:
// Special g++ Options:
template <class T> template <class T>
struct A struct A
......
// Build don't link: // Build don't link:
// Special g++ Options:
template <class T> template <class T>
struct A struct A
......
// Build don't link: // Build don't link:
// Special g++ Options:
template <class T> template <class T>
struct A struct A
......
...@@ -7,7 +7,7 @@ void test<class BOX> (test_box *); // ERROR - illegal code ...@@ -7,7 +7,7 @@ void test<class BOX> (test_box *); // ERROR - illegal code
class test_square class test_square
{ {
friend void test<class BOX> (test_box *); friend void test<class BOX> (test_box *); // ERROR - does not match
} }
......
// Build don't link: // Build don't link:
// excess errors test - XFAIL *-*-* // excess errors test
// Here we declare ::S // Here we declare ::S
typedef struct s1 *S; typedef struct s1 *S;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment