Commit f9a7ae04 by Mark Mitchell Committed by Mark Mitchell

cp-tree.h (TMPL_ARGS_LEVEL): Clarify comment.

	* cp-tree.h (TMPL_ARGS_LEVEL): Clarify comment.
	(INNERMOST_TEMPLATE_ARGS): New macro.
	(innermost_args): Remove.
	(get_innermost_template_args): New function.
	* decl2.c (arg_assoc_class): Use INNERMOST_TEMPLATE_ARGS.
	* error.c (dump_function_decl): Be caution when using
	most_general_template.
	* method.c (build_template_parm_names):  Use
	INNERMOST_TEMPLATE_ARGS.
	* pt.c (add_to_template_args): Tidy comment
	(get_innermost_template_args): New function.
	(check_explicit_specialization): Clear DECL_INITIAL for a new
	specialization.
	(process_partial_specialization): Use INNERMOST_TEMPLATE_ARGS.
	Tidy.
	(push_template_decl): Always register specializations of the most
	general template.
	(convert_template_argument): Use INNERMOST_TEMPLATE_ARGS.
	(coerce_template_parms): Likewise.
	(lookup_template_class): Likewise.
	(innermost_args): Remove.
	(tsubst_decl): Use INNERMOST_TEMPLATE_ARGS.
	(tsubst_decl): Handle tricky specializations.  Use
	get_innermost_template_args.
	(instantiate_template): Simplify handling of partial
	instantiations.
	(get_class_bindings): Use INNERMOST_TEMPLATE_ARGS.
	(most_general_template): Reimplement, in a more straightforward
	manner.
	(regenerate_decl_from_template): Tweak formatting.  Use
	TMPL_ARGS_DEPTH for clarity.
	(set_mangled_name_for_template_decl): Use INNERMOST_ARGS.

	* dump.c (dequeue_and_dump): Dump information about thunks.

From-SVN: r34384
parent 22ad5966
2000-06-03 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (TMPL_ARGS_LEVEL): Clarify comment.
(INNERMOST_TEMPLATE_ARGS): New macro.
(innermost_args): Remove.
(get_innermost_template_args): New function.
* decl2.c (arg_assoc_class): Use INNERMOST_TEMPLATE_ARGS.
* error.c (dump_function_decl): Be caution when using
most_general_template.
* method.c (build_template_parm_names): Use
INNERMOST_TEMPLATE_ARGS.
* pt.c (add_to_template_args): Tidy comment
(get_innermost_template_args): New function.
(check_explicit_specialization): Clear DECL_INITIAL for a new
specialization.
(process_partial_specialization): Use INNERMOST_TEMPLATE_ARGS.
Tidy.
(push_template_decl): Always register specializations of the most
general template.
(convert_template_argument): Use INNERMOST_TEMPLATE_ARGS.
(coerce_template_parms): Likewise.
(lookup_template_class): Likewise.
(innermost_args): Remove.
(tsubst_decl): Use INNERMOST_TEMPLATE_ARGS.
(tsubst_decl): Handle tricky specializations. Use
get_innermost_template_args.
(instantiate_template): Simplify handling of partial
instantiations.
(get_class_bindings): Use INNERMOST_TEMPLATE_ARGS.
(most_general_template): Reimplement, in a more straightforward
manner.
(regenerate_decl_from_template): Tweak formatting. Use
TMPL_ARGS_DEPTH for clarity.
(set_mangled_name_for_template_decl): Use INNERMOST_ARGS.
* dump.c (dequeue_and_dump): Dump information about thunks.
2000-06-02 Jason Merrill <jason@casey.soma.redhat.com> 2000-06-02 Jason Merrill <jason@casey.soma.redhat.com>
* exception.cc (__cp_pop_exception): If we aren't popping or * exception.cc (__cp_pop_exception): If we aren't popping or
......
...@@ -2325,8 +2325,8 @@ struct lang_decl ...@@ -2325,8 +2325,8 @@ struct lang_decl
#define TMPL_ARGS_DEPTH(NODE) \ #define TMPL_ARGS_DEPTH(NODE) \
(TMPL_ARGS_HAVE_MULTIPLE_LEVELS (NODE) ? TREE_VEC_LENGTH (NODE) : 1) (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (NODE) ? TREE_VEC_LENGTH (NODE) : 1)
/* The LEVELth level of the template ARGS. Note that template /* The LEVELth level of the template ARGS. The outermost level of of
parameter levels are indexed from 1, not from 0. */ args is level 1, not level 0. */
#define TMPL_ARGS_LEVEL(ARGS, LEVEL) \ #define TMPL_ARGS_LEVEL(ARGS, LEVEL) \
(TMPL_ARGS_HAVE_MULTIPLE_LEVELS (ARGS) \ (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (ARGS) \
? TREE_VEC_ELT ((ARGS), (LEVEL) - 1) : ARGS) ? TREE_VEC_ELT ((ARGS), (LEVEL) - 1) : ARGS)
...@@ -2352,6 +2352,10 @@ struct lang_decl ...@@ -2352,6 +2352,10 @@ struct lang_decl
: (TREE_CODE (NODE) == TREE_VEC \ : (TREE_CODE (NODE) == TREE_VEC \
? TREE_VEC_LENGTH (NODE) : list_length (NODE))) ? TREE_VEC_LENGTH (NODE) : list_length (NODE)))
/* Returns the innermost level of template arguments in ARGS. */
#define INNERMOST_TEMPLATE_ARGS(NODE) \
(get_innermost_template_args ((NODE), 1))
/* The number of levels of template parameters given by NODE. */ /* The number of levels of template parameters given by NODE. */
#define TMPL_PARMS_DEPTH(NODE) \ #define TMPL_PARMS_DEPTH(NODE) \
(TREE_INT_CST_HIGH (TREE_PURPOSE (NODE))) (TREE_INT_CST_HIGH (TREE_PURPOSE (NODE)))
...@@ -4298,7 +4302,7 @@ extern int maybe_clone_body PARAMS ((tree)); ...@@ -4298,7 +4302,7 @@ extern int maybe_clone_body PARAMS ((tree));
/* in pt.c */ /* in pt.c */
extern void init_pt PARAMS ((void)); extern void init_pt PARAMS ((void));
extern void check_template_shadow PARAMS ((tree)); extern void check_template_shadow PARAMS ((tree));
extern tree innermost_args PARAMS ((tree)); extern tree get_innermost_template_args PARAMS ((tree, int));
extern tree tsubst PARAMS ((tree, tree, int, tree)); extern tree tsubst PARAMS ((tree, tree, int, tree));
extern tree tsubst_expr PARAMS ((tree, tree, int, tree)); extern tree tsubst_expr PARAMS ((tree, tree, int, tree));
extern tree tsubst_copy PARAMS ((tree, tree, int, tree)); extern tree tsubst_copy PARAMS ((tree, tree, int, tree));
......
...@@ -4798,7 +4798,7 @@ arg_assoc_class (k, type) ...@@ -4798,7 +4798,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)); list = INNERMOST_TEMPLATE_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_template_arg (k, TREE_VEC_ELT (list, i)); arg_assoc_template_arg (k, TREE_VEC_ELT (list, i));
} }
......
...@@ -578,6 +578,13 @@ dequeue_and_dump (di) ...@@ -578,6 +578,13 @@ dequeue_and_dump (di)
dump_string (di, "operator"); dump_string (di, "operator");
if (DECL_CONV_FN_P (t)) if (DECL_CONV_FN_P (t))
dump_string (di, "conversion"); dump_string (di, "conversion");
if (DECL_THUNK_P (t))
{
dump_string (di, "thunk");
dump_int (di, "dlta", THUNK_DELTA (t));
dump_int (di, "vcll", THUNK_VCALL_OFFSET (t));
dump_child ("fn", DECL_INITIAL (t));
}
if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t)) if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t))
{ {
if (DECL_GLOBAL_CTOR_P (t)) if (DECL_GLOBAL_CTOR_P (t))
......
...@@ -1111,10 +1111,15 @@ dump_function_decl (t, flags) ...@@ -1111,10 +1111,15 @@ dump_function_decl (t, flags)
/* Pretty print template instantiations only. */ /* Pretty print template instantiations only. */
if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t)) if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t))
{ {
tree tmpl;
template_args = DECL_TI_ARGS (t); template_args = DECL_TI_ARGS (t);
t = most_general_template (t); tmpl = most_general_template (t);
if (TREE_CODE (t) == TEMPLATE_DECL) if (tmpl && TREE_CODE (tmpl) == TEMPLATE_DECL)
template_parms = DECL_TEMPLATE_PARMS (t); {
template_parms = DECL_TEMPLATE_PARMS (tmpl);
t = tmpl;
}
} }
fntype = TREE_TYPE (t); fntype = TREE_TYPE (t);
......
...@@ -945,7 +945,7 @@ build_template_parm_names (parmlist, arglist) ...@@ -945,7 +945,7 @@ build_template_parm_names (parmlist, arglist)
tree arglist; tree arglist;
{ {
int i, nparms; int i, nparms;
tree inner_args = innermost_args (arglist); tree inner_args = INNERMOST_TEMPLATE_ARGS (arglist);
nparms = TREE_VEC_LENGTH (parmlist); nparms = TREE_VEC_LENGTH (parmlist);
icat (nparms); icat (nparms);
......
...@@ -474,9 +474,7 @@ is_member_template_class (t) ...@@ -474,9 +474,7 @@ is_member_template_class (t)
#endif #endif
/* Return a new template argument vector which contains all of ARGS, /* Return a new template argument vector which contains all of ARGS,
but has as its innermost set of arguments the EXTRA_ARGS. The but has as its innermost set of arguments the EXTRA_ARGS. */
resulting vector will be built on a temporary obstack, and so must
be explicitly copied to the permanent obstack, if required. */
static tree static tree
add_to_template_args (args, extra_args) add_to_template_args (args, extra_args)
...@@ -535,6 +533,39 @@ add_outermost_template_args (args, extra_args) ...@@ -535,6 +533,39 @@ add_outermost_template_args (args, extra_args)
return new_args; return new_args;
} }
/* Return the N levels of innermost template arguments from the ARGS. */
tree
get_innermost_template_args (args, n)
tree args;
int n;
{
tree new_args;
int extra_levels;
int i;
my_friendly_assert (n >= 0, 20000603);
/* If N is 1, just return the innermost set of template arguments. */
if (n == 1)
return TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args));
/* If we're not removing anything, just return the arguments we were
given. */
extra_levels = TMPL_ARGS_DEPTH (args) - n;
my_friendly_assert (extra_levels >= 0, 20000603);
if (extra_levels == 0)
return args;
/* Make a new set of arguments, not containing the outer arguments. */
new_args = make_tree_vec (n);
for (i = 1; i <= n; ++i)
SET_TMPL_ARGS_LEVEL (new_args, i,
TMPL_ARGS_LEVEL (args, i + extra_levels));
return new_args;
}
/* We've got a template header coming up; push to a new level for storing /* We've got a template header coming up; push to a new level for storing
the parms. */ the parms. */
...@@ -1484,13 +1515,13 @@ check_explicit_specialization (declarator, decl, template_count, flags) ...@@ -1484,13 +1515,13 @@ check_explicit_specialization (declarator, decl, template_count, flags)
return instantiate_template (tmpl, targs); return instantiate_template (tmpl, targs);
} }
/* If this is both a template specialization, then it's a /* If this is a specialization of a member template of a
specialization of a member template of a template class. template class. In we want to return the TEMPLATE_DECL,
In that case we want to return the TEMPLATE_DECL, not the not the specialization of it. */
specialization of it. */
if (tsk == tsk_template) if (tsk == tsk_template)
{ {
SET_DECL_TEMPLATE_SPECIALIZATION (tmpl); SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
DECL_INITIAL (DECL_TEMPLATE_RESULT (tmpl)) = NULL_TREE;
return tmpl; return tmpl;
} }
...@@ -2025,7 +2056,7 @@ process_partial_specialization (decl) ...@@ -2025,7 +2056,7 @@ process_partial_specialization (decl)
tree type = TREE_TYPE (decl); tree type = TREE_TYPE (decl);
tree maintmpl = CLASSTYPE_TI_TEMPLATE (type); tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
tree specargs = CLASSTYPE_TI_ARGS (type); tree specargs = CLASSTYPE_TI_ARGS (type);
tree inner_args = innermost_args (specargs); tree inner_args = INNERMOST_TEMPLATE_ARGS (specargs);
tree inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms); tree inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms);
tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl); tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl);
int nargs = TREE_VEC_LENGTH (inner_args); int nargs = TREE_VEC_LENGTH (inner_args);
...@@ -2082,7 +2113,7 @@ process_partial_specialization (decl) ...@@ -2082,7 +2113,7 @@ process_partial_specialization (decl)
if (tpd.parms[i] == 0) if (tpd.parms[i] == 0)
{ {
/* One of the template parms was not used in the /* One of the template parms was not used in the
specialization. */ specialization. */
if (!did_error_intro) if (!did_error_intro)
{ {
cp_error ("template parameters not used in partial specialization:"); cp_error ("template parameters not used in partial specialization:");
...@@ -2097,9 +2128,10 @@ process_partial_specialization (decl) ...@@ -2097,9 +2128,10 @@ process_partial_specialization (decl)
The argument list of the specialization shall not be identical to The argument list of the specialization shall not be identical to
the implicit argument list of the primary template. */ the implicit argument list of the primary template. */
if (comp_template_args (inner_args, if (comp_template_args
innermost_args (CLASSTYPE_TI_ARGS (TREE_TYPE (inner_args,
(maintmpl))))) INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (TREE_TYPE
(maintmpl)))))
cp_error ("partial specialization `%T' does not specialize any template arguments", type); cp_error ("partial specialization `%T' does not specialize any template arguments", type);
/* [temp.class.spec] /* [temp.class.spec]
...@@ -2502,7 +2534,9 @@ push_template_decl_real (decl, is_friend) ...@@ -2502,7 +2534,9 @@ push_template_decl_real (decl, is_friend)
DECL_TEMPLATE_INFO (new_tmpl) DECL_TEMPLATE_INFO (new_tmpl)
= tree_cons (tmpl, args, NULL_TREE); = tree_cons (tmpl, args, NULL_TREE);
register_specialization (new_tmpl, tmpl, args); register_specialization (new_tmpl,
most_general_template (tmpl),
args);
return decl; return decl;
} }
...@@ -3124,7 +3158,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl) ...@@ -3124,7 +3158,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
tree inner_args; tree inner_args;
int is_type, requires_type, is_tmpl_type, requires_tmpl_type; int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
inner_args = innermost_args (args); inner_args = INNERMOST_TEMPLATE_ARGS (args);
if (TREE_CODE (arg) == TREE_LIST if (TREE_CODE (arg) == TREE_LIST
&& TREE_TYPE (arg) != NULL_TREE && TREE_TYPE (arg) != NULL_TREE
...@@ -3322,7 +3356,7 @@ coerce_template_parms (parms, args, in_decl, ...@@ -3322,7 +3356,7 @@ coerce_template_parms (parms, args, in_decl,
tree new_args; tree new_args;
tree new_inner_args; tree new_inner_args;
inner_args = innermost_args (args); inner_args = INNERMOST_TEMPLATE_ARGS (args);
nargs = NUM_TMPL_ARGS (inner_args); nargs = NUM_TMPL_ARGS (inner_args);
nparms = TREE_VEC_LENGTH (parms); nparms = TREE_VEC_LENGTH (parms);
...@@ -3469,7 +3503,7 @@ mangle_class_name_for_template (name, parms, arglist) ...@@ -3469,7 +3503,7 @@ mangle_class_name_for_template (name, parms, arglist)
cat (name); cat (name);
ccat ('<'); ccat ('<');
nparms = TREE_VEC_LENGTH (parms); nparms = TREE_VEC_LENGTH (parms);
arglist = innermost_args (arglist); arglist = INNERMOST_TEMPLATE_ARGS (arglist);
my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268); my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268);
for (i = 0; i < nparms; i++) for (i = 0; i < nparms; i++)
{ {
...@@ -3824,7 +3858,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope) ...@@ -3824,7 +3858,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
else else
arglist arglist
= coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist), = coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
innermost_args (arglist), INNERMOST_TEMPLATE_ARGS (arglist),
template, 1, 1); template, 1, 1);
if (arglist == error_mark_node) if (arglist == error_mark_node)
...@@ -5143,17 +5177,6 @@ maybe_fold_nontype_arg (arg) ...@@ -5143,17 +5177,6 @@ maybe_fold_nontype_arg (arg)
return arg; return arg;
} }
/* Return the TREE_VEC with the arguments for the innermost template header,
where ARGS is either that or the VEC of VECs for all the
arguments. */
tree
innermost_args (args)
tree args;
{
return TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args));
}
/* Substitute ARGS into the vector of template arguments T. */ /* Substitute ARGS into the vector of template arguments T. */
static tree static tree
...@@ -5548,7 +5571,7 @@ tsubst_decl (t, args, type, in_decl) ...@@ -5548,7 +5571,7 @@ tsubst_decl (t, args, type, in_decl)
spec_args, /*complain=*/1, in_decl); spec_args, /*complain=*/1, in_decl);
DECL_TI_TEMPLATE (new_fn) = fn; DECL_TI_TEMPLATE (new_fn) = fn;
register_specialization (new_fn, r, register_specialization (new_fn, r,
innermost_args (spec_args)); INNERMOST_TEMPLATE_ARGS (spec_args));
} }
/* Record this partial instantiation. */ /* Record this partial instantiation. */
...@@ -5593,7 +5616,19 @@ tsubst_decl (t, args, type, in_decl) ...@@ -5593,7 +5616,19 @@ tsubst_decl (t, args, type, in_decl)
break; break;
} }
/* Here, we deal with the peculiar case: /* We can see more levels of arguments than parameters if
there was a specialization of a member template, like
this:
template <class T> struct S { template <class U> void f(); }
template <> template <class U> void S<int>::f(U);
Here, we'll be subtituting into the specialization,
because that's where we can find the code we actually
want to generate, but we'll have enough arguments for
the most general template.
We also deal with the peculiar case:
template <class T> struct S { template <class T> struct S {
template <class U> friend void f(); template <class U> friend void f();
...@@ -5618,21 +5653,7 @@ tsubst_decl (t, args, type, in_decl) ...@@ -5618,21 +5653,7 @@ tsubst_decl (t, args, type, in_decl)
TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (t))); TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (t)));
if (args_depth > parms_depth if (args_depth > parms_depth
&& !DECL_TEMPLATE_SPECIALIZATION (t)) && !DECL_TEMPLATE_SPECIALIZATION (t))
{ args = get_innermost_template_args (args, parms_depth);
my_friendly_assert (DECL_FRIEND_P (t), 0);
if (parms_depth > 1)
{
int i;
args = make_tree_vec (parms_depth);
for (i = 0; i < parms_depth; ++i)
TREE_VEC_ELT (args, i) =
TREE_VEC_ELT (args, i + (args_depth - parms_depth));
}
else
args = TREE_VEC_ELT (args, args_depth - parms_depth);
}
} }
else else
{ {
...@@ -7440,25 +7461,23 @@ instantiate_template (tmpl, targ_ptr) ...@@ -7440,25 +7461,23 @@ instantiate_template (tmpl, targ_ptr)
if (spec != NULL_TREE) if (spec != NULL_TREE)
return spec; return spec;
if (DECL_TEMPLATE_INFO (tmpl) && !DECL_TEMPLATE_SPECIALIZATION (tmpl)) gen_tmpl = most_general_template (tmpl);
if (tmpl != gen_tmpl)
{ {
/* The TMPL is a partial instantiation. To get a full set of /* The TMPL is a partial instantiation. To get a full set of
arguments we must add the arguments used to perform the arguments we must add the arguments used to perform the
partial instantiation. */ partial instantiation. */
targ_ptr = add_outermost_template_args (DECL_TI_ARGS (tmpl), targ_ptr = add_outermost_template_args (DECL_TI_ARGS (tmpl),
targ_ptr); targ_ptr);
gen_tmpl = most_general_template (tmpl);
/* Check to see if we already have this specialization. */ /* Check to see if we already have this specialization. */
spec = retrieve_specialization (gen_tmpl, targ_ptr); spec = retrieve_specialization (gen_tmpl, targ_ptr);
if (spec != NULL_TREE) if (spec != NULL_TREE)
return spec; return spec;
} }
else
gen_tmpl = tmpl;
len = DECL_NTPARMS (gen_tmpl); len = DECL_NTPARMS (gen_tmpl);
inner_args = innermost_args (targ_ptr); inner_args = INNERMOST_TEMPLATE_ARGS (targ_ptr);
i = len; i = len;
while (i--) while (i--)
{ {
...@@ -8885,7 +8904,7 @@ get_class_bindings (tparms, parms, args) ...@@ -8885,7 +8904,7 @@ get_class_bindings (tparms, parms, args)
int i, ntparms = TREE_VEC_LENGTH (tparms); int i, ntparms = TREE_VEC_LENGTH (tparms);
tree vec = make_tree_vec (ntparms); tree vec = make_tree_vec (ntparms);
args = innermost_args (args); args = INNERMOST_TEMPLATE_ARGS (args);
if (unify (tparms, vec, parms, args, UNIFY_ALLOW_NONE)) if (unify (tparms, vec, parms, args, UNIFY_ALLOW_NONE))
return NULL_TREE; return NULL_TREE;
...@@ -8970,7 +8989,9 @@ most_specialized (fns, decl, explicit_args) ...@@ -8970,7 +8989,9 @@ most_specialized (fns, decl, explicit_args)
} }
/* If DECL is a specialization of some template, return the most /* If DECL is a specialization of some template, return the most
general such template. For example, given: general such template. Otherwise, returns NULL_TREE.
For example, given:
template <class T> struct S { template <class U> void f(U); }; template <class T> struct S { template <class U> void f(U); };
...@@ -8987,14 +9008,37 @@ tree ...@@ -8987,14 +9008,37 @@ tree
most_general_template (decl) most_general_template (decl)
tree decl; tree decl;
{ {
while (DECL_TEMPLATE_INFO (decl) /* If DECL is a FUNCTION_DECL, find the TEMPLATE_DECL of which it is
&& !(TREE_CODE (decl) == TEMPLATE_DECL an immediate specialization. */
&& DECL_TEMPLATE_SPECIALIZATION (decl)) if (TREE_CODE (decl) == FUNCTION_DECL)
/* The DECL_TI_TEMPLATE can be a LOOKUP_EXPR or {
IDENTIFIER_NODE in some cases. (See cp-tree.h for if (DECL_TEMPLATE_INFO (decl)) {
details.) */ decl = DECL_TI_TEMPLATE (decl);
&& TREE_CODE (DECL_TI_TEMPLATE (decl)) == TEMPLATE_DECL)
decl = DECL_TI_TEMPLATE (decl); /* The DECL_TI_TEMPLATE can be an IDENTIFIER_NODE for a
template friend. */
if (TREE_CODE (decl) != TEMPLATE_DECL)
return NULL_TREE;
} else
return NULL_TREE;
}
/* Look for more and more general templates. */
while (DECL_TEMPLATE_INFO (decl))
{
/* The DECL_TI_TEMPLATE can be a LOOKUP_EXPR or IDENTIFIER_NODE
in some cases. (See cp-tree.h for details.) */
if (TREE_CODE (DECL_TI_TEMPLATE (decl)) != TEMPLATE_DECL)
break;
/* Stop if we run into an explicitly specialized class template. */
if (!DECL_NAMESPACE_SCOPE_P (decl)
&& DECL_CONTEXT (decl)
&& CLASSTYPE_TEMPLATE_SPECIALIZATION (DECL_CONTEXT (decl)))
break;
decl = DECL_TI_TEMPLATE (decl);
}
return decl; return decl;
} }
...@@ -9345,10 +9389,13 @@ regenerate_decl_from_template (decl, tmpl) ...@@ -9345,10 +9389,13 @@ regenerate_decl_from_template (decl, tmpl)
tree decl; tree decl;
tree tmpl; tree tmpl;
{ {
/* The most general version of TMPL. */
tree gen_tmpl;
/* The arguments used to instantiate DECL, from the most general
template. */
tree args; tree args;
tree code_pattern; tree code_pattern;
tree new_decl; tree new_decl;
tree gen_tmpl;
int unregistered; int unregistered;
args = DECL_TI_ARGS (decl); args = DECL_TI_ARGS (decl);
...@@ -9474,32 +9521,30 @@ instantiate_decl (d, defer_ok) ...@@ -9474,32 +9521,30 @@ instantiate_decl (d, defer_ok)
and an instantiation of S<double>::f<int>. We want TD to be the and an instantiation of S<double>::f<int>. We want TD to be the
specialization S<T>::f<int>, not the more general S<T>::f<U>. */ specialization S<T>::f<int>, not the more general S<T>::f<U>. */
td = tmpl; td = tmpl;
for (td = tmpl; while (/* An instantiation cannot have a definition, so we need a
/* An instantiation cannot have a definition, so we need a more general template. */
more general template. */ DECL_TEMPLATE_INSTANTIATION (td)
DECL_TEMPLATE_INSTANTIATION (td) /* We must also deal with friend templates. Given:
/* We must also deal with friend templates. Given:
template <class T> struct S {
template <class T> struct S { template <class U> friend void f() {};
template <class U> friend void f() {}; };
};
S<int>::f<U> say, is not an instantiation of S<T>::f<U>,
S<int>::f<U> say, is not an instantiation of S<T>::f<U>, so far as the language is concerned, but that's still
so far as the language is concerned, but that's still where we get the pattern for the instantiation from. On
where we get the pattern for the instantiation from. On ther hand, if the definition comes outside the class, say:
ther hand, if the definition comes outside the class, say:
template <class T> struct S {
template <class T> struct S { template <class U> friend void f();
template <class U> friend void f(); };
}; template <class U> friend void f() {}
template <class U> friend void f() {}
we don't need to look any further. That's what the check for
we don't need to look any further. That's what the check for DECL_INITIAL is for. */
DECL_INITIAL is for. */ || (TREE_CODE (d) == FUNCTION_DECL
|| (TREE_CODE (d) == FUNCTION_DECL && DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (td)
&& DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (td) && !DECL_INITIAL (DECL_TEMPLATE_RESULT (td))))
&& !DECL_INITIAL (DECL_TEMPLATE_RESULT (td)));
)
{ {
/* The present template, TD, should not be a definition. If it /* The present template, TD, should not be a definition. If it
were a definition, we should be using it! Note that we were a definition, we should be using it! Note that we
...@@ -9941,7 +9986,7 @@ set_mangled_name_for_template_decl (decl) ...@@ -9941,7 +9986,7 @@ set_mangled_name_for_template_decl (decl)
/* Replace the innermost level of the TARGS with NULL_TREEs to /* Replace the innermost level of the TARGS with NULL_TREEs to
let tsubst know not to subsitute for those parameters. */ let tsubst know not to subsitute for those parameters. */
partial_args = make_tree_vec (TREE_VEC_LENGTH (targs)); partial_args = make_tree_vec (TMPL_ARGS_DEPTH (targs));
for (i = 1; i < TMPL_ARGS_DEPTH (targs); ++i) for (i = 1; i < TMPL_ARGS_DEPTH (targs); ++i)
SET_TMPL_ARGS_LEVEL (partial_args, i, SET_TMPL_ARGS_LEVEL (partial_args, i,
TMPL_ARGS_LEVEL (targs, i)); TMPL_ARGS_LEVEL (targs, i));
...@@ -9966,7 +10011,7 @@ set_mangled_name_for_template_decl (decl) ...@@ -9966,7 +10011,7 @@ set_mangled_name_for_template_decl (decl)
/* Now, get the innermost parameters and arguments, and figure out /* Now, get the innermost parameters and arguments, and figure out
the parameter and return types. */ the parameter and return types. */
tparms = INNERMOST_TEMPLATE_PARMS (tparms); tparms = INNERMOST_TEMPLATE_PARMS (tparms);
targs = innermost_args (targs); targs = INNERMOST_TEMPLATE_ARGS (targs);
ret_type = TREE_TYPE (fn_type); ret_type = TREE_TYPE (fn_type);
parm_types = TYPE_ARG_TYPES (fn_type); parm_types = TYPE_ARG_TYPES (fn_type);
......
// Build don't link:
// Origin: Jason Merrill <jason@cygnus.com>
template <class T> struct A {
template <class U> void f(U);
};
template <>
template <class U>
void A<int>::f(U);
A<int> a;
void g ()
{
a.f (3);
}
// Origin: Mark Mitchell <mark@codesourcery.com>
template <class T> struct A {
template <class U> int f(U) { return 1; }
};
template <>
template <class U>
int A<int>::f(U) { return 0; }
A<int> a;
int main ()
{
return a.f (3);
}
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