Commit d8c4447d by Mark Mitchell Committed by Mark Mitchell

pt.c (tsubst_decl): Move special case code for dealing with tricky friend templates here from ...

	* pt.c (tsubst_decl): Move special case code for dealing with
	tricky friend templates here from ...
	(regenerate_decl_from_template): Here.

From-SVN: r21953
parent 6f77675f
1998-08-24 Mark Mitchell <mark@markmitchell.com>
* pt.c (tsubst_decl): Move special case code for dealing with
tricky friend templates here from ...
(regenerate_decl_from_template): Here.
1998-08-24 Jason Merrill <jason@yorick.cygnus.com> 1998-08-24 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (start_decl): Remove redundant linkage check. * decl.c (start_decl): Remove redundant linkage check.
......
...@@ -4863,6 +4863,8 @@ tsubst_decl (t, args, type, in_decl) ...@@ -4863,6 +4863,8 @@ tsubst_decl (t, args, type, in_decl)
tree argvec; tree argvec;
tree gen_tmpl; tree gen_tmpl;
int member; int member;
int args_depth;
int parms_depth;
/* Nobody should be tsubst'ing into non-template functions. */ /* Nobody should be tsubst'ing into non-template functions. */
my_friendly_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE, 0); my_friendly_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE, 0);
...@@ -4885,6 +4887,47 @@ tsubst_decl (t, args, type, in_decl) ...@@ -4885,6 +4887,47 @@ tsubst_decl (t, args, type, in_decl)
r = spec; r = spec;
break; break;
} }
/* Here, we deal with the peculiar case:
template <class T> struct S {
template <class U> friend void f();
};
template <class U> friend void f() {}
template S<int>;
template void f<double>();
Here, the ARGS for the instantiation of will be {int,
double}. But, we only need as many ARGS as there are
levels of template parameters in CODE_PATTERN. We are
careful not to get fooled into reducing the ARGS in
situations like:
template <class T> struct S { template <class U> void f(U); }
template <class T> template <> void S<T>::f(int) {}
which we can spot because the pattern will be a
specialization in this case. */
args_depth = TMPL_ARGS_DEPTH (args);
parms_depth =
TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (t)));
if (args_depth > parms_depth
&& !DECL_TEMPLATE_SPECIALIZATION (t))
{
my_friendly_assert (DECL_FRIEND_P (t), 0);
if (parms_depth > 1)
{
int i;
args = make_temp_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
{ {
...@@ -7739,9 +7782,6 @@ regenerate_decl_from_template (decl, tmpl) ...@@ -7739,9 +7782,6 @@ regenerate_decl_from_template (decl, tmpl)
tree code_pattern; tree code_pattern;
tree new_decl; tree new_decl;
tree gen_tmpl; tree gen_tmpl;
tree subst_args;
int args_depth;
int parms_depth;
int unregistered; int unregistered;
args = DECL_TI_ARGS (decl); args = DECL_TI_ARGS (decl);
...@@ -7760,51 +7800,15 @@ regenerate_decl_from_template (decl, tmpl) ...@@ -7760,51 +7800,15 @@ regenerate_decl_from_template (decl, tmpl)
register_specialization for it. */ register_specialization for it. */
my_friendly_assert (unregistered, 0); my_friendly_assert (unregistered, 0);
/* Do the substitution to get the new declaration. Normally, of /* Do the substitution to get the new declaration. */
course, we want the full set of ARGS. However, one peculiar case new_decl = tsubst (code_pattern, args, NULL_TREE);
is code like this:
template <class T> struct S {
template <class U> friend void f();
};
template <class U> friend void f() {}
template S<int>;
template void f<double>();
Here, the ARGS for the instantiation of will be {int, double}.
But, we only need as many ARGS as there are levels of template
parameters in CODE_PATTERN. We are careful not to get fooled
into reducing the ARGS in situations like:
template <class T> struct S { template <class U> void f(U); }
template <class T> template <> void S<T>::f(int) {}
which we can spot because the innermost template args for the
CODE_PATTERN don't use any template parameters. */
args_depth = TMPL_ARGS_DEPTH (args);
parms_depth =
TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (code_pattern)));
if (args_depth > parms_depth
&& !DECL_TEMPLATE_SPECIALIZATION (code_pattern))
{
int i;
subst_args = make_temp_vec (parms_depth);
for (i = 0; i < parms_depth; ++i)
TREE_VEC_ELT (subst_args, i) =
TREE_VEC_ELT (args, i + (args_depth - parms_depth));
}
else
subst_args = args;
new_decl = tsubst (code_pattern, subst_args, NULL_TREE);
if (TREE_CODE (decl) == VAR_DECL) if (TREE_CODE (decl) == VAR_DECL)
{ {
/* Set up DECL_INITIAL, since tsubst doesn't. */ /* Set up DECL_INITIAL, since tsubst doesn't. */
pushclass (DECL_CONTEXT (decl), 2); pushclass (DECL_CONTEXT (decl), 2);
DECL_INITIAL (new_decl) = DECL_INITIAL (new_decl) =
tsubst_expr (DECL_INITIAL (code_pattern), subst_args, tsubst_expr (DECL_INITIAL (code_pattern), args,
DECL_TI_TEMPLATE (decl)); DECL_TI_TEMPLATE (decl));
popclass (1); popclass (1);
} }
......
// Build don't link:
template <class T, class U>
struct S {
template <class X, class Y, class Z>
friend X f(X, Y, Z);
};
template class S<int, double>;
template char f(char, long, short);
template char* f(char*, long*, short*);
template <class X, class Y, class Z>
X f(X x, Y, Z) {
return x;
}
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