1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
10 // UNSUPPORTED: libcpp-no-concepts
11 
12 // template<class Derived, class Base>
13 // concept derived_from;
14 
15 #include <concepts>
16 #include <type_traits>
17 
18 struct Base1 {};
19 struct Derived1 : Base1 {};
20 struct Derived2 : Base1 {};
21 
22 struct DerivedPrivate : private Base1 {};
23 struct Derived3 : DerivedPrivate {};
24 
25 struct DerivedProtected : protected DerivedPrivate {};
26 struct Derived4 : DerivedProtected {};
27 struct Derived5 : Derived4 {};
28 
29 template <typename From, typename To>
30 constexpr void CheckNotDerivedFromPointer() {
31   { // From as pointer
32     static_assert(!std::derived_from<From*, To>);
33     static_assert(!std::derived_from<From*, const To>);
34     static_assert(!std::derived_from<From*, volatile To>);
35     static_assert(!std::derived_from<From*, const volatile To>);
36 
37     if constexpr (!std::same_as<To, void>) {
38       static_assert(!std::derived_from<From*, To&>);
39       static_assert(!std::derived_from<From*, const To&>);
40       static_assert(!std::derived_from<From*, volatile To&>);
41       static_assert(!std::derived_from<From*, const volatile To&>);
42 
43       static_assert(!std::derived_from<From*, To&&>);
44       static_assert(!std::derived_from<From*, const To&&>);
45       static_assert(!std::derived_from<From*, volatile To&&>);
46       static_assert(!std::derived_from<From*, const volatile To&&>);
47 
48       static_assert(!std::derived_from<const From*, To&>);
49       static_assert(!std::derived_from<const From*, const To&>);
50       static_assert(!std::derived_from<const From*, volatile To&>);
51       static_assert(!std::derived_from<const From*, const volatile To&>);
52 
53       static_assert(!std::derived_from<const From*, To&&>);
54       static_assert(!std::derived_from<const From*, const To&&>);
55       static_assert(!std::derived_from<const From*, volatile To&&>);
56       static_assert(!std::derived_from<const From*, const volatile To&&>);
57 
58       static_assert(!std::derived_from<volatile From*, To&>);
59       static_assert(!std::derived_from<volatile From*, const To&>);
60       static_assert(!std::derived_from<volatile From*, volatile To&>);
61       static_assert(!std::derived_from<volatile From*, const volatile To&>);
62 
63       static_assert(!std::derived_from<volatile From*, To&&>);
64       static_assert(!std::derived_from<volatile From*, const To&&>);
65       static_assert(!std::derived_from<volatile From*, volatile To&&>);
66       static_assert(!std::derived_from<volatile From*, const volatile To&&>);
67 
68       static_assert(!std::derived_from<const volatile From*, To&>);
69       static_assert(!std::derived_from<const volatile From*, const To&>);
70       static_assert(!std::derived_from<const volatile From*, volatile To&>);
71       static_assert(
72           !std::derived_from<const volatile From*, const volatile To&>);
73 
74       static_assert(!std::derived_from<const volatile From*, To&&>);
75       static_assert(!std::derived_from<const volatile From*, const To&&>);
76       static_assert(!std::derived_from<const volatile From*, volatile To&&>);
77       static_assert(
78           !std::derived_from<const volatile From*, const volatile To&&>);
79     }
80   }
81   { // To as pointer
82     static_assert(!std::derived_from<From, To*>);
83     static_assert(!std::derived_from<From, const To*>);
84     static_assert(!std::derived_from<From, volatile To*>);
85     static_assert(!std::derived_from<From, const volatile To*>);
86 
87     if constexpr (!std::same_as<From, void>) {
88       static_assert(!std::derived_from<From&, To*>);
89       static_assert(!std::derived_from<From&, const To*>);
90       static_assert(!std::derived_from<From&, volatile To*>);
91       static_assert(!std::derived_from<From&, const volatile To*>);
92 
93       static_assert(!std::derived_from<From&&, To*>);
94       static_assert(!std::derived_from<From&&, const To*>);
95       static_assert(!std::derived_from<From&&, volatile To*>);
96       static_assert(!std::derived_from<From&&, const volatile To*>);
97 
98       static_assert(!std::derived_from<const From&, To*>);
99       static_assert(!std::derived_from<const From&, const To*>);
100       static_assert(!std::derived_from<const From&, volatile To*>);
101       static_assert(!std::derived_from<const From&, const volatile To*>);
102 
103       static_assert(!std::derived_from<const From&&, To*>);
104       static_assert(!std::derived_from<const From&&, const To*>);
105       static_assert(!std::derived_from<const From&&, volatile To*>);
106       static_assert(!std::derived_from<const From&&, const volatile To*>);
107 
108       static_assert(!std::derived_from<volatile From&, To*>);
109       static_assert(!std::derived_from<volatile From&, const To*>);
110       static_assert(!std::derived_from<volatile From&, volatile To*>);
111       static_assert(!std::derived_from<volatile From&, const volatile To*>);
112 
113       static_assert(!std::derived_from<volatile From&&, To*>);
114       static_assert(!std::derived_from<volatile From&&, const To*>);
115       static_assert(!std::derived_from<volatile From&&, volatile To*>);
116       static_assert(!std::derived_from<volatile From&&, const volatile To*>);
117 
118       static_assert(!std::derived_from<const volatile From&, To*>);
119       static_assert(!std::derived_from<const volatile From&, const To*>);
120       static_assert(!std::derived_from<const volatile From&, volatile To*>);
121       static_assert(
122           !std::derived_from<const volatile From&, const volatile To*>);
123 
124       static_assert(!std::derived_from<const volatile From&&, To*>);
125       static_assert(!std::derived_from<const volatile From&&, const To*>);
126       static_assert(!std::derived_from<const volatile From&&, volatile To*>);
127       static_assert(
128           !std::derived_from<const volatile From&&, const volatile To*>);
129     }
130   }
131   { // Both as pointers
132     static_assert(!std::derived_from<From*, To*>);
133     static_assert(!std::derived_from<From*, const To*>);
134     static_assert(!std::derived_from<From*, volatile To*>);
135     static_assert(!std::derived_from<From*, const volatile To*>);
136 
137     static_assert(!std::derived_from<const From*, To*>);
138     static_assert(!std::derived_from<const From*, const To*>);
139     static_assert(!std::derived_from<const From*, volatile To*>);
140     static_assert(!std::derived_from<const From*, const volatile To*>);
141 
142     static_assert(!std::derived_from<volatile From*, To*>);
143     static_assert(!std::derived_from<volatile From*, const To*>);
144     static_assert(!std::derived_from<volatile From*, volatile To*>);
145     static_assert(!std::derived_from<volatile From*, const volatile To*>);
146 
147     static_assert(!std::derived_from<const volatile From*, To*>);
148     static_assert(!std::derived_from<const volatile From*, const To*>);
149     static_assert(!std::derived_from<const volatile From*, volatile To*>);
150     static_assert(!std::derived_from<const volatile From*, const volatile To*>);
151   }
152 
153   // From as the return type of a pointer-to-function
154   if constexpr (!std::is_array_v<From>) {
155     static_assert(!std::derived_from<From (*)(), To>);
156     static_assert(!std::derived_from<From (*)(int), To>);
157   }
158 
159   // To as the return type of a pointer-to-function
160   if constexpr (!std::is_array_v<To>) {
161     static_assert(!std::derived_from<From, To (*)()>);
162     static_assert(!std::derived_from<From, To (*)(double)>);
163   }
164 
165   // Both as the return type of a pointer-to-function
166   if constexpr (!std::is_array_v<From> && !std::is_array_v<To>) {
167     static_assert(!std::derived_from<From (*)(), To (*)()>);
168     static_assert(!std::derived_from<From (*)(int), To (*)(double)>);
169   }
170   { // pointer-to-member
171     if constexpr (std::is_class_v<From> && !std::same_as<To, void>) {
172       static_assert(!std::derived_from<To From::*, To>);
173     }
174 
175     if constexpr (std::is_class_v<To> && !std::same_as<From, void>) {
176       static_assert(!std::derived_from<From To::*, From>);
177     }
178   }
179   { // pointer-to-member-functions
180     if constexpr (std::is_class_v<From>) {
181       static_assert(!std::derived_from<From (From::*)(), To>);
182     }
183 
184     if constexpr (std::is_class_v<To>) {
185       static_assert(!std::derived_from<To (To::*)(), From>);
186     }
187   }
188 }
189 
190 template <typename From, typename To>
191 constexpr void CheckNotDerivedFromReference() {
192   if constexpr (!std::same_as<To, void>) {
193     static_assert(!std::derived_from<From, To&>);
194     static_assert(!std::derived_from<From, const To&>);
195     static_assert(!std::derived_from<From, volatile To&>);
196     static_assert(!std::derived_from<From, const volatile To&>);
197 
198     static_assert(!std::derived_from<From, To&&>);
199     static_assert(!std::derived_from<From, const To&&>);
200     static_assert(!std::derived_from<From, volatile To&&>);
201     static_assert(!std::derived_from<From, const volatile To&&>);
202   }
203 
204   if constexpr (!std::same_as<From, void>) {
205     static_assert(!std::derived_from<From&, To>);
206     static_assert(!std::derived_from<From&, To>);
207     static_assert(!std::derived_from<From&, To>);
208     static_assert(!std::derived_from<From&, To>);
209 
210     static_assert(!std::derived_from<From&&, To>);
211     static_assert(!std::derived_from<From&&, To>);
212     static_assert(!std::derived_from<From&&, To>);
213     static_assert(!std::derived_from<From&&, To>);
214   }
215 
216   // From as lvalue references
217   if constexpr (!std::same_as<From, void> && !std::same_as<To, void>) {
218     static_assert(!std::derived_from<From&, To&>);
219     static_assert(!std::derived_from<From&, const To&>);
220     static_assert(!std::derived_from<From&, volatile To&>);
221     static_assert(!std::derived_from<From&, const volatile To&>);
222 
223     static_assert(!std::derived_from<From&, To&&>);
224     static_assert(!std::derived_from<From&, const To&&>);
225     static_assert(!std::derived_from<From&, volatile To&&>);
226     static_assert(!std::derived_from<From&, const volatile To&&>);
227 
228     static_assert(!std::derived_from<const From&, To&>);
229     static_assert(!std::derived_from<const From&, const To&>);
230     static_assert(!std::derived_from<const From&, volatile To&>);
231     static_assert(!std::derived_from<const From&, const volatile To&>);
232 
233     static_assert(!std::derived_from<const From&, To&&>);
234     static_assert(!std::derived_from<const From&, const To&&>);
235     static_assert(!std::derived_from<const From&, volatile To&&>);
236     static_assert(!std::derived_from<const From&, const volatile To&&>);
237 
238     static_assert(!std::derived_from<volatile From&, To&>);
239     static_assert(!std::derived_from<volatile From&, const To&>);
240     static_assert(!std::derived_from<volatile From&, volatile To&>);
241     static_assert(!std::derived_from<volatile From&, const volatile To&>);
242 
243     static_assert(!std::derived_from<volatile From&, To&&>);
244     static_assert(!std::derived_from<volatile From&, const To&&>);
245     static_assert(!std::derived_from<volatile From&, volatile To&&>);
246     static_assert(!std::derived_from<volatile From&, const volatile To&&>);
247 
248     static_assert(!std::derived_from<const volatile From&, To&>);
249     static_assert(!std::derived_from<const volatile From&, const To&>);
250     static_assert(!std::derived_from<const volatile From&, volatile To&>);
251     static_assert(!std::derived_from<const volatile From&, const volatile To&>);
252 
253     static_assert(!std::derived_from<const volatile From&, To&&>);
254     static_assert(!std::derived_from<const volatile From&, const To&&>);
255     static_assert(!std::derived_from<const volatile From&, volatile To&&>);
256     static_assert(
257         !std::derived_from<const volatile From&, const volatile To&&>);
258 
259     // From as rvalue references
260     static_assert(!std::derived_from<From&&, To&>);
261     static_assert(!std::derived_from<From&&, const To&>);
262     static_assert(!std::derived_from<From&&, volatile To&>);
263     static_assert(!std::derived_from<From&&, const volatile To&>);
264 
265     static_assert(!std::derived_from<From&&, To&&>);
266     static_assert(!std::derived_from<From&&, const To&&>);
267     static_assert(!std::derived_from<From&&, volatile To&&>);
268     static_assert(!std::derived_from<From&&, const volatile To&&>);
269 
270     static_assert(!std::derived_from<const From&&, To&>);
271     static_assert(!std::derived_from<const From&&, const To&>);
272     static_assert(!std::derived_from<const From&&, volatile To&>);
273     static_assert(!std::derived_from<const From&&, const volatile To&>);
274 
275     static_assert(!std::derived_from<const From&&, To&&>);
276     static_assert(!std::derived_from<const From&&, const To&&>);
277     static_assert(!std::derived_from<const From&&, volatile To&&>);
278     static_assert(!std::derived_from<const From&&, const volatile To&&>);
279 
280     static_assert(!std::derived_from<volatile From&&, To&>);
281     static_assert(!std::derived_from<volatile From&&, const To&>);
282     static_assert(!std::derived_from<volatile From&&, volatile To&>);
283     static_assert(!std::derived_from<volatile From&&, const volatile To&>);
284 
285     static_assert(!std::derived_from<volatile From&&, To&&>);
286     static_assert(!std::derived_from<volatile From&&, const To&&>);
287     static_assert(!std::derived_from<volatile From&&, volatile To&&>);
288     static_assert(!std::derived_from<volatile From&&, const volatile To&&>);
289 
290     static_assert(!std::derived_from<const volatile From&&, To&>);
291     static_assert(!std::derived_from<const volatile From&&, const To&>);
292     static_assert(!std::derived_from<const volatile From&&, volatile To&>);
293     static_assert(
294         !std::derived_from<const volatile From&&, const volatile To&>);
295 
296     static_assert(!std::derived_from<const volatile From&&, To&&>);
297     static_assert(!std::derived_from<const volatile From&&, const To&&>);
298     static_assert(!std::derived_from<const volatile From&&, volatile To&&>);
299     static_assert(
300         !std::derived_from<const volatile From&&, const volatile To&&>);
301   }
302 
303   // From as the return type of a reference-to-function
304   if constexpr (!std::is_array_v<From>) {
305     static_assert(!std::derived_from<From (&)(), To>);
306     static_assert(!std::derived_from<From (&)(int), To>);
307   }
308   // To as the return type of a reference-to-function
309   if constexpr (!std::is_array_v<To>) {
310     static_assert(!std::derived_from<From, To (&)()>);
311     static_assert(!std::derived_from<From, To (&)(double)>);
312   }
313   // Both as the return type of a reference-to-function
314   if constexpr (!std::is_array_v<From> && !std::is_array_v<To>) {
315     static_assert(!std::derived_from<From (&)(), To (&)()>);
316     static_assert(!std::derived_from<From (&)(int), To (&)(double)>);
317   }
318 }
319 
320 template <typename From, typename To>
321 constexpr void CheckDerivedFrom() {
322   static_assert(std::derived_from<From, To>);
323 
324   static_assert(std::derived_from<From, const To>);
325   static_assert(std::derived_from<From, volatile To>);
326   static_assert(std::derived_from<From, const volatile To>);
327 
328   static_assert(std::derived_from<const From, const To>);
329   static_assert(std::derived_from<const From, volatile To>);
330   static_assert(std::derived_from<const From, const volatile To>);
331 
332   static_assert(std::derived_from<volatile From, const To>);
333   static_assert(std::derived_from<volatile From, volatile To>);
334   static_assert(std::derived_from<volatile From, const volatile To>);
335 
336   static_assert(std::derived_from<const volatile From, const To>);
337   static_assert(std::derived_from<const volatile From, volatile To>);
338   static_assert(std::derived_from<const volatile From, const volatile To>);
339 
340   CheckNotDerivedFromPointer<From, To>();
341   CheckNotDerivedFromReference<From, To>();
342 }
343 
344 template <typename From, typename To>
345 constexpr void CheckNotDerivedFrom() {
346   static_assert(!std::derived_from<From, To>);
347 
348   static_assert(!std::derived_from<From, const To>);
349   static_assert(!std::derived_from<From, volatile To>);
350   static_assert(!std::derived_from<From, const volatile To>);
351 
352   static_assert(!std::derived_from<const From, const To>);
353   static_assert(!std::derived_from<const From, volatile To>);
354   static_assert(!std::derived_from<const From, const volatile To>);
355 
356   static_assert(!std::derived_from<volatile From, const To>);
357   static_assert(!std::derived_from<volatile From, volatile To>);
358   static_assert(!std::derived_from<volatile From, const volatile To>);
359 
360   static_assert(!std::derived_from<const volatile From, const To>);
361   static_assert(!std::derived_from<const volatile From, volatile To>);
362   static_assert(!std::derived_from<const volatile From, const volatile To>);
363 
364   CheckNotDerivedFromPointer<From, To>();
365   CheckNotDerivedFromReference<From, To>();
366 }
367 
368 enum Enumeration { Yes, No };
369 enum class ScopedEnumeration : int { No, Yes };
370 
371 int main(int, char**) {
372   { // Fundamentals shouldn't be derived from anything
373     CheckNotDerivedFrom<int, long>();
374     CheckNotDerivedFrom<signed char, char>();
375     CheckNotDerivedFrom<double, Base1>();
376 
377     CheckNotDerivedFrom<int, Enumeration>();
378     CheckNotDerivedFrom<int, ScopedEnumeration>();
379 
380     CheckNotDerivedFrom<void, void>();
381     CheckNotDerivedFrom<int, int>();
382   }
383   { // Nothing should be derived from a fundamental type
384     CheckNotDerivedFrom<Enumeration, int>();
385     CheckNotDerivedFrom<ScopedEnumeration, int>();
386 
387     CheckNotDerivedFrom<Base1, int>();
388     CheckNotDerivedFrom<Base1, double>();
389     CheckNotDerivedFrom<Derived1, char>();
390     CheckNotDerivedFrom<DerivedPrivate, long long>();
391   }
392   { // Other built-in things shouldn't have derivations
393     CheckNotDerivedFrom<Enumeration, Enumeration>();
394     CheckNotDerivedFrom<ScopedEnumeration, ScopedEnumeration>();
395 
396     CheckNotDerivedFrom<Enumeration, ScopedEnumeration>();
397     CheckNotDerivedFrom<ScopedEnumeration, Enumeration>();
398 
399     CheckNotDerivedFrom<Base1[5], Base1>();
400     CheckNotDerivedFrom<Derived1[5], Base1>();
401 
402     CheckNotDerivedFrom<Base1, Base1[5]>();
403     CheckNotDerivedFrom<Derived1, Base1[5]>();
404   }
405 
406   { // Base1 is the subject.
407     CheckDerivedFrom<Base1, Base1>();
408 
409     CheckNotDerivedFrom<Base1, void>();
410     CheckNotDerivedFrom<Base1, DerivedPrivate>();
411     CheckNotDerivedFrom<Base1, DerivedProtected>();
412     CheckNotDerivedFrom<Base1, Derived1>();
413     CheckNotDerivedFrom<Base1, Derived2>();
414     CheckNotDerivedFrom<Base1, Derived3>();
415     CheckNotDerivedFrom<Base1, Derived4>();
416   }
417 
418   { // Derived1 is the subject.
419     CheckDerivedFrom<Derived1, Base1>();
420     CheckDerivedFrom<Derived1, Derived1>();
421 
422     CheckNotDerivedFromPointer<Derived1, void>();
423     CheckNotDerivedFrom<Derived1, DerivedPrivate>();
424     CheckNotDerivedFrom<Derived1, DerivedProtected>();
425     CheckNotDerivedFrom<Derived1, Derived2>();
426     CheckNotDerivedFrom<Derived1, Derived3>();
427     CheckNotDerivedFrom<Derived1, Derived4>();
428   }
429 
430   { // Derived2 is the subject.
431     CheckDerivedFrom<Derived2, Base1>();
432     CheckDerivedFrom<Derived2, Derived2>();
433 
434     CheckNotDerivedFrom<Derived2, DerivedPrivate>();
435     CheckNotDerivedFrom<Derived2, DerivedProtected>();
436     CheckNotDerivedFrom<Derived2, Derived1>();
437     CheckNotDerivedFrom<Derived2, Derived3>();
438     CheckNotDerivedFrom<Derived2, Derived4>();
439   }
440 
441   { // DerivedPrivate is the subject.
442     CheckDerivedFrom<DerivedPrivate, DerivedPrivate>();
443 
444     CheckNotDerivedFrom<DerivedPrivate, Base1>();
445     CheckNotDerivedFrom<DerivedPrivate, DerivedProtected>();
446     CheckNotDerivedFrom<DerivedPrivate, Derived1>();
447     CheckNotDerivedFrom<DerivedPrivate, Derived2>();
448     CheckNotDerivedFrom<DerivedPrivate, Derived3>();
449     CheckNotDerivedFrom<DerivedPrivate, Derived4>();
450   }
451 
452   { // Derived3 is the subject.
453     CheckDerivedFrom<Derived3, DerivedPrivate>();
454     CheckDerivedFrom<Derived3, Derived3>();
455 
456     CheckNotDerivedFrom<Derived3, Base1>();
457     CheckNotDerivedFrom<Derived3, DerivedProtected>();
458     CheckNotDerivedFrom<Derived3, Derived1>();
459     CheckNotDerivedFrom<Derived3, Derived2>();
460     CheckNotDerivedFrom<Derived3, Derived4>();
461   }
462 
463   { // DerivedProtected is the subject.
464     CheckDerivedFrom<DerivedProtected, DerivedProtected>();
465 
466     CheckNotDerivedFromPointer<DerivedProtected, Base1>();
467     CheckNotDerivedFromPointer<DerivedProtected, DerivedPrivate>();
468     CheckNotDerivedFromPointer<DerivedProtected, Derived1>();
469     CheckNotDerivedFromPointer<DerivedProtected, Derived2>();
470     CheckNotDerivedFromPointer<DerivedProtected, Derived3>();
471     CheckNotDerivedFromPointer<DerivedProtected, Derived4>();
472   }
473 
474   { // Derived4 is the subject.
475     CheckDerivedFrom<Derived4, DerivedProtected>();
476     CheckDerivedFrom<Derived4, Derived4>();
477 
478     CheckNotDerivedFrom<Derived4, Base1>();
479     CheckNotDerivedFrom<Derived4, DerivedPrivate>();
480     CheckNotDerivedFrom<Derived4, Derived1>();
481     CheckNotDerivedFrom<Derived4, Derived2>();
482     CheckNotDerivedFrom<Derived4, Derived3>();
483   }
484 
485   { // Derived5 is the subject.
486     CheckDerivedFrom<Derived5, DerivedProtected>();
487     CheckDerivedFrom<Derived5, Derived4>();
488     CheckDerivedFrom<Derived5, Derived5>();
489 
490     CheckNotDerivedFrom<Derived5, Base1>();
491     CheckNotDerivedFrom<Derived5, DerivedPrivate>();
492     CheckNotDerivedFrom<Derived5, Derived1>();
493     CheckNotDerivedFrom<Derived5, Derived2>();
494     CheckNotDerivedFrom<Derived5, Derived3>();
495   }
496 
497   return 0;
498 }
499