diff options
author | Mark Mitchell <mark@markmitchell.com> | 1998-08-24 19:44:48 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1998-08-24 19:44:48 +0000 |
commit | d8c4447d837d01e68fee9f34328b8472c6785149 (patch) | |
tree | 74fb0bb47f4792bd06b0de7aab21dc2e51ef28c9 | |
parent | 6f77675fd9d508dfd431a888275f369bb30d89ab (diff) | |
download | gcc-d8c4447d837d01e68fee9f34328b8472c6785149.zip gcc-d8c4447d837d01e68fee9f34328b8472c6785149.tar.gz gcc-d8c4447d837d01e68fee9f34328b8472c6785149.tar.bz2 |
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
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/pt.c | 88 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/friend32.C | 16 |
3 files changed, 68 insertions, 42 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d171e64..edd3764 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +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> * decl.c (start_decl): Remove redundant linkage check. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 1bf232e..f817896 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -4863,6 +4863,8 @@ tsubst_decl (t, args, type, in_decl) tree argvec; tree gen_tmpl; int member; + int args_depth; + int parms_depth; /* Nobody should be tsubst'ing into non-template functions. */ my_friendly_assert (DECL_TEMPLATE_INFO (t) != NULL_TREE, 0); @@ -4885,6 +4887,47 @@ tsubst_decl (t, args, type, in_decl) r = spec; 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 { @@ -7739,9 +7782,6 @@ regenerate_decl_from_template (decl, tmpl) tree code_pattern; tree new_decl; tree gen_tmpl; - tree subst_args; - int args_depth; - int parms_depth; int unregistered; args = DECL_TI_ARGS (decl); @@ -7760,51 +7800,15 @@ regenerate_decl_from_template (decl, tmpl) register_specialization for it. */ my_friendly_assert (unregistered, 0); - /* Do the substitution to get the new declaration. Normally, of - course, we want the full set of ARGS. However, one peculiar case - 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); + /* Do the substitution to get the new declaration. */ + new_decl = tsubst (code_pattern, args, NULL_TREE); if (TREE_CODE (decl) == VAR_DECL) { /* Set up DECL_INITIAL, since tsubst doesn't. */ pushclass (DECL_CONTEXT (decl), 2); DECL_INITIAL (new_decl) = - tsubst_expr (DECL_INITIAL (code_pattern), subst_args, + tsubst_expr (DECL_INITIAL (code_pattern), args, DECL_TI_TEMPLATE (decl)); popclass (1); } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend32.C b/gcc/testsuite/g++.old-deja/g++.pt/friend32.C new file mode 100644 index 0000000..b1f173a --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/friend32.C @@ -0,0 +1,16 @@ +// 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; +} |