This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: C++ PATCH for member template classes
>>>>> "Jason" == Jason Merrill <jason@cygnus.com> writes:
Jason> This seems wrong; I don't see anything in the standard to
Jason> suggest that (say) auto_ptr<void>::auto_ptr_ref<int> and
Jason> auto_ptr<int>::auto_ptr_ref<int> have anything in common.
Actually, on second thought, I'm not sure the patch would have broken
things after all. Even if specializations_of_same_template_p holds,
unify will be unable to unify the outer template arguments. So, for
example,
template <class T>
struct S
{
template <class U>
struct I {};
template <class U>
static void f(I<U> iu);
};
void g()
{
S<double>::I<char> i;
S<int>::f(i);
}
still gives an error, as expected. But, back to the original test
case:
template <class T> struct S
{
template <class U> struct I
{
};
S();
S(S& s);
S(I<T>);
template <class U> operator I<U>();
};
S<int> f();
void g(S<int>);
void h()
{
g(f());
}
The oddity I referred to earlier, is that when we unify S<int>::I<U>
with S<int>::I<int> it turns out that CLASSTYPE_TI_TEMPLATE for the
former is S<int>::I<U> while for the latter it is S<T>::I<U>. (That's
why unification failed.) The reason for this anomaly is that
lookup_template_class doesn't make any effort to find the immediate
parent (S<int>::I<U>) when asked to find a specialization of
S<T>::I<U> given the two levels of args { int, int }. The attached
patch fixes that problem, which allows the removal of my earlier
patch.
--
Mark Mitchell mark@markmitchell.com
Mark Mitchell Consulting http://www.markmitchell.com
1998-10-13 Mark Mitchell <mark@markmitchell.com>
* cp-tree.h (specializations_of_same_template_p): Remove.
* search.c (get_template_base): Don't use it.
(get_template_base_recursive): Likewise.
* pt.c (specializations_of_same_template_p): Remove.
(unify): Don't use it.
(lookup_template_class): Find the correct parent when setting
CLASSTYPE_TI_TEMPLATE.
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.151
diff -c -p -r1.151 cp-tree.h
*** cp-tree.h 1998/10/12 02:08:06 1.151
--- cp-tree.h 1998/10/13 21:15:00
*************** extern int is_specialization_of
*** 2869,2875 ****
extern int comp_template_args PROTO((tree, tree));
extern void maybe_process_partial_specialization PROTO((tree));
extern void maybe_check_template_type PROTO((tree));
- extern int specializations_of_same_template_p PROTO((tree, tree));
extern int processing_specialization;
extern int processing_explicit_instantiation;
--- 2869,2874 ----
Index: pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.212
diff -c -p -r1.212 pt.c
*** pt.c 1998/10/11 17:38:53 1.212
--- pt.c 1998/10/13 21:15:50
*************** is_specialization_of (decl, tmpl)
*** 756,777 ****
return 0;
}
- /* Returns nonzero if T1 and T2 are instances of the same template.
- (They may have different template arguments.) */
-
- int
- specializations_of_same_template_p (t1, t2)
- tree t1;
- tree t2;
- {
- /* For now, we only deal with instances of class templates, since
- that is the only way in which this function is used. */
-
- return (most_general_template (CLASSTYPE_TI_TEMPLATE (t1))
- == most_general_template (CLASSTYPE_TI_TEMPLATE (t2)));
- }
-
-
/* Register the specialization SPEC as a specialization of TMPL with
the indicated ARGS. Returns SPEC, or an equivalent prior
declaration, if available. */
--- 756,761 ----
*************** classtype_mangled_name (t)
*** 3201,3222 ****
if (CLASSTYPE_TEMPLATE_INFO (t)
/* Specializations have already had their names set up in
lookup_template_class. */
! && !CLASSTYPE_TEMPLATE_SPECIALIZATION (t)
/* For non-primary templates, the template parameters are
implicit from their surrounding context. */
! && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
! {
! tree name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
! char *mangled_name = mangle_class_name_for_template
! (IDENTIFIER_POINTER (name),
! DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
! CLASSTYPE_TI_ARGS (t));
! tree id = get_identifier (mangled_name);
! IDENTIFIER_TEMPLATE (id) = name;
! return id;
}
! else
! return TYPE_IDENTIFIER (t);
}
static void
--- 3185,3210 ----
if (CLASSTYPE_TEMPLATE_INFO (t)
/* Specializations have already had their names set up in
lookup_template_class. */
! && !CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
! {
! tree tmpl = most_general_template (CLASSTYPE_TI_TEMPLATE (t));
!
/* For non-primary templates, the template parameters are
implicit from their surrounding context. */
! if (PRIMARY_TEMPLATE_P (tmpl))
! {
! tree name = DECL_NAME (tmpl);
! char *mangled_name = mangle_class_name_for_template
! (IDENTIFIER_POINTER (name),
! DECL_INNERMOST_TEMPLATE_PARMS (tmpl),
! CLASSTYPE_TI_ARGS (t));
! tree id = get_identifier (mangled_name);
! IDENTIFIER_TEMPLATE (id) = name;
! return id;
! }
}
!
! return TYPE_IDENTIFIER (t);
}
static void
*************** lookup_template_class (d1, arglist, in_d
*** 3602,3612 ****
}
else
type_decl = TYPE_NAME (t);
- /* Set up the template information. */
arglist = copy_to_permanent (arglist);
SET_TYPE_TEMPLATE_INFO (t,
! tree_cons (template, arglist, NULL_TREE));
DECL_TEMPLATE_INSTANTIATIONS (template)
= tree_cons (arglist, t,
DECL_TEMPLATE_INSTANTIATIONS (template));
--- 3590,3649 ----
}
else
type_decl = TYPE_NAME (t);
+
+ /* Set up the template information. We have to figure out which
+ template is the immediate parent if this is a full
+ instantiation. */
+ if (parm_depth == 1 || is_partial_instantiation
+ || !PRIMARY_TEMPLATE_P (template))
+ /* This case is easy; there are no member templates involved. */
+ found = template;
+ else
+ {
+ /* This is a full instantiation of a member template. There
+ should be some partial instantiation of which this is an
+ instance. */
+
+ for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
+ found; found = TREE_CHAIN (found))
+ {
+ int success;
+ tree tmpl = CLASSTYPE_TI_TEMPLATE (TREE_VALUE (found));
+
+ /* We only want partial instantiations, here, not
+ specializations or full instantiations. */
+ if (CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_VALUE (found))
+ || !uses_template_parms (TREE_VALUE (found)))
+ continue;
+
+ /* Temporarily reduce by one the number of levels in the
+ ARGLIST and in FOUND so as to avoid comparing the
+ last set of arguments. */
+ TREE_VEC_LENGTH (arglist)--;
+ TREE_VEC_LENGTH (TREE_PURPOSE (found)) --;
+
+ /* See if the arguments match. If they do, then TMPL is
+ the partial instantiation we want. */
+ success = comp_template_args (TREE_PURPOSE (found), arglist);
+
+ /* Restore the argument vectors to their full size. */
+ TREE_VEC_LENGTH (arglist)++;
+ TREE_VEC_LENGTH (TREE_PURPOSE (found))++;
+
+ if (success)
+ {
+ found = tmpl;
+ break;
+ }
+ }
+
+ if (!found)
+ my_friendly_abort (0);
+ }
arglist = copy_to_permanent (arglist);
SET_TYPE_TEMPLATE_INFO (t,
! tree_cons (found, arglist, NULL_TREE));
DECL_TEMPLATE_INSTANTIATIONS (template)
= tree_cons (arglist, t,
DECL_TEMPLATE_INSTANTIATIONS (template));
*************** unify (tparms, targs, parm, arg, strict,
*** 7363,7369 ****
derivation is involved. */
t = get_template_base (CLASSTYPE_TI_TEMPLATE (parm), arg);
else if (CLASSTYPE_TEMPLATE_INFO (arg)
! && specializations_of_same_template_p (parm, arg))
/* Perhaps PARM is something like S<U> and ARG is S<int>.
Then, we should unify `int' and `U'. */
t = arg;
--- 7400,7407 ----
derivation is involved. */
t = get_template_base (CLASSTYPE_TI_TEMPLATE (parm), arg);
else if (CLASSTYPE_TEMPLATE_INFO (arg)
! && (CLASSTYPE_TI_TEMPLATE (parm)
! == CLASSTYPE_TI_TEMPLATE (arg)))
/* Perhaps PARM is something like S<U> and ARG is S<int>.
Then, we should unify `int' and `U'. */
t = arg;
Index: search.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/search.c,v
retrieving revision 1.58
diff -c -p -r1.58 search.c
*** search.c 1998/10/11 17:38:52 1.58
--- search.c 1998/10/13 21:15:59
*************** get_template_base_recursive (binfo, rval
*** 3317,3324 ****
tree type = BINFO_TYPE (binfo);
if (CLASSTYPE_TEMPLATE_INFO (type)
! && specializations_of_same_template_p (TREE_TYPE (template),
! type))
{
if (rval == NULL_TREE || rval == type)
return type;
--- 3317,3323 ----
tree type = BINFO_TYPE (binfo);
if (CLASSTYPE_TEMPLATE_INFO (type)
! && CLASSTYPE_TI_TEMPLATE (type) == template)
{
if (rval == NULL_TREE || rval == type)
return type;
*************** get_template_base (template, binfo)
*** 3376,3383 ****
my_friendly_abort (92);
if (CLASSTYPE_TEMPLATE_INFO (type)
! && specializations_of_same_template_p (TREE_TYPE (template),
! type))
return type;
rval = get_template_base_recursive (binfo, NULL_TREE, template, 0);
--- 3375,3381 ----
my_friendly_abort (92);
if (CLASSTYPE_TEMPLATE_INFO (type)
! && CLASSTYPE_TI_TEMPLATE (type) == template)
return type;
rval = get_template_base_recursive (binfo, NULL_TREE, template, 0);
--
Mark Mitchell mark@markmitchell.com
Mark Mitchell Consulting http://www.markmitchell.com