This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix PR6440, a regression
- From: Kriang Lerdsuwanakij <lerdsuwa at users dot sourceforge dot net>
- To: <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 5 Mar 2003 20:52:43 +0700 (ICT)
- Subject: [C++ PATCH] Fix PR6440, a regression
- Reply-to: <lerdsuwa at users dot sourceforge dot net>
Hi
This patch is a revised fix for PR6440 which is a regression from 2.95
that present in 3.2, 3.3 branches and trunk. Currently GCC ICE on
the explicit specialization:
template <> template <class U> class C<int>::D;
due to problem in 'most_general_template' logic. It still thinks
'C<T>::D<U>' is the most general one rather than the
The patch fixes this ICE by applying SET_CLASSTYPE_TEMPLATE_SPECIALIZATION
to 'C<int>::D' in 'maybe_process_partial_specialization' and make
'most_general_template' terminate on this specialization. The rest
of the patch just adds some more checks to reject invalid code.
Bootstrapped and tested on i686-pc-linux-gnu. OK for 3.3 and trunk?
--Kriang
2003-03-05 Kriang Lerdsuwanakij <lerdsuwa at users dot sourceforge dot net>
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-05 Kriang Lerdsuwanakij <lerdsuwa at users dot sourceforge dot net>
PR c++/6440
* g++.dg/template/spec7.C: New test.
* g++.dg/template/spec8.C: Likewise.
diff -cprN gcc-33-save/gcc/cp/pt.c gcc-33-new/gcc/cp/pt.c
*** gcc-33-save/gcc/cp/pt.c Tue Mar 4 21:11:48 2003
--- gcc-33-new/gcc/cp/pt.c Wed Mar 5 19:09:13 2003
*************** void
*** 767,774 ****
maybe_process_partial_specialization (type)
tree type;
{
! if (IS_AGGR_TYPE (type) && CLASSTYPE_USE_TEMPLATE (type))
{
if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
&& !COMPLETE_TYPE_P (type))
{
--- 767,788 ----
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<int>;
+
+ or:
+
+ template <class T> class C<T*>;
+
+ Make sure that `C<int>' and `C<T*>' are implicit instantiations. */
+
if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
&& !COMPLETE_TYPE_P (type))
{
*************** maybe_process_partial_specialization (ty
*** 786,791 ****
--- 800,861 ----
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 U> class C<int>::D;
+
+ The context `C<int>' must be an implicit instantiation.
+ Otherwise this is just a member class template declared
+ earlier like:
+
+ template <> class C<int> { template <class U> class D; };
+ template <> template <class U> class C<int>::D;
+
+ In the first case, `C<int>::D' is a specialization of `C<T>::D'
+ while in the second case, `C<int>::D' is a primary template
+ and `C<T>::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<int>::D<int>;
+ template <> template <class U> class C<int>::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);
}
*************** most_general_template (decl)
*** 9603,9608 ****
--- 9673,9682 ----
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 -cprN gcc-33-save/gcc/testsuite/g++.dg/template/spec7.C gcc-33-new/gcc/testsuite/g++.dg/template/spec7.C
*** gcc-33-save/gcc/testsuite/g++.dg/template/spec7.C Thu Jan 1 07:00:00 1970
--- gcc-33-new/gcc/testsuite/g++.dg/template/spec7.C Wed Mar 5 19:21:46 2003
***************
*** 0 ****
--- 1,27 ----
+ // { dg-do compile }
+
+ // PR c++/6440: Specialization of member class template.
+
+ template<class T> struct A
+ {
+ template<class U> struct B {};
+ };
+
+ template<> template<class U>
+ struct A<int>::B
+ {
+ void f();
+ template <class V> void g(V);
+ };
+
+ template<> template<> template <class V> void A<int>::B<char>::g(V)
+ {
+ }
+
+ A<int>::B<char> b;
+
+ int h()
+ {
+ b.f();
+ b.g(0);
+ }
diff -cprN gcc-33-save/gcc/testsuite/g++.dg/template/spec8.C gcc-33-new/gcc/testsuite/g++.dg/template/spec8.C
*** gcc-33-save/gcc/testsuite/g++.dg/template/spec8.C Thu Jan 1 07:00:00 1970
--- gcc-33-new/gcc/testsuite/g++.dg/template/spec8.C Tue Mar 4 21:24:14 2003
***************
*** 0 ****
--- 1,11 ----
+ // { dg-do compile }
+
+ // Specialization of member class template.
+
+ template<class T1> struct A
+ {
+ template<class T2> struct B {};
+ };
+
+ template <> template <> struct A<int>::B<int> {};
+ template <> template <class U> struct A<int>::B {}; // { dg-error "specialization" }