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>
* 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 \
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(BIG_SWITCHFLAG) \
`echo $(PARSE_C) | sed 's,^\./,,'`
CONFLICTS = expect 26 shift/reduce conflicts and 42 reduce/reduce conflicts.
CONFLICTS = expect 25 shift/reduce conflicts and 42 reduce/reduce conflicts.
$(PARSE_H) : $(PARSE_C)
$(PARSE_C) : $(srcdir)/parse.y
@echo $(CONFLICTS)
......
......@@ -4458,49 +4458,21 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
/* Now, figure out which member templates we're specializing. */
for (x = specializations; x != NULL_TREE; x = TREE_CHAIN (x))
{
tree spec_args;
tree fn;
int pending_specialization;
if (uses_template_parms (t))
/* If t is a template class, and x is a specialization, then x
is itself really a template. Due to the vagaries of the
parser, however, we will have a handle to a function
declaration, rather than the template declaration, at this
point. */
{
my_friendly_assert (DECL_TEMPLATE_INFO (x) != NULL_TREE, 0);
my_friendly_assert (DECL_TI_TEMPLATE (x) != NULL_TREE, 0);
fn = DECL_TI_TEMPLATE (x);
}
else
fn = x;
/* We want the specialization arguments, which will be the
innermost ones. */
if (DECL_TI_ARGS (fn) && TREE_CODE (DECL_TI_ARGS (fn)) == TREE_VEC)
spec_args
= TREE_VEC_ELT (DECL_TI_ARGS (fn), 0);
else
spec_args = DECL_TI_ARGS (fn);
pending_specialization
= TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (fn));
= TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (x));
check_explicit_specialization
(lookup_template_function (DECL_NAME (fn), spec_args),
fn, 0, 1 | (8 * pending_specialization));
TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (fn)) = 0;
(lookup_template_function (DECL_NAME (x), DECL_TI_ARGS (x)),
x, 0, 1 | (8 * pending_specialization));
TI_PENDING_SPECIALIZATION_FLAG (DECL_TEMPLATE_INFO (x)) = 0;
/* Now, the assembler name will be correct for fn, so we
make its RTL. */
DECL_RTL (fn) = 0;
make_decl_rtl (fn, NULL_PTR, 1);
if (x != fn)
{
DECL_RTL (x) = 0;
make_decl_rtl (x, NULL_PTR, 1);
}
DECL_RTL (x) = 0;
make_decl_rtl (x, NULL_PTR, 1);
DECL_RTL (DECL_TI_TEMPLATE (x)) = 0;
make_decl_rtl (DECL_TI_TEMPLATE (x), NULL_PTR, 1);
}
if (current_class_type)
......
......@@ -2339,8 +2339,8 @@ pushtag (name, type, globalize)
class scope. In the friend case, push_template_decl
will already have put the friend into global scope,
if appropriate. */
if (!globalize && b->pseudo_global &&
b->level_chain->parm_flag == 2)
if (!globalize && b->pseudo_global
&& b->level_chain->parm_flag == 2)
{
pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
b->level_chain);
......@@ -4455,6 +4455,9 @@ lookup_tag (form, name, binding_level, thislevel_only)
int thislevel_only;
{
register struct binding_level *level;
/* Non-zero if, we should look past a pseudo-global level, even if
THISLEVEL_ONLY. */
int allow_pseudo_global = 1;
for (level = binding_level; level; level = level->level_chain)
{
......@@ -4472,7 +4475,19 @@ lookup_tag (form, name, binding_level, thislevel_only)
/* XXX: is this a real lookup, considering using-directives etc. ??? */
for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
{
tree old = BINDING_TYPE (binding_for_name (name, tail));
tree old = binding_for_name (name, tail);
/* If we just skipped past a pseudo global level, even
though THISLEVEL_ONLY, and we find a template class
declaration, then we use the _TYPE node for the
template. See the example below. */
if (thislevel_only && !allow_pseudo_global
&& old && BINDING_VALUE (old)
&& DECL_CLASS_TEMPLATE_P (BINDING_VALUE (old)))
old = TREE_TYPE (BINDING_VALUE (old));
else
old = BINDING_TYPE (old);
/* If it has an original type, it is a typedef, and we
should not return it. */
if (old && DECL_ORIGINAL_TYPE (TYPE_NAME (old)))
......@@ -4509,16 +4524,24 @@ lookup_tag (form, name, binding_level, thislevel_only)
}
if (thislevel_only && ! level->tag_transparent)
{
if (level->pseudo_global)
{
tree t = IDENTIFIER_CLASS_VALUE (name);
if (t && DECL_CLASS_TEMPLATE_P (t))
return TREE_TYPE (t);
t = IDENTIFIER_NAMESPACE_VALUE (name);
if (t && DECL_CLASS_TEMPLATE_P (t))
return TREE_TYPE (t);
if (level->pseudo_global && allow_pseudo_global)
{
/* We must deal with cases like this:
template <class T> struct S;
template <class T> struct S {};
When looking up `S', for the second declaration, we
would like to find the first declaration. But, we
are in the pseudo-global level created for the
template parameters, rather than the (surrounding)
namespace level. Thus, we keep going one more level,
even though THISLEVEL_ONLY is non-zero. */
allow_pseudo_global = 0;
continue;
}
return NULL_TREE;
else
return NULL_TREE;
}
if (current_class_type && level->level_chain->namespace_p)
{
......@@ -4730,7 +4753,8 @@ make_typename_type (context, name)
}
return lookup_template_class (t, TREE_OPERAND (fullname, 1),
NULL_TREE, context);
NULL_TREE, context,
/*entering_scope=*/0);
}
else
{
......@@ -6207,18 +6231,7 @@ shadow_tag (declspecs)
{
my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
if (IS_AGGR_TYPE (value) && CLASSTYPE_USE_TEMPLATE (value))
{
if (CLASSTYPE_IMPLICIT_INSTANTIATION (value)
&& TYPE_SIZE (value) == NULL_TREE)
{
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (value);
if (processing_template_decl)
push_template_decl (TYPE_MAIN_DECL (value));
}
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (value))
cp_error ("specialization after instantiation of `%T'", value);
}
maybe_process_partial_specialization (value);
t = value;
ok_code = code;
......@@ -10241,9 +10254,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
{
tree t = NULL_TREE;
if (decl && DECL_NAME (decl))
t = do_friend (ctype, declarator, decl,
last_function_parms, flags, quals,
funcdef_flag);
{
if (template_class_depth (current_class_type) == 0)
decl
= check_explicit_specialization
(declarator, decl,
template_count, 2 * (funcdef_flag != 0) + 4);
t = do_friend (ctype, declarator, decl,
last_function_parms, flags, quals,
funcdef_flag);
}
if (t && funcdef_flag)
return t;
......@@ -11321,37 +11341,66 @@ xref_tag (code_type_node, name, binfo, globalize)
if (t && TYPE_CONTEXT (t) && got_type)
ref = t;
else
{
/* If we know we are defining this tag, only look it up in
this scope and don't try to find it as a type. */
ref = lookup_tag (code, name, b, 1);
}
/* If we know we are defining this tag, only look it up in
this scope and don't try to find it as a type. */
ref = lookup_tag (code, name, b, 1);
}
else
{
if (t)
ref = t;
else
ref = lookup_tag (code, name, b, 0);
if (! ref)
{
/* Try finding it as a type declaration. If that wins, use it. */
ref = lookup_name (name, 1);
if (current_class_type
&& template_class_depth (current_class_type)
&& (processing_template_decl
> template_class_depth (current_class_type)))
/* Since GLOBALIZE is non-zero, we are not looking at a
definition of this tag. Since, in addition, we are currently
processing a (member) template declaration of a template
class, we don't want to do any lookup at all; consider:
template <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
&& processing_template_decl
&& DECL_CLASS_TEMPLATE_P (ref)
&& template_class_depth (current_class_type) == 0)
/* Since GLOBALIZE is true, we're declaring a global
if (ref != NULL_TREE
&& processing_template_decl
&& DECL_CLASS_TEMPLATE_P (ref)
&& template_class_depth (current_class_type) == 0)
/* Since GLOBALIZE is true, we're declaring a global
template, so we want this type. */
ref = DECL_RESULT (ref);
ref = DECL_RESULT (ref);
if (ref && TREE_CODE (ref) == TYPE_DECL
&& TREE_CODE (TREE_TYPE (ref)) == code)
ref = TREE_TYPE (ref);
else
ref = NULL_TREE;
if (ref && TREE_CODE (ref) == TYPE_DECL
&& TREE_CODE (TREE_TYPE (ref)) == code)
ref = TREE_TYPE (ref);
else
ref = NULL_TREE;
}
}
}
......@@ -12121,13 +12170,24 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
/* Set up current_class_type, and enter the scope of the class, if
appropriate. */
if (ctype)
push_nested_class (ctype, 1);
else if (DECL_STATIC_FUNCTION_P (decl1))
push_nested_class (DECL_CONTEXT (decl1), 2);
/* We must call push_template_decl after current_class_type is set
up. (If we are processing inline definitions after exiting a
class scope, current_class_type will be NULL_TREE until set above
by push_nested_class.) */
if (processing_template_decl)
decl1 = push_template_decl (decl1);
/* Record the decl so that the function name is defined.
If we already have a decl for this name, and it is a FUNCTION_DECL,
use the old decl. */
if (processing_template_decl)
decl1 = push_template_decl (decl1);
else if (pre_parsed_p == 0)
if (!processing_template_decl && pre_parsed_p == 0)
{
/* A specialization is not used to guide overload resolution. */
if ((flag_guiding_decls
......@@ -12207,8 +12267,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
if (ctype)
{
push_nested_class (ctype, 1);
/* If we're compiling a friend function, neither of the variables
current_class_ptr nor current_class_type will have values. */
if (! doing_friend)
......@@ -12241,10 +12299,8 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
}
else
{
if (DECL_STATIC_FUNCTION_P (decl1))
push_nested_class (DECL_CONTEXT (decl1), 2);
else
push_memoized_context (0, 1);
if (!DECL_STATIC_FUNCTION_P (decl1))
push_memoized_context (NULL_TREE, 1);
current_class_ptr = current_class_ref = NULL_TREE;
}
......@@ -13185,7 +13241,8 @@ start_method (declspecs, declarator)
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
if (processing_template_decl)
/* We process method specializations in finish_struct_1. */
if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
fndecl = push_template_decl (fndecl);
/* We read in the parameters on the maybepermanent_obstack,
......
......@@ -912,34 +912,29 @@ grok_x_components (specs, components)
break;
case RECORD_TYPE:
/* This code may be needed for UNION_TYPEs as
well. */
tcode = record_type_node;
case UNION_TYPE:
if (TREE_CODE (t) == UNION_TYPE)
tcode = union_type_node;
else
tcode = record_type_node;
if (CLASSTYPE_DECLARED_CLASS (t))
tcode = class_type_node;
else if (IS_SIGNATURE (t))
tcode = signature_type_node;
if (CLASSTYPE_IS_TEMPLATE (t))
/* In this case, the TYPE_IDENTIFIER will be something
like S<T>, rather than S, so to get the correct name we
look at the template. */
x = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
else
x = TYPE_IDENTIFIER (t);
t = xref_tag (tcode, x, NULL_TREE, 0);
return NULL_TREE;
break;
case UNION_TYPE:
case ENUMERAL_TYPE:
if (TREE_CODE (t) == UNION_TYPE)
tcode = union_type_node;
if (TYPE_LANG_SPECIFIC (t)
&& CLASSTYPE_USE_TEMPLATE (t))
/* We have already looked up this type. */
;
else
tcode = enum_type_node;
{
if (CLASSTYPE_IS_TEMPLATE (t))
x = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
else
x = TYPE_IDENTIFIER (t);
t = xref_tag (tcode, x, NULL_TREE, 0);
}
t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
if (ANON_UNION_TYPE_P (t))
{
/* See also shadow_tag. */
......@@ -972,11 +967,17 @@ grok_x_components (specs, components)
for (; *p; *p = (*p)->next)
if (DECL_CONTEXT ((*p)->fndecl) != t)
break;
return x;
}
else if (TREE_CODE (t) == ENUMERAL_TYPE)
x = grok_enum_decls (NULL_TREE);
else
x = NULL_TREE;
return NULL_TREE;
break;
case ENUMERAL_TYPE:
tcode = enum_type_node;
t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
x = grok_enum_decls (NULL_TREE);
return x;
break;
......@@ -1132,16 +1133,7 @@ grokclassfn (ctype, cname, function, flags, quals)
TYPE_HAS_DESTRUCTOR (ctype) = 1;
}
else
{
if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE)
/* Only true for static member functions. */
arg_types = hash_tree_chain (build_pointer_type (qualtype),
arg_types);
DECL_ASSEMBLER_NAME (function)
= build_decl_overload (fn_name, arg_types,
1 + DECL_CONSTRUCTOR_P (function));
}
set_mangled_name_for_decl (function);
}
/* Work on the expr used by alignof (this is only called by the parser). */
......@@ -4299,7 +4291,7 @@ arg_assoc_class (k, type)
/* Process template arguments. */
if (CLASSTYPE_TEMPLATE_INFO (type))
{
list = innermost_args (CLASSTYPE_TI_ARGS (type), 0);
list = innermost_args (CLASSTYPE_TI_ARGS (type));
for (i = 0; i < TREE_VEC_LENGTH (list); ++i)
arg_assoc (k, TREE_VEC_ELT (list, i));
}
......@@ -4690,13 +4682,21 @@ mark_used (decl)
if (processing_template_decl)
return;
assemble_external (decl);
/* Is it a synthesized method that needs to be synthesized? */
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CLASS_CONTEXT (decl)
&& DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
/* Kludge: don't synthesize for default args. */
&& current_function_decl)
synthesize_method (decl);
if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
/* If this is a function or variable that is an instance of some
template, we now know that we will need to actually do the
instantiation. A TEMPLATE_DECL may also have DECL_TEMPLATE_INFO,
if it's a partial instantiation, but there's no need to
instantiate such a thing. */
if (TREE_CODE (decl) != TEMPLATE_DECL
&& DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
instantiate_decl (decl);
}
......
......@@ -1042,91 +1042,75 @@ dump_function_name (t)
else
dump_decl (name, 0);
if (DECL_LANG_SPECIFIC (t) && DECL_USE_TEMPLATE (t))
if (DECL_LANG_SPECIFIC (t) && DECL_USE_TEMPLATE (t)
&& DECL_TEMPLATE_INFO (t)
&& (DECL_TEMPLATE_SPECIALIZATION (t)
|| TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL
|| DECL_TEMPLATE_SPECIALIZATION (DECL_TI_TEMPLATE (t))
|| PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t))))
{
tree args = DECL_TEMPLATE_INFO (t) ? DECL_TI_ARGS (t) : NULL_TREE;
OB_PUTC ('<');
if (args != NULL_TREE
&& DECL_CONTEXT (t) != NULL_TREE
&& uses_template_parms (DECL_CONTEXT (t))
/* This next clause checks that there is only one level of
template arguments. In that case, they are the
arguments for the class context. */
&& (TREE_CODE (args) == TREE_LIST
|| (TREE_CODE (args) == TREE_VEC
&& TREE_VEC_ELT (args, 0) != NULL_TREE
&& TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)))
/* We have something like this:
template <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
/* Be careful only to print things when we have them, so as not
to crash producing error messages. */
if (args)
{
OB_PUTC ('<');
/* Be careful only to print things when we have them, so as not
to crash producing error messages. */
if (args)
if (TREE_CODE (args) == TREE_LIST)
{
if (TREE_CODE (args) == TREE_LIST)
tree arg;
int need_comma = 0;
for (arg = args; arg; arg = TREE_CHAIN (arg))
{
tree arg;
int need_comma = 0;
for (arg = args; arg; arg = TREE_CHAIN (arg))
{
tree a = TREE_VALUE (arg);
if (need_comma)
OB_PUTS (", ");
if (a)
{
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't'
|| TREE_CODE (a) == TEMPLATE_DECL)
dump_type (a, 0);
else
dump_expr (a, 0);
}
tree a = TREE_VALUE (arg);
if (need_comma)
OB_PUTS (", ");
need_comma = 1;
if (a)
{
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't'
|| TREE_CODE (a) == TEMPLATE_DECL)
dump_type (a, 0);
else
dump_expr (a, 0);
}
need_comma = 1;
}
else if (TREE_CODE (args) == TREE_VEC)
}
else if (TREE_CODE (args) == TREE_VEC)
{
int i;
int need_comma = 0;
if (TREE_VEC_LENGTH (args) > 0
&& TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
args = TREE_VEC_ELT (args,
TREE_VEC_LENGTH (args) - 1);
for (i = 0; i < TREE_VEC_LENGTH (args); i++)
{
int i;
int need_comma = 0;
if (TREE_VEC_LENGTH (args) > 0
&& TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
args = TREE_VEC_ELT (args,
TREE_VEC_LENGTH (args) - 1);
for (i = 0; i < TREE_VEC_LENGTH (args); i++)
{
tree a = TREE_VEC_ELT (args, i);
if (need_comma)
OB_PUTS (", ");
if (a)
{
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't'
|| TREE_CODE (a) == TEMPLATE_DECL)
dump_type (a, 0);
else
dump_expr (a, 0);
}
tree a = TREE_VEC_ELT (args, i);
if (need_comma)
OB_PUTS (", ");
need_comma = 1;
if (a)
{
if (TREE_CODE_CLASS (TREE_CODE (a)) == 't'
|| TREE_CODE (a) == TEMPLATE_DECL)
dump_type (a, 0);
else
dump_expr (a, 0);
}
need_comma = 1;
}
}
OB_PUTC ('>');
}
OB_PUTC ('>');
}
}
......
......@@ -70,21 +70,22 @@ is_friend (type, supplicant)
if (TREE_VALUE (friends) == NULL_TREE)
continue;
if (TREE_CODE (TREE_VALUE (friends)) == TEMPLATE_DECL)
{
if (is_specialization_of (supplicant,
TREE_VALUE (friends)))
return 1;
continue;
}
/* FIXME: The use of comptypes here is bogus, since
two specializations of a template with non-type
parameters may have the same type, but be
different. */
if (comptypes (TREE_TYPE (supplicant),
TREE_TYPE (TREE_VALUE (friends)), 1))
if (supplicant == TREE_VALUE (friends))
return 1;
/* With -fguiding-decls we are more lenient about
friendship. This is bogus in general since two
specializations of a template with non-type
template parameters may have the same type, but
be different. */
if (flag_guiding_decls
&& comptypes (TREE_TYPE (supplicant),
TREE_TYPE (TREE_VALUE (friends)), 1))
return 1;
if (TREE_CODE (TREE_VALUE (friends)) == TEMPLATE_DECL
&& is_specialization_of (supplicant,
TREE_VALUE (friends)))
return 1;
}
break;
......@@ -253,6 +254,21 @@ make_friend_class (type, friend_type)
IDENTIFIER_POINTER (TYPE_IDENTIFIER (friend_type)));
return;
}
if (CLASSTYPE_TEMPLATE_SPECIALIZATION (friend_type))
{
/* [temp.friend]
Friend declarations shall not declare partial
specializations.
Note that CLASSTYPE_TEMPLATE_SPECIALIZATION is not set for
full specializations. */
cp_error ("partial specialization `%T' declared `friend'",
friend_type);
return;
}
if (processing_template_decl > template_class_depth (type))
/* If the TYPE is a template then it makes sense for it to be
friends with itself; this means that each instantiation is
......@@ -407,9 +423,7 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
Note that because classes all wind up being top-level
in their scope, their friend wind up in top-level scope as well. */
DECL_ASSEMBLER_NAME (decl)
= build_decl_overload (declarator, TYPE_ARG_TYPES (TREE_TYPE (decl)),
TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
set_mangled_name_for_decl (decl);
DECL_ARGUMENTS (decl) = parmdecls;
if (funcdef_flag)
DECL_CLASS_CONTEXT (decl) = current_class_type;
......@@ -417,20 +431,17 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
if (! DECL_USE_TEMPLATE (decl))
{
/* We can call pushdecl here, because the TREE_CHAIN of this
FUNCTION_DECL is not needed for other purposes. Don't do this
for a template instantiation. */
if (!is_friend_template)
{
/* However, we don't call pushdecl() for a friend
function of a template class, since in general,
such a declaration depends on template
parameters. Instead, we call pushdecl when the
class is instantiated. */
if (template_class_depth (current_class_type) == 0)
decl = pushdecl (decl);
}
FUNCTION_DECL is not needed for other purposes. Don't do
this for a template instantiation. However, we don't
call pushdecl() for a friend function of a template
class, since in general, such a declaration depends on
template parameters. Instead, we call pushdecl when the
class is instantiated. */
if (!is_friend_template
&& template_class_depth (current_class_type) == 0)
decl = pushdecl (decl);
else
decl = push_template_decl (decl);
decl = push_template_decl_real (decl, /*is_friend=*/1);
if (! funcdef_flag && ! flag_guiding_decls && ! is_friend_template
&& current_template_parms && uses_template_parms (decl))
......
......@@ -71,8 +71,6 @@ static void process_overload_item PROTO((tree,int));
static void do_build_assign_ref PROTO((tree));
static void do_build_copy_constructor PROTO((tree));
static tree largest_union_member PROTO((tree));
static tree build_decl_overload_real PROTO((tree, tree, tree, tree,
tree, int));
static void build_template_template_parm_names PROTO((tree));
static void build_template_parm_names PROTO((tree, tree));
static void build_underscore_int PROTO((int));
......@@ -922,7 +920,7 @@ build_overload_identifier (name)
/* NAME is the TYPE_DECL for a template specialization. */
tree template, parmlist, arglist, tname;
template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name));
arglist = innermost_args (TREE_VALUE (template), 0);
arglist = innermost_args (TREE_VALUE (template));
template = TREE_PURPOSE (template);
tname = DECL_NAME (template);
parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
......@@ -1499,7 +1497,10 @@ build_static_name (context, name)
return get_identifier ((char *)obstack_base (&scratch_obstack));
}
static tree
/* FOR_METHOD should be 1 if the declaration in question is for a member
of a class (including a static member) and 2 if the declaration is
for a constructor. */
tree
build_decl_overload_real (dname, parms, ret_type, tparms, targs,
for_method)
tree dname;
......@@ -1660,38 +1661,32 @@ build_decl_overload (dname, parms, for_method)
NULL_TREE, for_method);
}
/* Like build_decl_overload, but for template functions. */
/* Set the mangled name (DECL_ASSEMBLER_NAME) for DECL. */
tree
build_template_decl_overload (decl, parms, ret_type, tparms, targs,
for_method)
set_mangled_name_for_decl (decl)
tree decl;
tree parms;
tree ret_type;
tree tparms;
tree targs;
int for_method;
{
tree res, saved_ctx;
tree parm_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
/* If the template is in a namespace, we need to put that into the
mangled name. Unfortunately, build_decl_overload_real does not
get the decl to mangle, so it relies on the current
namespace. Therefore, we set that here temporarily. */
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 980702);
saved_ctx = current_namespace;
current_namespace = CP_DECL_CONTEXT (decl);
res = build_decl_overload_real (DECL_NAME (decl), parms, ret_type,
tparms, targs, for_method);
current_namespace = saved_ctx;
return res;
if (DECL_STATIC_FUNCTION_P (decl))
parm_types =
hash_tree_chain (build_pointer_type (DECL_CLASS_CONTEXT (decl)),
parm_types);
else
/* The only member functions whose type is a FUNCTION_TYPE, rather
than a METHOD_TYPE, should be static members. */
my_friendly_assert (!DECL_CONTEXT (decl)
|| !IS_AGGR_TYPE_CODE (TREE_CODE (DECL_CONTEXT (decl)))
|| TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE,
0);
DECL_ASSEMBLER_NAME (decl)
= build_decl_overload (DECL_NAME (decl), parm_types,
DECL_FUNCTION_MEMBER_P (decl)
+ DECL_CONSTRUCTOR_P (decl));
}
/* Build an overload name for the type expression TYPE. */
tree
......
......@@ -267,7 +267,7 @@ empty_parms ()
%type <ttype> named_class_head_sans_basetype_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
%type <ttype> NSNAME
......@@ -556,22 +556,38 @@ template_parm:
;
template_def:
template_header
extdef
{
if ($1)
end_template_decl ();
else
end_specialization ();
}
| template_header
error %prec EMPTY
{
if ($1)
end_template_decl ();
else
end_specialization ();
}
template_header template_extdef
{ finish_template_decl ($1); }
| template_header error %prec EMPTY
{ finish_template_decl ($1); }
;
template_extdef:
fndef eat_saved_input
{ if (pending_inlines) do_pending_inlines (); }
| template_datadef
{ if (pending_inlines) do_pending_inlines (); }
| template_def
{ if (pending_inlines) do_pending_inlines (); }
| extern_lang_string .hush_warning fndef .warning_ok eat_saved_input
{ if (pending_inlines) do_pending_inlines ();
pop_lang_context (); }
| extern_lang_string .hush_warning template_datadef .warning_ok
{ if (pending_inlines) do_pending_inlines ();
pop_lang_context (); }
| extension template_extdef
{ pedantic = $<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:
......@@ -579,9 +595,7 @@ datadef:
| declmods notype_initdecls ';'
{}
| typed_declspecs initdecls ';'
{
note_list_got_semicolon ($1.t);
}
{ note_list_got_semicolon ($1.t); }
| declmods ';'
{ pedwarn ("empty declaration"); }
| explicit_instantiation ';'
......@@ -870,29 +884,29 @@ end_explicit_instantiation:
template_type:
PTYPENAME '<' template_arg_list_opt template_close_bracket
{
$$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
.finish_template_type
{ $$ = $5; }
| TYPENAME '<' template_arg_list_opt template_close_bracket
{
$$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
.finish_template_type
{ $$ = $5; }
| self_template_type
;
self_template_type:
SELFNAME '<' template_arg_list_opt template_close_bracket
{
$$ = lookup_template_class ($1, $3, NULL_TREE, NULL_TREE);
if ($$ != error_mark_node)
$$ = TYPE_STUB_DECL ($$);
}
.finish_template_type
{ $$ = $5; }
;
.finish_template_type:
{
if (yychar == YYEMPTY)
yychar = YYLEX;
$$ = finish_template_type ($<ttype>-3, $<ttype>-1,
yychar == SCOPE);
}
template_close_bracket:
'>'
| RSHIFT
......@@ -2193,18 +2207,7 @@ named_class_head:
cp_pedwarn ("non-`union' tag used in declaring `%#T'", $$);
if ($2)
{
if (IS_AGGR_TYPE ($$) && CLASSTYPE_USE_TEMPLATE ($$))
{
if (CLASSTYPE_IMPLICIT_INSTANTIATION ($$)
&& TYPE_SIZE ($$) == NULL_TREE)
{
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION ($$);
if (processing_template_decl)
push_template_decl (TYPE_MAIN_DECL ($$));
}
else if (CLASSTYPE_TEMPLATE_INSTANTIATION ($$))
cp_error ("specialization after instantiation of `%T'", $$);
}
maybe_process_partial_specialization ($$);
xref_basetypes (current_aggr, $1, $$, $2);
}
}
......
......@@ -1235,18 +1235,7 @@ begin_class_definition (t)
push_template_decl (TYPE_STUB_DECL (t));
pushclass (t, 0);
TYPE_BEING_DEFINED (t) = 1;
if (IS_AGGR_TYPE (t) && CLASSTYPE_USE_TEMPLATE (t))
{
if (CLASSTYPE_IMPLICIT_INSTANTIATION (t)
&& TYPE_SIZE (t) == NULL_TREE)
{
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t);
if (processing_template_decl)
push_template_decl (TYPE_MAIN_DECL (t));
}
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t))
cp_error ("specialization after instantiation of `%T'", t);
}
maybe_process_partial_specialization (t);
/* Reset the interface data, at the earliest possible
moment, as it might have been set via a class foo;
before. */
......@@ -1378,6 +1367,15 @@ finish_member_class_template (parms, types)
tree parms;
tree types;
{
tree t;
/* If there are declared, but undefined, partial specializations
mixed in with the typespecs they will not yet have passed through
maybe_process_partial_specialization, so we do that here. */
for (t = types; t != NULL_TREE; t = TREE_CHAIN (t))
if (IS_AGGR_TYPE_CODE (TREE_CODE (TREE_VALUE (t))))
maybe_process_partial_specialization (TREE_VALUE (t));
note_list_got_semicolon (types);
grok_x_components (types, NULL_TREE);
if (TYPE_CONTEXT (TREE_VALUE (types)) != current_class_type)
......@@ -1391,3 +1389,37 @@ finish_member_class_template (parms, types)
component_decls. */
return NULL_TREE;
}
/* Finish processsing a complete template declaration. The PARMS are
the template parameters. */
void
finish_template_decl (parms)
tree parms;
{
if (parms)
end_template_decl ();
else
end_specialization ();
}
/* Finish processing a a template-id (which names a type) of the form
NAME < ARGS >. Return the TYPE_DECL for the type named by the
template-id. If ENTERING_SCOPE is non-zero we are about to enter
the scope of template-id indicated. */
tree
finish_template_type (name, args, entering_scope)
tree name;
tree args;
int entering_scope;
{
tree decl;
decl = lookup_template_class (name, args,
NULL_TREE, NULL_TREE, entering_scope);
if (decl != error_mark_node)
decl = TYPE_STUB_DECL (decl);
return decl;
}
......@@ -587,7 +587,10 @@ common_type (t1, t2)
else if (binfo_or_else (t2, t1))
return build_type_attribute_variant (t2, attributes);
else
compiler_error ("common_type called with uncommon aggregate types");
{
compiler_error ("common_type called with uncommon aggregate types");
return error_mark_node;
}
case METHOD_TYPE:
if (TREE_CODE (TREE_TYPE (t1)) == TREE_CODE (TREE_TYPE (t2)))
......
// Build don't link:
// GROUPS passed old-abort
// Special g++ Options:
const bool FALSE = 0;
const bool TRUE = 1;
class ListDProto {
......@@ -41,8 +43,8 @@ public:
enum Action { NORMAL, REMOVE_CURRENT };
Vix first() const;
void first(Vix& x) const;
void next(Vix& x) const;// ERROR - candidate for call
void next(Vix& x, Action a = NORMAL);// ERROR - list of candidates
void next(Vix& x) const;
void next(Vix& x, Action a = NORMAL);
Vix last() const;
void last(Vix& x) const;
void prev(Vix& x) const;
......
......@@ -6,7 +6,7 @@ class Elvis
} ;
template<int a>
class Elvis<0>// ERROR - .*
{ // ERROR -
class Elvis<0>
{ // ERROR - incorrect number of parameters
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
template <class T> class C
{
template <class U>
friend class A<U>;
friend class A;
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
// specialization
template<class Key, class Value>
class base<Key, Value, mymap<int, int > > // ERROR - mymap<...> is not a template
{ // ERROR - Bad class name
class base<Key, Value, mymap<int, int > >
{ // ERROR - type/value mismatch
};
// Build don't link:
// Special g++ Options:
template <class T>
struct A
......
// Build don't link:
// Special g++ Options:
template <class T>
struct A
......
// Build don't link:
// Special g++ Options:
template <class T>
struct A
......
// Build don't link:
// Special g++ Options:
template <class T>
struct A
......
......@@ -7,7 +7,7 @@ void test<class BOX> (test_box *); // ERROR - illegal code
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:
// excess errors test - XFAIL *-*-*
// excess errors test
// Here we declare ::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