Message ID | CAFk2RUZHVfbqOBH6PDEcyyoVOP_=LSKtvgxdKKk+whQ=uXBtPQ@mail.gmail.com |
---|---|
State | New |
Headers | show |
On 06/13/2014 02:05 PM, Ville Voutilainen wrote:
> that example has ones that have the wrong underlying type.
Good point. That was fixed after the DR was incorporated into the WP,
which now says
template<class T> struct A {
enum E : T;
enum class S : T;
};
template<> enum A<int>::E : int { eint }; // OK
template<> enum class A<int>::S : int { sint }; // OK
template<class T> enum A<T>::E : T { eT };
template<class T> enum class A<T>::S : T { sT };
template<> enum A<char>::E : char { echar }; // ill-formed, A<char>::E
was instantiated
// when A<char> was instantiated
template<> enum class A<char>::S : char { schar }; // OK
Jason
On 13 June 2014 21:33, Jason Merrill <jason@redhat.com> wrote: > On 06/13/2014 02:05 PM, Ville Voutilainen wrote: >> >> that example has ones that have the wrong underlying type. > > > Good point. That was fixed after the DR was incorporated into the WP, which > now says > > > template<class T> struct A { > enum E : T; > enum class S : T; > }; > template<> enum A<int>::E : int { eint }; // OK > template<> enum class A<int>::S : int { sint }; // OK > template<class T> enum A<T>::E : T { eT }; > template<class T> enum class A<T>::S : T { sT }; > template<> enum A<char>::E : char { echar }; // ill-formed, A<char>::E was > instantiated > // when A<char> was instantiated > template<> enum class A<char>::S : char { schar }; // OK Yeah, my point was just that unscoped enums (with an explicit underlying type) as such are eligible for specialization, hence I added tests for that, and also for unscoped enums with no explicit underlying type, which cannot really be specialized since you either can't just declare the enum, or alternatively the members end up being redeclarations. So, is the last patch ok, or does it need further work?
On 06/13/2014 02:45 PM, Ville Voutilainen wrote: > Yeah, my point was just that unscoped enums (with an explicit underlying type) > as such are eligible for specialization Yes, but if there is a template definition for the enum available when the specialization is declared, the enum template is implicitly instantiated along with its containing class, so the specialization is ill-formed because you can't define a specialization that has already been instantiated. Which is what the example in the standard illustrates. Jason
On 15 June 2014 16:37, Jason Merrill <jason@redhat.com> wrote: > Yes, but if there is a template definition for the enum available when the > specialization is declared, the enum template is implicitly instantiated > along with its containing class, so the specialization is ill-formed because > you can't define a specialization that has already been instantiated. Which > is what the example in the standard illustrates. Ah, I see. So it's not just the difference in the underlying type, it's that an unscoped enum cannot be specialized to begin with, even when it has an underlying type. Ok, then the patch does need further work. I don't know how to solve that part yet, guidance would be welcome.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d267a5c..507585f 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -966,12 +966,8 @@ maybe_process_partial_specialization (tree type) } else if (processing_specialization) { - /* Someday C++0x may allow for enum template specialization. */ - if (cxx_dialect > cxx98 && TREE_CODE (type) == ENUMERAL_TYPE - && CLASS_TYPE_P (context) && CLASSTYPE_USE_TEMPLATE (context)) - pedwarn (input_location, OPT_Wpedantic, "template specialization " - "of %qD not allowed by ISO C++", type); - else + if (!(cxx_dialect > cxx98 && TREE_CODE (type) == ENUMERAL_TYPE + && CLASS_TYPE_P (context) && CLASSTYPE_USE_TEMPLATE (context))) { error ("explicit specialization of non-template %qT", type); return error_mark_node; diff --git a/gcc/testsuite/g++.dg/cpp0x/pr61491.C b/gcc/testsuite/g++.dg/cpp0x/pr61491.C new file mode 100644 index 0000000..191cfd3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr61491.C @@ -0,0 +1,50 @@ +// { dg-do compile { target c++11 } } +// { dg-options "-pedantic" } +// DR 1206 (explicit specialization of a member enumeration of a class template) + +template <class D> struct Base +{ + enum class E : D; +}; + +template<> enum class Base<int>::E : int { a, b }; + +template <class D> struct Base2 +{ + enum class E : D; // { dg-error "previous definition" } +}; + +template<> enum class Base2<int>::E : char { a, b }; // { dg-error "different underlying type" } + +template <class D> struct Base3 +{ + enum E : D; +}; + +template<> enum Base3<int>::E : int { a, b }; + +template <class D> struct Base4 +{ + enum E : D; // { dg-error "previous definition" } +}; + +template<> enum Base4<int>::E : char { a, b }; // { dg-error "different underlying type" } + +template <class D> struct Base5 +{ + enum E; // { dg-error "use of enum.*without previous declaration" } +}; + +template <class D> struct Base6 +{ + enum E {a,b}; +}; + +template<> enum Base6<int>::E {a,b}; // { dg-error "redeclaration|enumerator value" } + +template <class D> struct Base7 +{ + enum E {}; +}; + +template<> enum Base7<int>::E {};