Fix PR c++/42225, take 2

gcc/cp/ChangeLog:
	PR c++/42225
	* pt.c (push_template_decl_real): Set DECL_CONTEXT of template type
	parms to their containing template decl.
	* typeck.c (comp_template_parms_position): Split this from
	structural_comptypes.
	(incompatible_template_type_parms_p): Renamed
	incompatible_dependent_typedefs_p into this. Change the function to
	handle comparison between TEMPLATE_TYPE_PARMs only.
	(structural_comptypes): Use comp_template_parms_position in
	TEMPLATE_TEMPLATE_PARM and BOUND_TEMPLATE_TEMPLATE_PARM cases.
	Use incompatible_template_type_parms_p in TEMPLATE_TYPE_PARM case.
	* mangle.c (decl_mangling_context): Template type parms don't have
	a mangling context.
	* tree.c (cp_set_underlying_type): Set type structural equality
	only for TEMPLATE_TYPE_PARMs.

gcc/testsuite/ChangeLog:
	PR c++/42225
	* g++.dg/template/typedef26.C: New test.

From-SVN: r155363
This commit is contained in:
Dodji Seketeli 2009-12-19 22:40:37 +00:00 committed by Dodji Seketeli
parent b0ce048a3f
commit e96ce650a8
7 changed files with 151 additions and 40 deletions

View File

@ -1,3 +1,21 @@
2009-12-19 Dodji Seketeli <dodji@redhat.com>
PR c++/42225
* pt.c (push_template_decl_real): Set DECL_CONTEXT of template type parms
to their containing template decl.
* typeck.c (comp_template_parms_position): Split this from
structural_comptypes.
(incompatible_template_type_parms_p): Renamed
incompatible_dependent_typedefs_p into this. Change the function to
handle comparison between TEMPLATE_TYPE_PARMs only.
(structural_comptypes): Use comp_template_parms_position in
TEMPLATE_TEMPLATE_PARM and BOUND_TEMPLATE_TEMPLATE_PARM cases.
Use incompatible_template_type_parms_p in TEMPLATE_TYPE_PARM case.
* mangle.c (decl_mangling_context): Template type parms don't have
a mangling context.
* tree.c (cp_set_underlying_type): Set type structural equality
only for TEMPLATE_TYPE_PARMs.
2009-12-18 Jason Merrill <jason@redhat.com>
PR c++/28300

View File

@ -743,6 +743,10 @@ decl_mangling_context (tree decl)
if (extra)
return extra;
}
else if (TREE_CODE (decl) == TYPE_DECL
&& TREE_CODE (TREE_TYPE (decl)) == TEMPLATE_TYPE_PARM)
/* template type parms have no mangling context. */
return NULL_TREE;
return CP_DECL_CONTEXT (decl);
}

View File

@ -4514,6 +4514,9 @@ template arguments to %qD do not match original template %qD",
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
if (TREE_CODE (parm) == TEMPLATE_DECL)
DECL_CONTEXT (parm) = tmpl;
if (TREE_CODE (TREE_TYPE (parm)) == TEMPLATE_TYPE_PARM)
DECL_CONTEXT (TYPE_NAME (TREE_TYPE (parm))) = tmpl;
}
}

View File

@ -1083,12 +1083,11 @@ void
cp_set_underlying_type (tree t)
{
set_underlying_type (t);
/* If the typedef variant type is dependent, make it require
structural equality.
This is useful when comparing two dependent typedef variant types,
/* If T is a template type parm, make it require structural equality.
This is useful when comparing two template type parms,
because it forces the comparison of the template parameters of their
decls for instance. */
if (dependent_type_p (TREE_TYPE (t)))
decls. */
if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
}

View File

@ -1073,45 +1073,96 @@ comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration)
return true;
}
/* Subroutine of structural_comptypes.
Compare the template parameters of the
typedef decl of T1 and T2.
Return TRUE if the template parameters of the typedef decls of T1 and T2 are
different, FALSE otherwise. */
/* Compare the relative position of T1 and T2 into their respective
template parameter list.
T1 and T2 must be template parameter types.
Return TRUE if T1 and T2 have the same position, FALSE otherwise. */
static bool
incompatible_dependent_typedefs_p (tree t1, tree t2)
comp_template_parms_position (tree t1, tree t2)
{
tree decl1, tinfo1,
decl2, tinfo2;
gcc_assert (t1 && t2
&& TREE_CODE (t1) == TREE_CODE (t2)
&& (TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
if (!typedef_variant_p (t1)
|| !typedef_variant_p (t2)
|| !dependent_type_p (t1)
|| !dependent_type_p (t2))
if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
|| TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
|| (TEMPLATE_TYPE_PARAMETER_PACK (t1)
!= TEMPLATE_TYPE_PARAMETER_PACK (t2)))
return false;
return true;
}
/* Subroutine of structural_comptypes.
Compare the template type parameters T1 and T2.
Return TRUE if we are sure they can't be equal, FALSE otherwise. */
static bool
incompatible_template_type_parms_p (tree t1, tree t2)
{
tree decl1, tparms1 = NULL_TREE,
decl2, tparms2 = NULL_TREE;
gcc_assert (t1 && TREE_CODE (t1) == TEMPLATE_TYPE_PARM
&& t2 && TREE_CODE (t2) == TEMPLATE_TYPE_PARM);
/* If T1 and T2 don't have the same relative position in their
template parameters set, they can't be equal. */
if (!comp_template_parms_position (t1, t2))
return true;
if (!typedef_variant_p (t1) && !typedef_variant_p (t2))
/* If neither T1 nor T2 is a typedef we cannot know more
about their incompatibility than what comp_template_parms_position
told us above. If we try to keep going nonetheless, the call to
comp_template_parms at the end of this function might lead to an
infinite recursion. */
return false;
decl1 = TYPE_NAME (t1);
decl2 = TYPE_NAME (t2);
if (decl1 == decl2)
if (decl1 == NULL_TREE || decl2 == NULL_TREE || decl1 == decl2)
return false ;
tinfo1 = get_template_info (decl1);
if (!tinfo1)
tinfo1 = get_template_info (DECL_CONTEXT (decl1));
/* So if we reach this point, it means either T1 or T2 is a typedef variant.
Let's compare their template parameters. */
tinfo2 = get_template_info (decl2);
if (!tinfo2)
tinfo2 = get_template_info (DECL_CONTEXT (decl2));
/* If T1 is not a typedef, there possibly is a delay between the
creation of DECL1 and the setting of DECL_CONTEXT (DECL1) to its
template decl so DECL_CONTEXT (DECL1) can be empty for
a little while. */
if (DECL_CONTEXT (decl1))
{
if (TREE_CODE (DECL_CONTEXT (decl1)) == TEMPLATE_DECL)
tparms1 = DECL_TEMPLATE_PARMS (DECL_CONTEXT (decl1));
else
/* T1 is a typedef variant type. Get the parms of its context. */
tparms1 =
DECL_TEMPLATE_PARMS (TI_TEMPLATE
(get_template_info (DECL_CONTEXT (decl1))));
}
gcc_assert (tinfo1 != NULL_TREE
&& tinfo2 != NULL_TREE);
/* Do the same thing for DECL2. */
if (DECL_CONTEXT (decl2))
{
if (TREE_CODE (DECL_CONTEXT (decl2)) == TEMPLATE_DECL)
tparms2 = DECL_TEMPLATE_PARMS (DECL_CONTEXT (decl2));
else
tparms2 =
DECL_TEMPLATE_PARMS (TI_TEMPLATE
(get_template_info (DECL_CONTEXT (decl2))));
}
if (tinfo1 == tinfo2)
if (tparms1 == NULL_TREE
|| tparms2 == NULL_TREE
|| tparms1 == tparms2)
return false;
return !comp_template_parms (DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo1)),
DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo2)));
/* And now compare the mighty template parms! */
return !comp_template_parms (tparms1, tparms2);
}
/* Subroutine in comptypes. */
@ -1161,9 +1212,6 @@ structural_comptypes (tree t1, tree t2, int strict)
&& TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
return true;
if (incompatible_dependent_typedefs_p (t1, t2))
return false;
/* Compare the types. Break out if they could be the same. */
switch (TREE_CODE (t1))
{
@ -1193,10 +1241,7 @@ structural_comptypes (tree t1, tree t2, int strict)
case TEMPLATE_TEMPLATE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
|| TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
|| (TEMPLATE_TYPE_PARAMETER_PACK (t1)
!= TEMPLATE_TYPE_PARAMETER_PACK (t2)))
if (!comp_template_parms_position (t1, t2))
return false;
if (!comp_template_parms
(DECL_TEMPLATE_PARMS (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t1)),
@ -1258,10 +1303,7 @@ structural_comptypes (tree t1, tree t2, int strict)
break;
case TEMPLATE_TYPE_PARM:
if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2)
|| TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2)
|| (TEMPLATE_TYPE_PARAMETER_PACK (t1)
!= TEMPLATE_TYPE_PARAMETER_PACK (t2)))
if (incompatible_template_type_parms_p (t1, t2))
return false;
break;

View File

@ -1,3 +1,8 @@
2009-12-19 Dodji Seketeli <dodji@redhat.com>
PR c++/42225
* g++.dg/template/typedef26.C: New test.
2009-12-19 Richard Guenther <rguenther@suse.de>
PR lto/42401

View File

@ -0,0 +1,40 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin: PR c++/42225
// { dg-do compile }
struct A
{
typedef int TI;
};
template<class T0>
struct S0
{
int i;
};
template<class _T, int>
struct S1
{
typedef _T T;
typedef typename T::TI TTI;
typedef S0<TTI> TT0;
typedef S0<typename T::TI> TT1;
};
template<class T>
void
foo(const T&)
{
typedef typename T::TI TTI;
typedef S0<TTI> TT1;
typedef S0<typename T::TI> TT2;
}
int
main()
{
A a;
foo (a);
}