diff mbox

[C++,RFC] PR c++/61491

Message ID CAFk2RUZHVfbqOBH6PDEcyyoVOP_=LSKtvgxdKKk+whQ=uXBtPQ@mail.gmail.com
State New
Headers show

Commit Message

Ville Voutilainen June 13, 2014, 6:05 p.m. UTC
On 13 June 2014 19:56, Jason Merrill <jason@redhat.com> wrote:
> This needs a test that we complain about a specialization of an unscoped
> enum.  Perhaps just the test from 14.7p6??


Well, a specialization of an unscoped enum with the proper underlying type
is fine, and that example has ones that have the wrong underlying type. Unscoped
enums with no underlying type are a different case. How about the
attached patch?

Comments

Jason Merrill June 13, 2014, 6:33 p.m. UTC | #1
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
Ville Voutilainen June 13, 2014, 6:45 p.m. UTC | #2
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?
Jason Merrill June 15, 2014, 1:37 p.m. UTC | #3
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
Ville Voutilainen June 15, 2014, 2:20 p.m. UTC | #4
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 mbox

Patch

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 {};