This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PR c++/42713


On Thu, Jan 21, 2010 at 12:48:23PM -0500, Jason Merrill wrote:
> On 01/14/2010 10:43 AM, Dodji Seketeli wrote:
> >     	PR c++/42713
> >     	* typeck.c (incompatible_dependent_typedefs): New function.
> 
> Surely incompatible_template_type_parms_p should be combined with
> this function?

Indeed.

I renamed incompatible_template_type_parms_p
into incompatible_dependent_types_p and made it handle comparison
between dependent types that can be typedefs or that can contain
typedefs, e.g. TYPENAME_TYPEs which TYPE_CONTEXT can be a typedef.
This also fixes the recently filed PR c++/42820.

Tested against trunk on x86_64-unknown-linux-gnu.

        Dodji

commit f7c5785df4a0b9750a71601ea2b35bc92cc0d83f
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Thu Jan 14 16:18:48 2010 +0100

    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.

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..3f0db5e 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1096,65 +1096,78 @@ 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 decl, tparms = NULL_TREE;
+
+  decl = TYPE_NAME (t);
+  if (decl == NULL_TREE)
+    return NULL_TREE;
+
+  /* If T is not a typedef, there possibly is a delay between the
+     creation of DECL and the setting of DECL_CONTEXT (DECL) to its
+     template decl so DECL_CONTEXT (DECL) can be empty for
+     a little while.  */
+  if (DECL_CONTEXT (decl)
+      && !NAMESPACE_SCOPE_P (decl))
+    {
+      tree tinfo;
+      /* If T1 is a typedef or whatever has a template info associated
+         to its context, get the template parameters from that context.  */
+      if ((tinfo = get_template_info (DECL_CONTEXT (decl))))
+	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 (DECL_CONTEXT (decl)) == TEMPLATE_DECL)
+	tparms = DECL_TEMPLATE_PARMS (DECL_CONTEXT (decl));
+      /* If T is a TYPENAME_TYPE which context is a template type
+         parameter, get the template parameters from that context.  */
+      else if (TREE_CODE (DECL_CONTEXT (decl)) == TEMPLATE_TYPE_PARM)
+	tparms = get_template_parms_of_dependent_type (DECL_CONTEXT (decl));
+    }
+  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 +1225,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,7 +1322,7 @@ structural_comptypes (tree t1, tree t2, int strict)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      if (incompatible_template_type_parms_p (t1, t2))
+      if (incompatible_dependent_types_p (t1, t2))
 	return false;
       break;
 
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>();
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]