aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@markmitchell.com>1998-08-24 19:44:48 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1998-08-24 19:44:48 +0000
commitd8c4447d837d01e68fee9f34328b8472c6785149 (patch)
tree74fb0bb47f4792bd06b0de7aab21dc2e51ef28c9 /gcc
parent6f77675fd9d508dfd431a888275f369bb30d89ab (diff)
downloadgcc-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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/pt.c88
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/friend32.C16
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;
+}