Commit 6e049fcd by Kriang Lerdsuwanakij Committed by Kriang Lerdsuwanakij

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
parent ef529bb6
2003-03-15 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.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-13 Jason Merrill <jason@redhat.com>
PR c++/9420
......
......@@ -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<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))
{
......@@ -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 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);
}
......@@ -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)
......
2003-03-15 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/6440
* g++.dg/template/spec7.C: New test.
* g++.dg/template/spec8.C: Likewise.
2003-03-14 Jakub Jelinek <jakub@redhat.com>
* gcc.c-torture/execute/20030313-1.c: New test.
......
// { 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);
}
// { 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" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment