aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog13
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/pt.c2
-rw-r--r--gcc/cp/typeck.c112
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/template/typedef27.C55
-rw-r--r--gcc/testsuite/g++.dg/template/typedef28.C28
-rw-r--r--gcc/testsuite/g++.dg/template/typedef29.C25
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>();
+}