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