[PATCH] PR c++/42225

Dodji Seketeli dodji@redhat.com
Tue Dec 8 15:40:00 GMT 2009


Hello,

In my previous patch I added is_typedef_variant_type, but later I realised
typedef_variant_p does the same thing. Please find below an updated patch
that just uses typedef_variant_p instead of re-doing that wheel.

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

        Dodji

commit 92dfeb36398a0e2d8272b29d82789ab1a9bf9307
Author: Dodji Seketeli <dodji@redhat.com>
Date:   Fri Dec 4 23:54:13 2009 +0100

    Fix PR c++/42225
    
    gcc/cp/ChangeLog:
    	PR c++/42225
    	* typeck.c (typedef_decl_tmpl_parms_equal_p): New function.
    	(structural_comptypes): Use it.
    	* pt.c (canonical_type_parameter, canonical_template_parms): Remove.
    	(process_template_parm, tsubst, make_auto): Adjust. TEMPLATE_TYPE_PARMs
    	now uses structural equality.
    
    gcc/testsuite/ChangeLog:
    	PR c++/42225
    	* g++.dg/template/typedef24.C: New test.
    	* g++.dg/template/typedef25.C: New test.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9fd06b3..c20b0c0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -95,12 +95,6 @@ static GTY ((param_is (spec_entry)))
 static GTY ((param_is (spec_entry)))
   htab_t type_specializations;
 
-/* Contains canonical template parameter types. The vector is indexed by
-   the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
-   TREE_LIST, whose TREE_VALUEs contain the canonical template
-   parameters of various types and levels.  */
-static GTY(()) VEC(tree,gc) *canonical_template_parms;
-
 #define UNIFY_ALLOW_NONE 0
 #define UNIFY_ALLOW_MORE_CV_QUAL 1
 #define UNIFY_ALLOW_LESS_CV_QUAL 2
@@ -3285,35 +3279,6 @@ build_template_parm_index (int index,
   return t;
 }
 
-/* Find the canonical type parameter for the given template type
-   parameter.  Returns the canonical type parameter, which may be TYPE
-   if no such parameter existed.  */
-static tree
-canonical_type_parameter (tree type)
-{
-  tree list;
-  int idx = TEMPLATE_TYPE_IDX (type);
-  if (!canonical_template_parms)
-    canonical_template_parms = VEC_alloc (tree, gc, idx+1);
-
-  while (VEC_length (tree, canonical_template_parms) <= (unsigned)idx)
-    VEC_safe_push (tree, gc, canonical_template_parms, NULL_TREE);
-
-  list = VEC_index (tree, canonical_template_parms, idx);
-  while (list && !comptypes (type, TREE_VALUE (list), COMPARE_STRUCTURAL))
-    list = TREE_CHAIN (list);
-
-  if (list)
-    return TREE_VALUE (list);
-  else
-    {
-      VEC_replace(tree, canonical_template_parms, idx,
-		  tree_cons (NULL_TREE, type, 
-			     VEC_index (tree, canonical_template_parms, idx)));
-      return type;
-    }
-}
-
 /* Return a TEMPLATE_PARM_INDEX, similar to INDEX, but whose
    TEMPLATE_PARM_LEVEL has been decreased by LEVELS.  If such a
    TEMPLATE_PARM_INDEX already exists, it is returned; otherwise, a
@@ -3473,7 +3438,7 @@ process_template_parm (tree list, location_t parm_loc, tree parm, bool is_non_ty
 				     processing_template_decl,
 				     decl, TREE_TYPE (parm));
       TEMPLATE_TYPE_PARAMETER_PACK (t) = is_parameter_pack;
-      TYPE_CANONICAL (t) = canonical_type_parameter (t);
+      SET_TYPE_STRUCTURAL_EQUALITY (t);
     }
   DECL_ARTIFICIAL (decl) = 1;
   SET_DECL_TEMPLATE_PARM_P (decl);
@@ -9924,20 +9889,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 		TYPE_MAIN_VARIANT (r) = r;
 		TYPE_POINTER_TO (r) = NULL_TREE;
 		TYPE_REFERENCE_TO (r) = NULL_TREE;
-
-		if (TREE_CODE (r) == TEMPLATE_TEMPLATE_PARM)
-		  /* We have reduced the level of the template
-		     template parameter, but not the levels of its
-		     template parameters, so canonical_type_parameter
-		     will not be able to find the canonical template
-		     template parameter for this level. Thus, we
-		     require structural equality checking to compare
-		     TEMPLATE_TEMPLATE_PARMs. */
-		  SET_TYPE_STRUCTURAL_EQUALITY (r);
-		else if (TYPE_STRUCTURAL_EQUALITY_P (t))
-		  SET_TYPE_STRUCTURAL_EQUALITY (r);
-		else
-		  TYPE_CANONICAL (r) = canonical_type_parameter (r);
+		SET_TYPE_STRUCTURAL_EQUALITY (r);
 
 		if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
 		  {
@@ -17982,7 +17934,7 @@ make_auto (void)
   TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
     (0, processing_template_decl + 1, processing_template_decl + 1,
      TYPE_NAME (au), NULL_TREE);
-  TYPE_CANONICAL (au) = canonical_type_parameter (au);
+  SET_TYPE_STRUCTURAL_EQUALITY (au);
   DECL_ARTIFICIAL (TYPE_NAME (au)) = 1;
   SET_DECL_TEMPLATE_PARM_P (TYPE_NAME (au));
 
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 307825f..290bfb4 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1073,6 +1073,42 @@ comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration)
   return true;
 }
 
+/* Subroutine of structural_comptypes.
+   T1 and T2 must be typedef variant types.
+   Compare the template parameters of the
+   typedef decl of T1 and T2. 
+   Return TRUE if the parms are equal, FALSE otherwise.  */
+
+static bool
+typedef_decl_tmpl_parms_equal_p (tree t1, tree t2)
+{
+  tree decl1, tinfo1,
+       decl2, tinfo2;
+
+  if (!t1 || !t2 || t1 == error_mark_node || t2 == error_mark_node)
+    return false;
+
+  gcc_assert (typedef_variant_p (t1)
+	      && typedef_variant_p (t2));
+
+  if (!uses_template_parms (t1) || !uses_template_parms (t2))
+    return false;
+  decl1 = TYPE_NAME (t1);
+  decl2 = TYPE_NAME (t2);
+  if (decl1 == decl2)
+    return true;
+  tinfo1 = get_template_info (decl1);
+  tinfo2 = get_template_info (decl2);
+  if (tinfo1 == tinfo2)
+    return true;
+  return (tinfo1
+	  && tinfo2
+	  && TI_TEMPLATE (tinfo1)
+	  && TI_TEMPLATE (tinfo2)
+	  && comp_template_parms (DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo1)),
+				  DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo2))));
+}
+
 /* Subroutine in comptypes.  */
 
 static bool
@@ -1120,6 +1156,18 @@ structural_comptypes (tree t1, tree t2, int strict)
       && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
     return true;
 
+  /* Assuming t1 and t2 are type dependent typedef variant types,
+     the template parameters of their decls must match.  */
+  if (/* So if t1 and t2 are typedef variant types...  */
+      typedef_variant_p (t1)
+      && typedef_variant_p (t2)
+      /* ... and if they are type dependent...  */
+      && uses_template_parms (t1)
+      && uses_template_parms (t2)
+      /* ...the template parameters of their decls must match.  */
+      && !typedef_decl_tmpl_parms_equal_p (t1, t2))
+    return false;
+
   /* Compare the types.  Break out if they could be the same.  */
   switch (TREE_CODE (t1))
     {
diff --git a/gcc/testsuite/g++.dg/template/typedef24.C b/gcc/testsuite/g++.dg/template/typedef24.C
new file mode 100644
index 0000000..ad05846
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef24.C
@@ -0,0 +1,32 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/42225
+// { dg-do compile }
+
+template<class T>
+struct A
+{
+    typedef T I;
+};
+
+template<class T, int>
+struct B
+{
+    typedef T TT;
+    typedef typename TT::I TT_I;
+    typedef A<TT_I> TA;
+};
+
+template<class T>
+void
+foo()
+{
+    typedef T TT;
+    typedef typename TT::I TT_I;
+    typedef A<TT_I> TA;
+}
+
+int
+main()
+{
+    foo<A<int> >();
+}
diff --git a/gcc/testsuite/g++.dg/template/typedef25.C b/gcc/testsuite/g++.dg/template/typedef25.C
new file mode 100644
index 0000000..098a022
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef25.C
@@ -0,0 +1,42 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/42225
+// { dg-options "-std=c++0x" }
+// { dg-do compile }
+
+template<class T>
+struct A
+{
+    typedef T I;
+    static const char *i;
+};
+
+template<class T, int>
+struct B
+{
+    typedef T TT;
+    typedef decltype(TT::i)  TT_I0;
+    typedef decltype(&TT::i) TT_I1;
+    typedef decltype(*TT::i) TT_I2;
+    typedef A<TT_I0> TA0;
+    typedef A<TT_I1> TA1;
+    typedef A<TT_I2> TA2;
+};
+
+template<class T>
+void
+foo()
+{
+    typedef T TT;
+    typedef decltype(TT::i)  TT_I0;
+    typedef decltype(&TT::i) TT_I1;
+    typedef decltype(*TT::i) TT_I2;
+    typedef A<TT_I0> TA0;
+    typedef A<TT_I1> TA1;
+    typedef A<TT_I2> TA2;
+}
+
+int
+main()
+{
+    foo<A<int> >();
+}



More information about the Gcc-patches mailing list