aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDodji Seketeli <dodji@redhat.com>2009-12-19 22:40:37 +0000
committerDodji Seketeli <dodji@gcc.gnu.org>2009-12-19 23:40:37 +0100
commite96ce650a83492661331c551dc767179eab5f8b7 (patch)
tree1dea0c05df1cc3687feff71c23514edde26e0836 /gcc
parentb0ce048a3f7a78329145d0f48d63d3cabab8908b (diff)
downloadgcc-e96ce650a83492661331c551dc767179eab5f8b7.zip
gcc-e96ce650a83492661331c551dc767179eab5f8b7.tar.gz
gcc-e96ce650a83492661331c551dc767179eab5f8b7.tar.bz2
Fix PR c++/42225, take 2
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. From-SVN: r155363
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog18
-rw-r--r--gcc/cp/mangle.c4
-rw-r--r--gcc/cp/pt.c3
-rw-r--r--gcc/cp/tree.c9
-rw-r--r--gcc/cp/typeck.c110
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/template/typedef26.C40
7 files changed, 150 insertions, 39 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3bbc3fd..7b752cf 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 3afc094..d673c6e 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -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);
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5d98cbd..bb7c167 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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;
}
}
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 865abbc..35d53e8 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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));
}
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index e001a07..402f9e4 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0debb44..462eee1 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..7f4bc6b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef26.C
@@ -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);
+}
+