Commit 20c202f3 by Dodji Seketeli Committed by Dodji Seketeli

re PR c++/42713 (ICE - segfault in tsubst)

Fix PR c++/42713

gcc/cp/ChangeLog:
	PR c++/42713
	PR c++/42820
	* typeck.c (get_template_parms_of_dependent_type): Factorized
	this out of incompatible_template_type_parms_p
	(incompatible_dependent_types_p): Renamed
	incompatible_template_type_parms_p into this. Make it detect
	two incompatible dependent typedefs too.
	(structural_comptypes): Use incompatible_dependent_types_p.
	* pt.c (get_template_info):
	Handle BOUND_TEMPLATE_TEMPLATE_PARAM.

gcc/testsuite/ChangeLog:
	PR c++/42713
	PR c++/42820
	* g++.dg/template/typedef27.C: New test case.
	* g++.dg/template/typedef28.C: New test case.

From-SVN: r156316
parent b4394ebd
2010-01-28 Dodji Seketeli <dodji@redhat.com>
PR c++/42713
PR c++/42820
* typeck.c (get_template_parms_of_dependent_type): Factorized
this out of incompatible_template_type_parms_p
(incompatible_dependent_types_p): Renamed
incompatible_template_type_parms_p into this. Make it detect
two incompatible dependent typedefs too.
(structural_comptypes): Use incompatible_dependent_types_p.
* pt.c (get_template_info):
Handle BOUND_TEMPLATE_TEMPLATE_PARAM.
2010-01-20 Janis Johnson <janis187@us.ibm.com> 2010-01-20 Janis Johnson <janis187@us.ibm.com>
Jason Merrill <jason@redhat.com> Jason Merrill <jason@redhat.com>
......
...@@ -2320,6 +2320,10 @@ struct GTY(()) lang_decl { ...@@ -2320,6 +2320,10 @@ struct GTY(()) lang_decl {
#define TYPE_NAMESPACE_SCOPE_P(NODE) \ #define TYPE_NAMESPACE_SCOPE_P(NODE) \
(TREE_CODE (CP_TYPE_CONTEXT (NODE)) == NAMESPACE_DECL) (TREE_CODE (CP_TYPE_CONTEXT (NODE)) == NAMESPACE_DECL)
#define NAMESPACE_SCOPE_P(NODE) \
((DECL_P (NODE) && DECL_NAMESPACE_SCOPE_P (NODE)) \
|| (TYPE_P (NODE) && TYPE_NAMESPACE_SCOPE_P (NODE)))
/* 1 iff NODE is a class member. */ /* 1 iff NODE is a class member. */
#define DECL_CLASS_SCOPE_P(NODE) \ #define DECL_CLASS_SCOPE_P(NODE) \
(DECL_CONTEXT (NODE) && TYPE_P (DECL_CONTEXT (NODE))) (DECL_CONTEXT (NODE) && TYPE_P (DECL_CONTEXT (NODE)))
......
...@@ -317,6 +317,8 @@ get_template_info (const_tree t) ...@@ -317,6 +317,8 @@ get_template_info (const_tree t)
if (TAGGED_TYPE_P (t)) if (TAGGED_TYPE_P (t))
tinfo = TYPE_TEMPLATE_INFO (t); tinfo = TYPE_TEMPLATE_INFO (t);
else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
tinfo = TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t);
return tinfo; return tinfo;
} }
......
...@@ -1096,65 +1096,75 @@ comp_template_parms_position (tree t1, tree t2) ...@@ -1096,65 +1096,75 @@ comp_template_parms_position (tree t1, tree t2)
return true; return true;
} }
/* Subroutine of incompatible_dependent_types_p.
Return the template parameter of the dependent type T.
If T is a typedef, return the template parameters of
the _decl_ of the typedef. T must be a dependent type. */
static tree
get_template_parms_of_dependent_type (tree t)
{
tree tinfo = NULL_TREE, tparms = NULL_TREE;
/* If T1 is a typedef or whatever has a template info associated
to its context, get the template parameters from that context. */
if (typedef_variant_p (t)
&& DECL_CONTEXT (TYPE_NAME (t))
&& !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
else if (TYPE_CONTEXT (t)
&& !NAMESPACE_SCOPE_P (t))
tinfo = get_template_info (TYPE_CONTEXT (t));
if (tinfo)
tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
/* If T is a template type parameter, get the template parameter
set it is part of. */
else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
&& DECL_CONTEXT (TYPE_NAME (t)))
tparms = DECL_TEMPLATE_PARMS (DECL_CONTEXT (TYPE_NAME (t)));
/* If T is a TYPENAME_TYPE which context is a template type
parameter, get the template parameters from that context. */
else if (TYPE_CONTEXT (t)
&& TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
tparms = get_template_parms_of_dependent_type (TYPE_CONTEXT (t));
return tparms;
}
/* Subroutine of structural_comptypes. /* Subroutine of structural_comptypes.
Compare the template type parameters T1 and T2. Compare the dependent types T1 and T2.
Return TRUE if we are sure they can't be equal, FALSE otherwise. */ Return TRUE if we are sure they can't be equal, FALSE otherwise.
The whole point of this function is to support cases where either T1 or
T2 is a typedef. In those cases, we need to compare the template parameters
of the _decl_ of the typedef. If those don't match then we know T1
and T2 cannot be equal. */
static bool static bool
incompatible_template_type_parms_p (tree t1, tree t2) incompatible_dependent_types_p (tree t1, tree t2)
{ {
tree decl1, tparms1 = NULL_TREE, tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
decl2, tparms2 = NULL_TREE;
gcc_assert (t1 && TREE_CODE (t1) == TEMPLATE_TYPE_PARM if (!uses_template_parms (t1) || !uses_template_parms (t2))
&& t2 && TREE_CODE (t2) == TEMPLATE_TYPE_PARM); return false;
/* If T1 and T2 don't have the same relative position in their if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
template parameters set, they can't be equal. */ {
if (!comp_template_parms_position (t1, t2)) /* If T1 and T2 don't have the same relative position in their
return true; template parameters set, they can't be equal. */
if (!comp_template_parms_position (t1, t2))
return true;
}
/* Either T1 or T2 must be a typedef. */
if (!typedef_variant_p (t1) && !typedef_variant_p (t2)) 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; return false;
decl1 = TYPE_NAME (t1);
decl2 = TYPE_NAME (t2);
if (decl1 == NULL_TREE || decl2 == NULL_TREE || decl1 == decl2)
return false ;
/* So if we reach this point, it means either T1 or T2 is a typedef variant. /* So if we reach this point, it means either T1 or T2 is a typedef variant.
Let's compare their template parameters. */ Let's compare their template parameters. */
/* If T1 is not a typedef, there possibly is a delay between the tparms1 = get_template_parms_of_dependent_type (t1);
creation of DECL1 and the setting of DECL_CONTEXT (DECL1) to its tparms2 = get_template_parms_of_dependent_type (t2);
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))));
}
/* 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 (tparms1 == NULL_TREE if (tparms1 == NULL_TREE
|| tparms2 == NULL_TREE || tparms2 == NULL_TREE
...@@ -1212,6 +1222,12 @@ structural_comptypes (tree t1, tree t2, int strict) ...@@ -1212,6 +1222,12 @@ structural_comptypes (tree t1, tree t2, int strict)
&& TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
return true; return true;
/* If T1 and T2 are dependent typedefs then check upfront that
the template parameters of their typedef DECLs match before
going down checking their subtypes. */
if (incompatible_dependent_types_p (t1, t2))
return false;
/* Compare the types. Break out if they could be the same. */ /* Compare the types. Break out if they could be the same. */
switch (TREE_CODE (t1)) switch (TREE_CODE (t1))
{ {
...@@ -1303,8 +1319,8 @@ structural_comptypes (tree t1, tree t2, int strict) ...@@ -1303,8 +1319,8 @@ structural_comptypes (tree t1, tree t2, int strict)
break; break;
case TEMPLATE_TYPE_PARM: case TEMPLATE_TYPE_PARM:
if (incompatible_template_type_parms_p (t1, t2)) /* If incompatible_dependent_types_p called earlier didn't decide
return false; T1 and T2 were different, they might be equal. */
break; break;
case TYPENAME_TYPE: case TYPENAME_TYPE:
......
2010-01-28 Dodji Seketeli <dodji@redhat.com>
PR c++/42713
PR c++/42820
* g++.dg/template/typedef27.C: New test case.
* g++.dg/template/typedef28.C: New test case.
2010-01-27 Stephen Thomas <stephen.thomas@arm.com> 2010-01-27 Stephen Thomas <stephen.thomas@arm.com>
* testsuite/gcc.dg/optimize-bswap*.c: Add ARM target * testsuite/gcc.dg/optimize-bswap*.c: Add ARM target
......
// Origin: PR c++/42713
// { dg-do compile }
template<class T>
struct S
{
};
template<class T>
struct S0
{
typedef T TT;
};
template<class U, class V>
struct super_struct : S0<V>
{
typedef S0<V> super;
};
template<class U, class V, class W>
struct S1 : super_struct<U, V>
{
typedef super_struct<U, V> super;
typedef typename super::super Super2;
typedef typename Super2::TT Super2TT;
void
foo()
{
S<Super2TT> s1;
}
};
template<class U, class V>
struct S2 : super_struct<U, V>
{
typedef super_struct<U, V> super;
typedef typename super::super Super2;
typedef typename Super2::TT Super2TT;
void
foo()
{
S<Super2TT> s1;
}
};
int
main()
{
S1<int, S<int>, int> s1;
s1.foo();
S2<int, S<int> > s2;
s2.foo();
}
// Origin: PR c++/42820
// { dg-do compile }
template <class T> struct vector{};
struct Traits{struct Primitive{struct Id{};};};
template <class Tree, class Polyhedron> struct Tree_vs_naive
{
typedef typename Tree::Primitive Primitive;
void f() const
{
typedef vector<typename Primitive::Id> Id_vector;
}
};
template <class Tree> void test_hint_strategies()
{
vector<typename Tree::Primitive::Id> v;
}
int main(void)
{
test_hint_strategies<Traits>();
}
// Origin: PR c++/42820
// { dg-do compile }
template <class T> struct vector{};
template<class T>struct Traits{struct Primitive{struct Id{};};};
template <template<class T> class Tree, class Polyhedron> struct Tree_vs_naive
{
typedef typename Tree<int>::Primitive Primitive;
void f() const
{
typedef vector<typename Primitive::Id> Id_vector;
}
};
template <template<class T> class Tree> void test_hint_strategies()
{
vector<typename Tree<int>::Primitive::Id> v;
}
int main(void)
{
test_hint_strategies<Traits>();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment