• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
fA6   E f() { return A::e1; } // expected-error {{no member named 'e1' in 'A<T>'}}
gA7   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 }; // expected-note 2 {{declared here}}
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>'; did you mean simply 'e1'?}}
24 
25 A<char>::E a2 = A<char>::e2;
26 
h()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;
fB34   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 
g()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 };
fb5()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 };
fc1()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' in 'D<char>::E'; did you mean simply '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