In this testcase we get confused by a specialization nested inside a
class template; the members of the specialization end up having
dependent template arguments, and then we get confused when we try to
define one of them in a context that has no template headers.
Fixed by rejecting the definition of the specialization, and therefore
the definition of the member of the specialization.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 9bcbafc418c3f7aff48c8e98f362e7f44849051e
Author: Jason Merrill <ja...@redhat.com>
Date: Tue Dec 11 10:59:36 2012 -0500
* pt.c (maybe_process_partial_specialization): Handle aliases first.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 1bc9e1b..f30a1e1 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -812,13 +812,17 @@ maybe_process_partial_specialization (tree type)
context = TYPE_CONTEXT (type);
- if ((CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type))
- /* Consider non-class instantiations of alias templates as
- well. */
- || (TYPE_P (type)
- && TYPE_TEMPLATE_INFO (type)
- && DECL_LANG_SPECIFIC (TYPE_NAME (type))
- && DECL_USE_TEMPLATE (TYPE_NAME (type))))
+ if (TYPE_ALIAS_P (type))
+ {
+ if (TYPE_TEMPLATE_INFO (type)
+ && DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (type)))
+ error ("specialization of alias template %qD",
+ TYPE_TI_TEMPLATE (type));
+ else
+ error ("explicit specialization of non-template %qT", type);
+ return error_mark_node;
+ }
+ else if (CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type))
{
/* This is for ordinary explicit specialization and partial
specialization of a template class such as:
@@ -831,8 +835,7 @@ maybe_process_partial_specialization (tree type)
Make sure that `C<int>' and `C<T*>' are implicit instantiations. */
- if (CLASS_TYPE_P (type)
- && CLASSTYPE_IMPLICIT_INSTANTIATION (type)
+ if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
&& !COMPLETE_TYPE_P (type))
{
check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type));
@@ -845,16 +848,9 @@ maybe_process_partial_specialization (tree type)
return error_mark_node;
}
}
- else if (CLASS_TYPE_P (type)
- && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
+ else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
error ("specialization of %qT after instantiation", type);
- if (DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (type)))
- {
- error ("partial specialization of alias template %qD",
- TYPE_TI_TEMPLATE (type));
- return error_mark_node;
- }
}
else if (CLASS_TYPE_P (type)
&& !CLASSTYPE_USE_TEMPLATE (type)
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
index d0eda5f..cbba90f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C
@@ -5,10 +5,10 @@
template<class T, class U> struct A0 {};
template<class T, class U> using AA0 = A0<T, U>;
-template<class T> struct AA0<int, T> {}; // { dg-error "partial specialization" }
+template<class T> struct AA0<int, T> {}; // { dg-error "specialization" }
template <class U> using Ptr = U*;
-template<class U> struct Ptr<U*> {}; // { dg-error "partial specialization" }
+template<class U> struct Ptr<U*> {}; // { dg-error "specialization" }
struct A {
using A = int;//{ dg-error "nested|has|same name as|class|in which|declared" }
commit e575667938e576ceeede4bdb00361d2b52540a48
Author: Jason Merrill <ja...@redhat.com>
Date: Sat Dec 8 20:16:30 2012 -0500
PR c++/54416
* pt.c (maybe_process_partial_specialization): Don't accept
definition of a specialization without the appropriate header.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f30a1e1..91450d8 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -850,7 +850,13 @@ maybe_process_partial_specialization (tree type)
}
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
error ("specialization of %qT after instantiation", type);
-
+ else if (errorcount && !processing_specialization
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (type)
+ && !uses_template_parms (CLASSTYPE_TI_ARGS (type)))
+ /* Trying to define a specialization either without a template<> header
+ or in an inappropriate place. We've already given an error, so just
+ bail now so we don't actually define the specialization. */
+ return error_mark_node;
}
else if (CLASS_TYPE_P (type)
&& !CLASSTYPE_USE_TEMPLATE (type)
diff --git a/gcc/testsuite/g++.dg/template/crash105.C b/gcc/testsuite/g++.dg/template/crash105.C
index 649bf8b..8cfff6a 100644
--- a/gcc/testsuite/g++.dg/template/crash105.C
+++ b/gcc/testsuite/g++.dg/template/crash105.C
@@ -10,5 +10,8 @@ template < typename > struct S < int >
void
f ()
{
- S < int >::f (); // { dg-error "cannot call" }
+ S < int >::f ();
}
+
+// Don't be picky about error-recovery.
+// { dg-prune-output "." }
diff --git a/gcc/testsuite/g++.dg/template/error48.C b/gcc/testsuite/g++.dg/template/error48.C
new file mode 100644
index 0000000..483f7b5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/error48.C
@@ -0,0 +1,15 @@
+// PR c++/54416
+
+template < typename T > struct foo;
+template <> struct foo < int >;
+template < typename T > struct bar
+{
+ template <> struct foo < int > // { dg-error "non-namespace scope" }
+ {
+ void baz ();
+ };
+};
+void foo < int >::baz () { }
+
+// Don't be picky about error-recovery.
+// { dg-prune-output "." }