This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Patch for member class template problems
- To: egcs at cygnus dot com
- Subject: Patch for member class template problems
- From: Kriang Lerdsuwanakij <lerdsuwa at scf-fs dot usc dot edu>
- Date: Sun, 29 Mar 1998 14:33:31 -0800 (PST)
Hi
I fix several problems in template code exposed by the recent addition of
member class template. The changes are summarized below:
- instantiate_class_template now supplies unbound template arguments when
calling tsubst. This is required to partially instantiate templates
inside the template class/function. In memclass8.C, D<0> is instantiated
while its context, C<T>, still not bound until inside main().
The TEMPLATE_ARGS_UNBOUND_P macro is introduced to ensure that we don't
take into account unbound outer template arguments when reducing template
level.
- Name mangling mechanism inside tsubst, case FUNCTION_DECL is changed.
It doesn't work when the function template is a member of member class
template. Wrong template parameters and arguments were used to build
the mangled name. I change the code so that unbound arguments are
used rather than resort to outer levels when the desired arguments are
still not bound. The changes only effect name mangling of partially
instantiated templates and does not appear in object files.
--Kriang
===================================================================
* cp-tree.h (TEMPLATE_ARGS_UNBOUND_P): New macro.
pt.c (complete_template_args, tsubst): Use it.
(complete_template_args): Handle member class template.
(instantiate_class_template): Add unbound outer template
arguments if available.
(instantiate_decl): Do not tsubst non-template member
function.
(tsubst, FUNCTION_DECL): Always use innermost template
parameters for name mangling.
===================================================================
diff -cpNr gcc-980322/cp/cp-tree.h gcc-980329/cp/cp-tree.h
*** gcc-980322/cp/cp-tree.h Fri Mar 27 12:36:21 1998
--- gcc-980329/cp/cp-tree.h Fri Mar 27 12:35:36 1998
*************** struct lang_decl
*** 1157,1162 ****
--- 1157,1166 ----
#define CLASSTYPE_TI_SPEC_INFO(NODE) TI_SPEC_INFO (CLASSTYPE_TEMPLATE_INFO (NODE))
#define INNERMOST_TEMPLATE_PARMS(NODE) TREE_VALUE(NODE)
+ /* True if unbound template arguments are added to this template
+ argument vector. */
+ #define TEMPLATE_ARGS_UNBOUND_P(NODE) TREE_LANG_FLAG_0 (NODE)
+
#define TEMPLATE_PARMS_FOR_INLINE(NODE) TREE_LANG_FLAG_1 (NODE)
#define DECL_SAVED_TREE(NODE) DECL_MEMFUNC_POINTER_TO (NODE)
diff -cpNr gcc-980322/cp/pt.c gcc-980329/cp/pt.c
*** gcc-980322/cp/pt.c Fri Mar 27 12:36:50 1998
--- gcc-980329/cp/pt.c Sun Mar 29 14:16:41 1998
*************** complete_template_args (tmpl, extra_args
*** 410,419 ****
return extra_args;
new_args = make_tree_vec (depth + 1);
/* If this isn't a member template, extra_args is for the innermost
template class, so skip over it. */
! skip = (! is_member_template (tmpl));
type = DECL_REAL_CONTEXT (tmpl);
for (i = depth; i; type = TYPE_CONTEXT (type))
--- 410,421 ----
return extra_args;
new_args = make_tree_vec (depth + 1);
+ TEMPLATE_ARGS_UNBOUND_P (new_args) = 1;
/* If this isn't a member template, extra_args is for the innermost
template class, so skip over it. */
! skip = (! is_member_template (tmpl)
! && TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) != TYPE_DECL);
type = DECL_REAL_CONTEXT (tmpl);
for (i = depth; i; type = TYPE_CONTEXT (type))
*************** instantiate_class_template (type)
*** 3188,3193 ****
--- 3190,3197 ----
if (outer_args)
args = add_to_template_args (outer_args, args);
+ else
+ args = complete_template_args (TI_TEMPLATE (template_info), args, 1);
if (flag_external_templates)
{
*************** tsubst (t, args, in_decl)
*** 3682,3687 ****
--- 3686,3696 ----
more deeply nested template. */
my_friendly_assert(level > 1, 0);
+ /* Only reduce template level by 1 when outer template arguments are
+ unbound. */
+ if (TEMPLATE_ARGS_UNBOUND_P (args))
+ levels = 1;
+
/* Make a new version of this template parameter, but with a
lower level. */
switch (TREE_CODE (t))
*************** tsubst (t, args, in_decl)
*** 3726,3731 ****
--- 3735,3743 ----
tree parms;
tree* new_parms;
tree spec;
+ int parm_depth;
+ int level_reduce;
+ int j;
if (TREE_CODE (decl) == TYPE_DECL
&& TREE_CODE (TREE_TYPE (decl)) == TEMPLATE_TEMPLATE_PARM)
*************** tsubst (t, args, in_decl)
*** 3772,3785 ****
DECL_TEMPLATE_INSTANTIATIONS (tmpl) = NULL_TREE;
SET_DECL_IMPLICIT_INSTANTIATION (tmpl);
/* The template parameters for this new template are all the
template parameters for the old template, except the
outermost level of parameters. */
for (new_parms = &DECL_TEMPLATE_PARMS (tmpl),
! parms = DECL_TEMPLATE_PARMS (t);
! TREE_CHAIN (parms) != NULL_TREE;
new_parms = &(TREE_CHAIN (*new_parms)),
! parms = TREE_CHAIN (parms))
{
tree new_vec =
make_tree_vec (TREE_VEC_LENGTH (TREE_VALUE (parms)));
--- 3784,3806 ----
DECL_TEMPLATE_INSTANTIATIONS (tmpl) = NULL_TREE;
SET_DECL_IMPLICIT_INSTANTIATION (tmpl);
+ level_reduce = TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC
+ ? 1: TREE_VEC_LENGTH (args);
+ /* Only reduce template level by 1 when outer template arguments are
+ unbound. */
+ if (level_reduce > 1 && TEMPLATE_ARGS_UNBOUND_P (args))
+ level_reduce = 1;
+
+ parm_depth = list_length (DECL_TEMPLATE_PARMS (tmpl));
+
/* The template parameters for this new template are all the
template parameters for the old template, except the
outermost level of parameters. */
for (new_parms = &DECL_TEMPLATE_PARMS (tmpl),
! parms = DECL_TEMPLATE_PARMS (t), j = 0;
! j < parm_depth - level_reduce;
new_parms = &(TREE_CHAIN (*new_parms)),
! parms = TREE_CHAIN (parms), ++j)
{
tree new_vec =
make_tree_vec (TREE_VEC_LENGTH (TREE_VALUE (parms)));
*************** tsubst (t, args, in_decl)
*** 3801,3807 ****
*new_parms =
tree_cons (build_int_2 (0,
TREE_INT_CST_HIGH
! (TREE_PURPOSE (parms)) - 1),
new_vec,
NULL_TREE);
}
--- 3822,3828 ----
*new_parms =
tree_cons (build_int_2 (0,
TREE_INT_CST_HIGH
! (TREE_PURPOSE (parms)) - level_reduce),
new_vec,
NULL_TREE);
}
*************** tsubst (t, args, in_decl)
*** 3991,4007 ****
if (!DECL_TEMPLATE_SPECIALIZATION (tmpl))
{
! /* We pass the outermost template parameters to
! build_template_decl_overload, since the innermost
! template parameters are still just template
! parameters; there are no corresponding subsitution
! arguments. Levels of parms that have been bound
! before are not represented in DECL_TEMPLATE_PARMS. */
tparms = DECL_TEMPLATE_PARMS (tmpl);
! while (tparms && TREE_CHAIN (tparms) != NULL_TREE)
! tparms = TREE_CHAIN (tparms);
!
! targs = innermost_args (args, 0);
}
else
{
--- 4012,4037 ----
if (!DECL_TEMPLATE_SPECIALIZATION (tmpl))
{
! /* We pass the innermost template parameters to
! build_template_decl_overload. The corresponding
! template arguments may come from ARGS or may
! still just template parameters. Levels of parms
! that have been bound before are not represented
! in DECL_TEMPLATE_PARMS. */
tparms = DECL_TEMPLATE_PARMS (tmpl);
!
! if (DECL_TEMPLATE_INFO (r))
! {
! int depth1 = TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC
! ? 1: TREE_VEC_LENGTH (args);
! int depth2 = list_length (tparms);
! if (depth1 < depth2)
! targs = DECL_TI_ARGS (r);
! else
! targs = innermost_args (args, 0);
! }
! else
! targs = innermost_args (args, 0);
}
else
{
*************** instantiate_decl (d)
*** 6248,6262 ****
lineno = DECL_SOURCE_LINE (d);
input_filename = DECL_SOURCE_FILE (d);
! /* Trick tsubst into giving us a new decl in case the template changed. */
! save_ti = DECL_TEMPLATE_INFO (decl_pattern);
! DECL_TEMPLATE_INFO (decl_pattern) = NULL_TREE;
! /* decl_pattern has all but one level of template parms bound. Only pass
! in that one level of args. */
! temp = innermost_args (args, DECL_TEMPLATE_SPECIALIZATION (decl_pattern));
! td = tsubst (decl_pattern, temp, tmpl);
! SET_DECL_IMPLICIT_INSTANTIATION (td);
! DECL_TEMPLATE_INFO (decl_pattern) = save_ti;
/* And set up DECL_INITIAL, since tsubst doesn't. */
if (TREE_CODE (td) == VAR_DECL)
--- 6278,6304 ----
lineno = DECL_SOURCE_LINE (d);
input_filename = DECL_SOURCE_FILE (d);
! if (DECL_CONTEXT (code_pattern) != NULL_TREE
! && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (code_pattern))) == 't'
! && ! is_member_template (code_pattern)
! && TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) != TYPE_DECL)
! /* For non-template member functions, All levels of template arguments
! is already bounded. We don't want to do it again. */
! td = d;
! else
! {
! /* Trick tsubst into giving us a new decl in case the template
! changed. */
! save_ti = DECL_TEMPLATE_INFO (decl_pattern);
! DECL_TEMPLATE_INFO (decl_pattern) = NULL_TREE;
! /* decl_pattern has all but one level of template parms bound. Only
! pass in that one level of args. */
! temp = innermost_args (args, DECL_TEMPLATE_SPECIALIZATION (decl_pattern));
!
! td = tsubst (decl_pattern, temp, tmpl);
! SET_DECL_IMPLICIT_INSTANTIATION (td);
! DECL_TEMPLATE_INFO (decl_pattern) = save_ti;
! }
/* And set up DECL_INITIAL, since tsubst doesn't. */
if (TREE_CODE (td) == VAR_DECL)
diff -cpNr gcc-980322/testsuite/g++.old-deja/g++.pt/memclass10.C gcc-980329/testsuite/g++.old-deja/g++.pt/memclass10.C
*** gcc-980322/testsuite/g++.old-deja/g++.pt/memclass10.C Wed Dec 31 16:00:00 1969
--- gcc-980329/testsuite/g++.old-deja/g++.pt/memclass10.C Fri Mar 27 12:53:09 1998
***************
*** 0 ****
--- 1,13 ----
+ template <class T> struct A {
+ template <int U> struct B {
+ template <class V> void f (V) { }
+ void g () { }
+ };
+ };
+
+ main ()
+ {
+ A<int>::B<1> b;
+ b.f (42);
+ b.g ();
+ }
diff -cpNr gcc-980322/testsuite/g++.old-deja/g++.pt/memclass11.C gcc-980329/testsuite/g++.old-deja/g++.pt/memclass11.C
*** gcc-980322/testsuite/g++.old-deja/g++.pt/memclass11.C Wed Dec 31 16:00:00 1969
--- gcc-980329/testsuite/g++.old-deja/g++.pt/memclass11.C Fri Mar 27 12:53:48 1998
***************
*** 0 ****
--- 1,20 ----
+ template <class T> struct A {
+ template <int i> struct AA {
+ template <class U> struct B {
+ template <class V> void f (V) { }
+ void g () { }
+ };
+ template <class W> struct B<W*> {
+ void h () { }
+ };
+ };
+ };
+
+ main ()
+ {
+ A<int>::AA<0>::B<char> b;
+ b.f (42);
+ b.g ();
+ A<double>::AA<1>::B<void*> b2;
+ b2.h ();
+ }
diff -cpNr gcc-980322/testsuite/g++.old-deja/g++.pt/memclass8.C gcc-980329/testsuite/g++.old-deja/g++.pt/memclass8.C
*** gcc-980322/testsuite/g++.old-deja/g++.pt/memclass8.C Wed Dec 31 16:00:00 1969
--- gcc-980329/testsuite/g++.old-deja/g++.pt/memclass8.C Fri Mar 27 12:51:20 1998
***************
*** 0 ****
--- 1,9 ----
+ template <class T> class C {
+ template <int i> class D {};
+ D<0> d;
+ };
+
+ int main()
+ {
+ C<int> c;
+ }
diff -cpNr gcc-980322/testsuite/g++.old-deja/g++.pt/memclass9.C gcc-980329/testsuite/g++.old-deja/g++.pt/memclass9.C
*** gcc-980322/testsuite/g++.old-deja/g++.pt/memclass9.C Wed Dec 31 16:00:00 1969
--- gcc-980329/testsuite/g++.old-deja/g++.pt/memclass9.C Fri Mar 27 12:52:52 1998
***************
*** 0 ****
--- 1,11 ----
+ template <class T> struct C {
+ template <int i> struct D {
+ template <class U> struct E {};
+ };
+ D<0>::E<T> e;
+ };
+
+ int main()
+ {
+ C<int> c;
+ }