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 }; // 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 | |
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' 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> enum D<T>::E; |
105 | template<> enum D<short>::E; |
106 | |
107 | template<> 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 | |