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