diff options
author | Dodji Seketeli <dodji@redhat.com> | 2010-01-28 12:29:52 +0000 |
---|---|---|
committer | Dodji Seketeli <dodji@gcc.gnu.org> | 2010-01-28 13:29:52 +0100 |
commit | 20c202f32379dda202fb726344aeebf8904aef37 (patch) | |
tree | abd78a9e6d9ecdd9290f22ee3b6236af0f660b1a /gcc | |
parent | b4394ebd5626bb745bcb5a4710955dff058539a1 (diff) | |
download | gcc-20c202f32379dda202fb726344aeebf8904aef37.zip gcc-20c202f32379dda202fb726344aeebf8904aef37.tar.gz gcc-20c202f32379dda202fb726344aeebf8904aef37.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 4 | ||||
-rw-r--r-- | gcc/cp/pt.c | 2 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 112 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/typedef27.C | 55 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/typedef28.C | 28 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/typedef29.C | 25 |
8 files changed, 198 insertions, 48 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 43da561..a3b9755 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +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> Jason Merrill <jason@redhat.com> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 531ede1..a1bdf25 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2320,6 +2320,10 @@ struct GTY(()) lang_decl { #define TYPE_NAMESPACE_SCOPE_P(NODE) \ (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. */ #define DECL_CLASS_SCOPE_P(NODE) \ (DECL_CONTEXT (NODE) && TYPE_P (DECL_CONTEXT (NODE))) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f27b931..0bda219 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -317,6 +317,8 @@ get_template_info (const_tree t) if (TAGGED_TYPE_P (t)) tinfo = TYPE_TEMPLATE_INFO (t); + else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM) + tinfo = TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t); return tinfo; } diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index f17d9c5..36f3065 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1096,65 +1096,75 @@ comp_template_parms_position (tree t1, tree t2) 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. - Compare the template type parameters T1 and T2. - Return TRUE if we are sure they can't be equal, FALSE otherwise. */ + Compare the dependent types T1 and T2. + 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 -incompatible_template_type_parms_p (tree t1, tree t2) +incompatible_dependent_types_p (tree t1, tree t2) { - tree decl1, tparms1 = NULL_TREE, - decl2, tparms2 = NULL_TREE; + tree tparms1 = NULL_TREE, tparms2 = NULL_TREE; - gcc_assert (t1 && TREE_CODE (t1) == TEMPLATE_TYPE_PARM - && t2 && TREE_CODE (t2) == TEMPLATE_TYPE_PARM); + if (!uses_template_parms (t1) || !uses_template_parms (t2)) + return false; - /* 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 (TREE_CODE (t1) == 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; + } + /* Either T1 or T2 must be a typedef. */ 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 == 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. Let's compare their template parameters. */ - /* 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)))); - } - - /* 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)))); - } + tparms1 = get_template_parms_of_dependent_type (t1); + tparms2 = get_template_parms_of_dependent_type (t2); if (tparms1 == NULL_TREE || tparms2 == NULL_TREE @@ -1212,6 +1222,12 @@ structural_comptypes (tree t1, tree t2, int strict) && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) 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. */ switch (TREE_CODE (t1)) { @@ -1303,8 +1319,8 @@ structural_comptypes (tree t1, tree t2, int strict) break; case TEMPLATE_TYPE_PARM: - if (incompatible_template_type_parms_p (t1, t2)) - return false; + /* If incompatible_dependent_types_p called earlier didn't decide + T1 and T2 were different, they might be equal. */ break; case TYPENAME_TYPE: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 99ed3a5..8e8362c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +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> * testsuite/gcc.dg/optimize-bswap*.c: Add ARM target diff --git a/gcc/testsuite/g++.dg/template/typedef27.C b/gcc/testsuite/g++.dg/template/typedef27.C new file mode 100644 index 0000000..e50f17c --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typedef27.C @@ -0,0 +1,55 @@ +// 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(); +} + diff --git a/gcc/testsuite/g++.dg/template/typedef28.C b/gcc/testsuite/g++.dg/template/typedef28.C new file mode 100644 index 0000000..a0bad1b --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typedef28.C @@ -0,0 +1,28 @@ +// 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>(); +} + + diff --git a/gcc/testsuite/g++.dg/template/typedef29.C b/gcc/testsuite/g++.dg/template/typedef29.C new file mode 100644 index 0000000..bb3b81e --- /dev/null +++ b/gcc/testsuite/g++.dg/template/typedef29.C @@ -0,0 +1,25 @@ +// 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>(); +} |