Home | History | Annotate | Download | only in temp.mem.enum
      1 // RUN: %clang_cc1 -std=c++11 -verify %s
      2 
      3 template<typename T> struct A {
      4   enum E : T; // expected-note {{here}}
      5   E v;
      6   E f() { return A::e1; } // expected-error {{no member named 'e1' in 'A<T>'}}
      7   E g() { return E::e1; }
      8   E h();
      9 };
     10 
     11 A<int> a;
     12 A<int>::E a0 = A<int>().v;
     13 int n = A<int>::E::e1; // expected-error {{implicit instantiation of undefined member}}
     14 
     15 template<typename T> enum A<T>::E : T { e1, e2 };
     16 
     17 // FIXME: Now that A<T>::E is defined, we are supposed to inject its enumerators
     18 // into the already-instantiated class A<T>. This seems like a really bad idea,
     19 // though, so we don't implement that, but what we do implement is inconsistent.
     20 //
     21 // Either do as the standard says, or only include enumerators lexically defined
     22 // within the class in its scope.
     23 A<int>::E a1 = A<int>::e1; // expected-error {{no member named 'e1' in 'A<int>'}}
     24 
     25 A<char>::E a2 = A<char>::e2;
     26 
     27 template<typename T> typename A<T>::E A<T>::h() { return e2; }
     28 A<short>::E a3 = A<short>().h();
     29 
     30 
     31 template<typename T> struct B {
     32   enum class E;
     33   E v;
     34   E f() { return E::e1; }
     35   E g();
     36 };
     37 
     38 B<int> b;
     39 B<int>::E b0 = B<int>().v;
     40 
     41 template<typename T> enum class B<T>::E { e1, e2 };
     42 B<int>::E b1 = B<int>::E::e1;
     43 
     44 B<char>::E b2 = B<char>::E::e2;
     45 
     46 template<typename T> typename B<T>::E B<T>::g() { return e2; }
     47 B<short>::E b3 = B<short>().g();
     48 
     49 
     50 // Enumeration members of class templates can be explicitly specialized. For
     51 // unscoped enumerations, specializations must be defined before the primary
     52 // template is, since otherwise the primary template will be implicitly
     53 // instantiated when we parse the nested name specifier.
     54 template<> enum A<long long>::E : long long { e3, e4 }; // expected-error {{explicit specialization of 'E' after instantiation}} expected-note {{first required here}}
     55 
     56 template<> enum class B<long long>::E { e3, e4 };
     57 B<long long>::E b4 = B<long long>::E::e4;
     58 
     59 B<long>::E b5;
     60 template<> enum class B<long>::E { e5 };
     61 void fb5() { b5 = decltype(b5)::e5; }
     62 B<long>::E b6 = B<long>::E::e5;
     63 
     64 
     65 template<typename T> struct C {
     66   enum class E : T;
     67 };
     68 
     69 template<> enum class C<long long>::E : long long { e3, e4 };
     70 C<long long>::E c0 = C<long long>::E::e3;
     71 
     72 C<long>::E c1;
     73 template<> enum class C<long>::E : long { e5 };
     74 void fc1() { c1 = decltype(c1)::e5; }
     75 C<long>::E c2 = C<long>::E::e5;
     76 
     77 template<> enum class C<int>::E : int { e6 };
     78 template<typename T> enum class C<T>::E : T { e0 };
     79 C<int>::E c3 = C<int>::E::e6;
     80 C<int>::E c4 = C<int>::E::e0; // expected-error {{no member named 'e0' in 'C<int>::E'}}
     81 
     82 
     83 // Enumeration members can't be partially-specialized.
     84 template<typename T> enum class B<T*>::E { e5, e6 }; // expected-error {{nested name specifier for a declaration cannot depend on a template parameter}}
     85 
     86 
     87 // Explicit specializations can be forward-declared.
     88 template<typename T>
     89 struct D {
     90   enum class E { e1 };
     91 };
     92 template<> enum class D<int>::E;
     93 D<int>::E d1 = D<int>::E::e1; // expected-error {{incomplete type 'D<int>::E'}}
     94 template<> enum class D<int>::E { e2 };
     95 D<int>::E d2 = D<int>::E::e2;
     96 D<char>::E d3 = D<char>::E::e1; // expected-note {{first required here}}
     97 D<char>::E d4 = D<char>::E::e2; // expected-error {{no member named 'e2'}}
     98 template<> enum class D<char>::E { e3 }; // expected-error {{explicit specialization of 'E' after instantiation}}
     99 
    100 template<> enum class D<short>::E;
    101 struct F {
    102   // Per C++11 [class.friend]p3, these friend declarations have no effect.
    103   // Only classes and functions can be friends.
    104   template<typename T> friend enum D<T>::E;
    105   template<> friend enum D<short>::E;
    106 
    107   template<> friend enum D<double>::E { e3 }; // expected-error {{cannot define a type in a friend declaration}}
    108 
    109 private:
    110   static const int n = 1; // expected-note {{private here}}
    111 };
    112 template<> enum class D<short>::E {
    113   e = F::n // expected-error {{private member}}
    114 };
    115 
    116 class Access {
    117   friend class X;
    118 
    119   template<typename T>
    120   class Priv {
    121     friend class X;
    122 
    123     enum class E : T;
    124   };
    125 
    126   class S {
    127     typedef int N; // expected-note {{here}}
    128     static const int k = 3; // expected-note {{here}}
    129 
    130     friend class Priv<char>;
    131   };
    132 
    133   static const int k = 5;
    134 };
    135 
    136 template<> enum class Access::Priv<Access::S::N>::E
    137   : Access::S::N { // expected-error {{private member}}
    138   a = Access::k, // ok
    139   b = Access::S::k // expected-error {{private member}}
    140 };
    141 
    142 template<typename T> enum class Access::Priv<T>::E : T {
    143   c = Access::k,
    144   d = Access::S::k
    145 };
    146 
    147 class X {
    148   Access::Priv<int>::E a = Access::Priv<int>::E::a;
    149   Access::Priv<char>::E c = Access::Priv<char>::E::d;
    150   // FIXME: We should see an access error for this enumerator.
    151   Access::Priv<short>::E b = Access::Priv<short>::E::d;
    152 };
    153