OSDN Git Service

Fix PR c++/42225, take 2
authordodji <dodji@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 19 Dec 2009 22:40:37 +0000 (22:40 +0000)
committerdodji <dodji@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 19 Dec 2009 22:40:37 +0000 (22:40 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@155363 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/mangle.c
gcc/cp/pt.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/typedef26.C [new file with mode: 0644]

index 3bbc3fd..7b752cf 100644 (file)
@@ -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
index 3afc094..d673c6e 100644 (file)
@@ -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);
 }
 
index 5d98cbd..bb7c167 100644 (file)
@@ -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;
        }
     }
 
index 865abbc..35d53e8 100644 (file)
@@ -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));
 }
 
index e001a07..402f9e4 100644 (file)
@@ -1073,45 +1073,96 @@ comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration)
   return true;
 }
 
+/* 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
+comp_template_parms_position (tree t1, tree t2)
+{
+  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 (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 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 template type parameters T1 and T2.
+   Return TRUE if we are sure they can't be equal, FALSE otherwise.  */
 
 static bool
-incompatible_dependent_typedefs_p (tree t1, tree t2)
+incompatible_template_type_parms_p (tree t1, tree t2)
 {
-  tree decl1, tinfo1,
-       decl2, tinfo2;
+  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)
-      || !dependent_type_p (t1)
-      || !dependent_type_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;
 
   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;
 
index 0debb44..462eee1 100644 (file)
@@ -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
diff --git a/gcc/testsuite/g++.dg/template/typedef26.C b/gcc/testsuite/g++.dg/template/typedef26.C
new file mode 100644 (file)
index 0000000..7f4bc6b
--- /dev/null
@@ -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);
+}
+