1 // RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
2 // RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
3 
4 // p1099 'using enum ELABORATED-ENUM-SPECIFIER ;'
5 
6 namespace One {
7 namespace Bob {
8 enum A { a, // expected-note{{declared here}}
9          b,
10          c };
11 class C; // expected-note{{previous use}}
12 enum class D : int;
13 enum class D { d,
14                e,
15                f };
16 enum class D : int;
17 } // namespace Bob
18 
19 using enum Bob::A;
20 #if __cplusplus < 202002
21 // expected-warning@-2{{is a C++20 extension}}
22 #endif
23 using enum Bob::B; // expected-error{{no enum named 'B'}}
24 #if __cplusplus < 202002
25 // expected-warning@-2{{is a C++20 extension}}
26 #endif
27 using enum Bob::C; // expected-error{{tag type that does not match}}
28 #if __cplusplus < 202002
29 // expected-warning@-2{{is a C++20 extension}}
30 #endif
31 auto v = a;
32 
33 A g; // expected-error{{unknown type name 'A'}}
34 
35 int A;
36 
37 using enum Bob::D;
38 #if __cplusplus < 202002
39 // expected-warning@-2{{is a C++20 extension}}
40 #endif
41 } // namespace One
42 
43 namespace Two {
44 namespace Kevin {
45 enum class B { d,
46                e,
47                f };
48 }
49 
50 using enum Kevin::B;
51 #if __cplusplus < 202002
52 // expected-warning@-2{{is a C++20 extension}}
53 #endif
54 auto w = e;
55 
56 } // namespace Two
57 
58 #if __cplusplus >= 202002
59 // Now only check c++20 onwards
60 
61 namespace Three {
62 namespace Stuart {
63 enum class C : int; // expected-note{{declared here}}
64 }
65 
66 using enum Stuart::C; // expected-error{{is incomplete}}
67 } // namespace Three
68 
69 namespace Four {
70 class Dave {
71 public:
72   enum D { a,
73            b,
74            c };
75 
76 private:
77   enum class E { d, // expected-note{{declared private here}}
78                  e,
79                  f };
80 };
81 
82 using enum Dave::D;
83 using enum Dave::E; // expected-error{{is a private member}}
84 
85 } // namespace Four
86 
87 namespace Five {
88 enum class A { b,
89                c };
90 class Dave {
91 public:
92   using enum A;
93   A f = b;
94 };
95 
96 } // namespace Five
97 
98 namespace Six {
99 template <typename T> class TPL;
100 template <> class TPL<int> {
101 public:
102   enum A { a };
103 };
104 
105 template <typename T> class USR {
106   using enum TPL<T>::B; // expected-error{{cannot name a dependent type}}
107   using enum TPL<int>::A;
108 };
109 } // namespace Six
110 
111 // Now instantiate things
112 namespace Seven {
113 namespace Stuart {
114 enum class A { a,
115                b,
116                c };
117 }
118 
119 static_assert(!int(Stuart::A::a));
Bar()120 constexpr int Bar() {
121   using enum Stuart::A;
122   return int(b);
123 }
124 static_assert(Bar() == 1);
125 
Foo()126 template <int I> constexpr int Foo() {
127   using enum Stuart::A;
128   return int(b) + I;
129 }
130 
131 static_assert(Foo<10>() == 11);
132 
133 template <int I> struct C {
134   using enum Stuart::A;
135   static constexpr int V = int(c) + I;
136 
137   enum class D { d,
138                  e,
139                  f };
140   using enum D;
141 
142   static constexpr int W = int(f) + I;
143 };
144 
145 static_assert(C<2>::V == 4);
146 static_assert(C<20>::W == 22);
147 
148 } // namespace Seven
149 
150 namespace Eight {
151 enum class Bob : int {};
152 using enum Bob;
153 } // namespace Eight
154 
155 namespace Nine {
156 template <int I> struct C {
157   enum class D { i = I };
158   enum class E : int; // expected-note{{declared here}}
159 };
160 
161 using enum C<2>::D;
162 
163 constexpr auto d = i;
164 static_assert(unsigned(d) == 2);
165 
166 using enum C<2>::E; // expected-error{{instantiation of undefined member}}
167 } // namespace Nine
168 
169 namespace Ten {
170 enum class Bob { a };
171 
Foo()172 void Foo() {
173   extern void a();
174 }
175 
176 // We don't see the hidden extern a fn!
177 using enum Bob;
178 
179 auto v = a;
180 } // namespace Ten
181 
182 namespace Eleven {
183 enum class Bob { a }; // expected-note{{conflicting declaration}}
184 
185 struct Base {
186   enum { a }; // expected-note{{target of using}}
187 };
188 
189 template <typename B>
190 class TPLa : B {
191   using enum Bob;
192   using B::a; // expected-error{{target of using declaration}}
193 };
194 
195 TPLa<Base> a; // expected-note{{in instantiation}}
196 
197 } // namespace Eleven
198 
199 namespace Twelve {
200 enum class Bob { a }; // expected-note{{target of using}}
201 
202 struct Base {
203   enum { a };
204 };
205 
206 template <typename B>
207 class TPLb : B {
208   using B::a;     // expected-note{{conflicting declaration}}
209   using enum Bob; // expected-error{{target of using declaration}}
210 };
211 
212 TPLb<Base> b;
213 
214 } // namespace Twelve
215 
216 namespace Thirteen {
217 enum class Bob { a };
218 class Foo {
219   using enum Bob; // expected-note{{previous using-enum}}
220   using enum Bob; // expected-error{{redeclaration of using-enum}}
221 };
222 
223 template <typename B>
224 class TPLa {
225   using enum Bob; // expected-note{{previous using-enum}}
226   using enum Bob; // expected-error{{redeclaration of using-enum}}
227 };
228 
229 TPLa<int> a;
230 
231 } // namespace Thirteen
232 
233 #endif
234