diff options
author | Dodji Seketeli <dodji@redhat.com> | 2009-12-19 22:40:37 +0000 |
---|---|---|
committer | Dodji Seketeli <dodji@gcc.gnu.org> | 2009-12-19 23:40:37 +0100 |
commit | e96ce650a83492661331c551dc767179eab5f8b7 (patch) | |
tree | 1dea0c05df1cc3687feff71c23514edde26e0836 | |
parent | b0ce048a3f7a78329145d0f48d63d3cabab8908b (diff) | |
download | gcc-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
-rw-r--r-- | gcc/cp/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 4 | ||||
-rw-r--r-- | gcc/cp/pt.c | 3 | ||||
-rw-r--r-- | gcc/cp/tree.c | 9 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 110 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/typedef26.C | 40 |
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); +} + |