From: Kriang Lerdsuwanakij Date: Sun, 16 Mar 2003 14:28:43 +0000 (+0000) Subject: re PR c++/6440 (template specializations cause ICE) X-Git-Tag: releases/gcc-3.2.3~108 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9eaa910b265291b1fa82720941d84c2d86a94542;p=thirdparty%2Fgcc.git re PR c++/6440 (template specializations cause ICE) PR c++/6440 * pt.c (maybe_process_partial_specialization): Handle member class template when enclosing class template is explicit specialized. (most_general_template): Stop looking when DECL is already specialized. * g++.dg/template/spec7.C: New test. * g++.dg/template/spec8.C: Likewise. From-SVN: r64437 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d306a402074a..6487a59218c6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2003-03-16 Kriang Lerdsuwanakij + + PR c++/6440 + * pt.c (maybe_process_partial_specialization): Handle + member class template when enclosing class template is + explicit specialized. + (most_general_template): Stop looking when DECL is already + specialized. + 2003-03-13 Jason Merrill PR c++/9420 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b751ad49e74e..a2fed22b7745 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -695,8 +695,22 @@ void maybe_process_partial_specialization (type) tree type; { - if (IS_AGGR_TYPE (type) && CLASSTYPE_USE_TEMPLATE (type)) + /* TYPE maybe an ERROR_MARK_NODE. */ + tree context = TYPE_P (type) ? TYPE_CONTEXT (type) : NULL_TREE; + + if (CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type)) { + /* This is for ordinary explicit specialization and partial + specialization of a template class such as: + + template <> class C; + + or: + + template class C; + + Make sure that `C' and `C' are implicit instantiations. */ + if (CLASSTYPE_IMPLICIT_INSTANTIATION (type) && !COMPLETE_TYPE_P (type)) { @@ -714,6 +728,62 @@ maybe_process_partial_specialization (type) else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type)) error ("specialization of `%T' after instantiation", type); } + else if (CLASS_TYPE_P (type) + && !CLASSTYPE_USE_TEMPLATE (type) + && CLASSTYPE_TEMPLATE_INFO (type) + && context && CLASS_TYPE_P (context) + && CLASSTYPE_TEMPLATE_INFO (context)) + { + /* This is for an explicit specialization of member class + template according to [temp.expl.spec/18]: + + template <> template class C::D; + + The context `C' must be an implicit instantiation. + Otherwise this is just a member class template declared + earlier like: + + template <> class C { template class D; }; + template <> template class C::D; + + In the first case, `C::D' is a specialization of `C::D' + while in the second case, `C::D' is a primary template + and `C::D' may not exist. */ + + if (CLASSTYPE_IMPLICIT_INSTANTIATION (context) + && !COMPLETE_TYPE_P (type)) + { + tree t; + + if (current_namespace + != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type))) + { + pedwarn ("specializing `%#T' in different namespace", type); + cp_pedwarn_at (" from definition of `%#D'", + CLASSTYPE_TI_TEMPLATE (type)); + } + + /* Check for invalid specialization after instantiation: + + template <> template <> class C::D; + template <> template class C::D; */ + + for (t = DECL_TEMPLATE_INSTANTIATIONS + (most_general_template (CLASSTYPE_TI_TEMPLATE (type))); + t; t = TREE_CHAIN (t)) + if (TREE_VALUE (t) != type + && TYPE_CONTEXT (TREE_VALUE (t)) == context) + error ("specialization `%T' after instantiation `%T'", + type, TREE_VALUE (t)); + + /* Mark TYPE as a specialization. And as a result, we only + have one level of template argument for the innermost + class template. */ + SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type); + CLASSTYPE_TI_ARGS (type) + = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type)); + } + } else if (processing_specialization) error ("explicit specialization of non-template `%T'", type); } @@ -9434,6 +9504,10 @@ most_general_template (decl) if (TREE_CODE (DECL_TI_TEMPLATE (decl)) != TEMPLATE_DECL) break; + if (CLASS_TYPE_P (TREE_TYPE (decl)) + && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl))) + break; + /* Stop if we run into an explicitly specialized class template. */ if (!DECL_NAMESPACE_SCOPE_P (decl) && DECL_CONTEXT (decl) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f2054c9f46eb..4c04d99b42cc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2003-03-16 Kriang Lerdsuwanakij + + PR c++/6440 + * g++.dg/template/spec7.C: New test. + * g++.dg/template/spec8.C: Likewise. + 2003-03-14 Eric Botcazou * gcc.c-torture/compile/20030314-1.c: New test.