From 6e049fcd1f2935275f6e567dc902c5929c923ce6 Mon Sep 17 00:00:00 2001 From: Kriang Lerdsuwanakij Date: Sat, 15 Mar 2003 10:08:31 +0000 Subject: [PATCH] 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: r64395 --- gcc/cp/ChangeLog | 9 ++++ gcc/cp/pt.c | 74 +++++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/g++.dg/template/spec7.C | 27 ++++++++++ gcc/testsuite/g++.dg/template/spec8.C | 11 ++++ 5 files changed, 127 insertions(+) create mode 100644 gcc/testsuite/g++.dg/template/spec7.C create mode 100644 gcc/testsuite/g++.dg/template/spec8.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 539ad19f999..46356856b0e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2003-03-15 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 a0589781010..410cd8fe025 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -776,8 +776,22 @@ void maybe_process_partial_specialization (type) tree 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)) { @@ -795,6 +809,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); } @@ -10124,6 +10194,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 75049056c02..f3222e6844d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2003-03-15 Kriang Lerdsuwanakij + + PR c++/6440 + * g++.dg/template/spec7.C: New test. + * g++.dg/template/spec8.C: Likewise. + 2003-03-14 Jakub Jelinek * gcc.c-torture/execute/20030313-1.c: New test. diff --git a/gcc/testsuite/g++.dg/template/spec7.C b/gcc/testsuite/g++.dg/template/spec7.C new file mode 100644 index 00000000000..18d3c90c45e --- /dev/null +++ b/gcc/testsuite/g++.dg/template/spec7.C @@ -0,0 +1,27 @@ +// { dg-do compile } + +// PR c++/6440: Specialization of member class template. + +template struct A +{ + template struct B {}; +}; + +template<> template +struct A::B +{ + void f(); + template void g(V); +}; + +template<> template<> template void A::B::g(V) +{ +} + +A::B b; + +int h() +{ + b.f(); + b.g(0); +} diff --git a/gcc/testsuite/g++.dg/template/spec8.C b/gcc/testsuite/g++.dg/template/spec8.C new file mode 100644 index 00000000000..26d207b8131 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/spec8.C @@ -0,0 +1,11 @@ +// { dg-do compile } + +// Specialization of member class template. + +template struct A +{ + template struct B {}; +}; + +template <> template <> struct A::B {}; +template <> template struct A::B {}; // { dg-error "specialization" } -- 2.30.2