aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorKriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>2003-03-15 10:08:31 +0000
committerKriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org>2003-03-15 10:08:31 +0000
commit6e049fcd1f2935275f6e567dc902c5929c923ce6 (patch)
tree11be24aef8d002da647d36084647c1232523e109 /gcc/cp
parentef529bb6bb315b607b8f9ef1b914098321a5c07b (diff)
downloadgcc-6e049fcd1f2935275f6e567dc902c5929c923ce6.zip
gcc-6e049fcd1f2935275f6e567dc902c5929c923ce6.tar.gz
gcc-6e049fcd1f2935275f6e567dc902c5929c923ce6.tar.bz2
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/pt.c74
2 files changed, 83 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 539ad19..4635685 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+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
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a058978..410cd8f 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<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)