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