This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] PR c++/42225
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> >();
+}