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; DECL_RTL (x) = 0;
make_decl_rtl (fn, NULL_PTR, 1); make_decl_rtl (x, NULL_PTR, 1);
DECL_RTL (DECL_TI_TEMPLATE (x)) = 0;
if (x != fn) make_decl_rtl (DECL_TI_TEMPLATE (x), NULL_PTR, 1);
{
DECL_RTL (x) = 0;
make_decl_rtl (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,16 +4524,24 @@ lookup_tag (form, name, binding_level, thislevel_only) ...@@ -4509,16 +4524,24 @@ 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;
} }
return NULL_TREE; else
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))
t = do_friend (ctype, declarator, decl, {
last_function_parms, flags, quals, if (template_class_depth (current_class_type) == 0)
funcdef_flag); decl
= check_explicit_specialization
(declarator, decl,
template_count, 2 * (funcdef_flag != 0) + 4);
t = do_friend (ctype, declarator, decl,
last_function_parms, flags, quals,
funcdef_flag);
}
if (t && funcdef_flag) if (t && funcdef_flag)
return t; return t;
...@@ -11321,37 +11341,66 @@ xref_tag (code_type_node, name, binfo, globalize) ...@@ -11321,37 +11341,66 @@ 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 else
{ {
if (t) if (current_class_type
ref = t; && template_class_depth (current_class_type)
else && (processing_template_decl
ref = lookup_tag (code, name, b, 0); > template_class_depth (current_class_type)))
/* Since GLOBALIZE is non-zero, we are not looking at a
if (! ref) definition of this tag. Since, in addition, we are currently
{ processing a (member) template declaration of a template
/* Try finding it as a type declaration. If that wins, use it. */ class, we don't want to do any lookup at all; consider:
ref = lookup_name (name, 1);
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
{
if (t)
ref = t;
else
ref = lookup_tag (code, name, b, 0);
if (! ref)
{
/* Try finding it as a type declaration. If that wins,
use it. */
ref = lookup_name (name, 1);
if (ref != NULL_TREE if (ref != NULL_TREE
&& processing_template_decl && processing_template_decl
&& DECL_CLASS_TEMPLATE_P (ref) && DECL_CLASS_TEMPLATE_P (ref)
&& template_class_depth (current_class_type) == 0) && template_class_depth (current_class_type) == 0)
/* Since GLOBALIZE is true, we're declaring a global /* Since GLOBALIZE is true, we're declaring a global
template, so we want this type. */ template, so we want this type. */
ref = DECL_RESULT (ref); ref = DECL_RESULT (ref);
if (ref && TREE_CODE (ref) == TYPE_DECL if (ref && TREE_CODE (ref) == TYPE_DECL
&& TREE_CODE (TREE_TYPE (ref)) == code) && TREE_CODE (TREE_TYPE (ref)) == code)
ref = TREE_TYPE (ref); ref = TREE_TYPE (ref);
else else
ref = NULL_TREE; ref = NULL_TREE;
}
} }
} }
...@@ -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;
/* Set up current_class_type, and enter the scope of the class, if
appropriate. */
if (ctype)
push_nested_class (ctype, 1);
else if (DECL_STATIC_FUNCTION_P (decl1))
push_nested_class (DECL_CONTEXT (decl1), 2);
/* We must call push_template_decl after current_class_type is set
up. (If we are processing inline definitions after exiting a
class scope, current_class_type will be NULL_TREE until set above
by push_nested_class.) */
if (processing_template_decl)
decl1 = push_template_decl (decl1);
/* Record the decl so that the function name is defined. /* 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, If we already have a decl for this name, and it is a FUNCTION_DECL,
use the old decl. */ use the old decl. */
if (!processing_template_decl && pre_parsed_p == 0)
if (processing_template_decl)
decl1 = push_template_decl (decl1);
else if (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 = record_type_node; tcode = union_type_node;
else
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 (CLASSTYPE_IS_TEMPLATE (t)) if (TYPE_LANG_SPECIFIC (t)
/* In this case, the TYPE_IDENTIFIER will be something && CLASSTYPE_USE_TEMPLATE (t))
like S<T>, rather than S, so to get the correct name we /* We have already looked up this type. */
look at the template. */ ;
x = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
else
x = TYPE_IDENTIFIER (t);
t = xref_tag (tcode, x, NULL_TREE, 0);
return NULL_TREE;
break;
case UNION_TYPE:
case ENUMERAL_TYPE:
if (TREE_CODE (t) == UNION_TYPE)
tcode = union_type_node;
else else
tcode = enum_type_node; {
if (CLASSTYPE_IS_TEMPLATE (t))
x = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
else
x = TYPE_IDENTIFIER (t);
t = xref_tag (tcode, x, NULL_TREE, 0);
}
t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
if (ANON_UNION_TYPE_P (t)) 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)
x = grok_enum_decls (NULL_TREE); return NULL_TREE;
else break;
x = NULL_TREE;
case ENUMERAL_TYPE:
tcode = enum_type_node;
t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
x = grok_enum_decls (NULL_TREE);
return x; 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,91 +1042,75 @@ dump_function_name (t) ...@@ -1042,91 +1042,75 @@ 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;
OB_PUTC ('<');
if (args != NULL_TREE /* Be careful only to print things when we have them, so as not
&& DECL_CONTEXT (t) != NULL_TREE to crash producing error messages. */
&& uses_template_parms (DECL_CONTEXT (t)) if (args)
/* 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 ('<'); if (TREE_CODE (args) == TREE_LIST)
/* Be careful only to print things when we have them, so as not
to crash producing error messages. */
if (args)
{ {
if (TREE_CODE (args) == TREE_LIST) tree arg;
int need_comma = 0;
for (arg = args; arg; arg = TREE_CHAIN (arg))
{ {
tree arg; tree a = TREE_VALUE (arg);
int need_comma = 0;
if (need_comma)
for (arg = args; arg; arg = TREE_CHAIN (arg)) OB_PUTS (", ");
{
tree a = TREE_VALUE (arg);
if (need_comma)
OB_PUTS (", ");
if (a)
{
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't'
|| TREE_CODE (a) == TEMPLATE_DECL)
dump_type (a, 0);
else
dump_expr (a, 0);
}
need_comma = 1; if (a)
{
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't'
|| TREE_CODE (a) == TEMPLATE_DECL)
dump_type (a, 0);
else
dump_expr (a, 0);
} }
need_comma = 1;
} }
else if (TREE_CODE (args) == TREE_VEC) }
else if (TREE_CODE (args) == TREE_VEC)
{
int i;
int need_comma = 0;
if (TREE_VEC_LENGTH (args) > 0
&& TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
args = TREE_VEC_ELT (args,
TREE_VEC_LENGTH (args) - 1);
for (i = 0; i < TREE_VEC_LENGTH (args); i++)
{ {
int i; tree a = TREE_VEC_ELT (args, i);
int need_comma = 0;
if (need_comma)
if (TREE_VEC_LENGTH (args) > 0 OB_PUTS (", ");
&& TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
args = TREE_VEC_ELT (args,
TREE_VEC_LENGTH (args) - 1);
for (i = 0; i < TREE_VEC_LENGTH (args); i++)
{
tree a = TREE_VEC_ELT (args, i);
if (need_comma)
OB_PUTS (", ");
if (a)
{
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't'
|| TREE_CODE (a) == TEMPLATE_DECL)
dump_type (a, 0);
else
dump_expr (a, 0);
}
need_comma = 1; if (a)
{
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't'
|| TREE_CODE (a) == TEMPLATE_DECL)
dump_type (a, 0);
else
dump_expr (a, 0);
} }
need_comma = 1;
} }
} }
OB_PUTC ('>');
} }
OB_PUTC ('>');
} }
} }
......
...@@ -70,21 +70,22 @@ is_friend (type, supplicant) ...@@ -70,21 +70,22 @@ 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))
{ return 1;
if (is_specialization_of (supplicant,
TREE_VALUE (friends))) /* With -fguiding-decls we are more lenient about
return 1; friendship. This is bogus in general since two
specializations of a template with non-type
continue; template parameters may have the same type, but
} be different. */
if (flag_guiding_decls
/* FIXME: The use of comptypes here is bogus, since && comptypes (TREE_TYPE (supplicant),
two specializations of a template with non-type TREE_TYPE (TREE_VALUE (friends)), 1))
parameters may have the same type, but be return 1;
different. */
if (comptypes (TREE_TYPE (supplicant), if (TREE_CODE (TREE_VALUE (friends)) == TEMPLATE_DECL
TREE_TYPE (TREE_VALUE (friends)), 1)) && is_specialization_of (supplicant,
TREE_VALUE (friends)))
return 1; 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, class is instantiated. */
such a declaration depends on template if (!is_friend_template
parameters. Instead, we call pushdecl when the && template_class_depth (current_class_type) == 0)
class is instantiated. */ decl = pushdecl (decl);
if (template_class_depth (current_class_type) == 0)
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 if (DECL_STATIC_FUNCTION_P (decl))
mangled name. Unfortunately, build_decl_overload_real does not parm_types =
get the decl to mangle, so it relies on the current hash_tree_chain (build_pointer_type (DECL_CLASS_CONTEXT (decl)),
namespace. Therefore, we set that here temporarily. */ parm_types);
else
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 980702); /* The only member functions whose type is a FUNCTION_TYPE, rather
saved_ctx = current_namespace; than a METHOD_TYPE, should be static members. */
current_namespace = CP_DECL_CONTEXT (decl); my_friendly_assert (!DECL_CONTEXT (decl)
|| !IS_AGGR_TYPE_CODE (TREE_CODE (DECL_CONTEXT (decl)))
res = build_decl_overload_real (DECL_NAME (decl), parms, ret_type, || TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE,
tparms, targs, for_method); 0);
current_namespace = saved_ctx; DECL_ASSEMBLER_NAME (decl)
return res; = 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,29 +884,29 @@ end_explicit_instantiation: ...@@ -870,29 +884,29 @@ 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
$$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE); { $$ = $5; }
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
; ;
.finish_template_type:
{
if (yychar == YYEMPTY)
yychar = YYLEX;
$$ = finish_template_type ($<ttype>-3, $<ttype>-1,
yychar == SCOPE);
}
template_close_bracket: template_close_bracket:
'>' '>'
| RSHIFT | RSHIFT
...@@ -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);
} }
} }
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -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