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:
parent
b0ce048a3f
commit
e96ce650a8
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
112
gcc/cp/typeck.c
112
gcc/cp/typeck.c
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
40
gcc/testsuite/g++.dg/template/typedef26.C
Normal file
40
gcc/testsuite/g++.dg/template/typedef26.C
Normal 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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user