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, c++20, c++23
10
11// These compilers don't support __builtin_is_virtual_base_of yet.
12// UNSUPPORTED: clang-18, clang-19, gcc-14, apple-clang-16, apple-clang-17
13
14// <type_traits>
15
16// std::is_virtual_base_of
17
18#include <type_traits>
19#include <cassert>
20
21#include "test_macros.h"
22
23template <bool expected, class Base, class Derived>
24void test() {
25 // Test the type of the variables
26 {
27 static_assert(std::is_same_v<bool const, decltype(std::is_virtual_base_of<Base, Derived>::value)>);
28 static_assert(std::is_same_v<bool const, decltype(std::is_virtual_base_of_v<Base, Derived>)>);
29 }
30
31 // Test their value
32 {
33 static_assert(std::is_virtual_base_of<Base, Derived>::value == expected);
34 static_assert(std::is_virtual_base_of<const Base, Derived>::value == expected);
35 static_assert(std::is_virtual_base_of<Base, const Derived>::value == expected);
36 static_assert(std::is_virtual_base_of<const Base, const Derived>::value == expected);
37
38 static_assert(std::is_virtual_base_of_v<Base, Derived> == expected);
39 static_assert(std::is_virtual_base_of_v<const Base, Derived> == expected);
40 static_assert(std::is_virtual_base_of_v<Base, const Derived> == expected);
41 static_assert(std::is_virtual_base_of_v<const Base, const Derived> == expected);
42 }
43
44 // Check the relationship with is_base_of. If it's not a base of, it can't be a virtual base of.
45 { static_assert(!std::is_base_of_v<Base, Derived> ? !std::is_virtual_base_of_v<Base, Derived> : true); }
46
47 // Make sure they can be referenced at runtime
48 {
49 bool const& a = std::is_virtual_base_of<Base, Derived>::value;
50 bool const& b = std::is_virtual_base_of_v<Base, Derived>;
51 assert(a == expected);
52 assert(b == expected);
53 }
54}
55
56struct Incomplete;
57struct Unrelated {};
58union IncompleteUnion;
59union Union {
60 int i;
61 float f;
62};
63
64class Base {};
65class Derived : Base {};
66class Derived2 : Base {};
67class Derived2a : Derived {};
68class Derived2b : Derived {};
69class Derived3Virtual : virtual Derived2a, virtual Derived2b {};
70
71struct DerivedTransitiveViaNonVirtual : Derived3Virtual {};
72struct DerivedTransitiveViaVirtual : virtual Derived3Virtual {};
73
74template <typename T>
75struct CrazyDerived : T {};
76template <typename T>
77struct CrazyDerivedVirtual : virtual T {};
78
79struct DerivedPrivate : private virtual Base {};
80struct DerivedProtected : protected virtual Base {};
81struct DerivedPrivatePrivate : private DerivedPrivate {};
82struct DerivedPrivateProtected : private DerivedProtected {};
83struct DerivedProtectedPrivate : protected DerivedProtected {};
84struct DerivedProtectedProtected : protected DerivedProtected {};
85struct DerivedTransitivePrivate : private Derived, private Derived2 {};
86
87int main(int, char**) {
88 // Test with non-virtual inheritance
89 {
90 test<false, Base, Base>();
91 test<false, Base, Derived>();
92 test<false, Base, Derived2>();
93 test<false, Derived, DerivedTransitivePrivate>();
94 test<false, Derived, Base>();
95 test<false, Incomplete, Derived>();
96
97 // Derived must be a complete type if Base and Derived are non-union class types
98 // test<false, Base, Incomplete>();
99 }
100
101 // Test with virtual inheritance
102 {
103#ifdef TEST_COMPILER_GCC // FIXME: Is this a GCC or Clang bug? Or is the standards wording ambiguous?
104 test<true, Base, Derived3Virtual>();
105 test<true, Derived, Derived3Virtual>();
106#else
107 test<false, Base, Derived3Virtual>();
108 test<false, Derived, Derived3Virtual>();
109#endif
110 test<true, Derived2b, Derived3Virtual>();
111 test<true, Derived2a, Derived3Virtual>();
112 test<true, Base, DerivedPrivate>();
113 test<true, Base, DerivedProtected>();
114 test<true, Base, DerivedPrivatePrivate>();
115 test<true, Base, DerivedPrivateProtected>();
116 test<true, Base, DerivedProtectedPrivate>();
117 test<true, Base, DerivedProtectedProtected>();
118 test<true, Derived2a, DerivedTransitiveViaNonVirtual>();
119 test<true, Derived2b, DerivedTransitiveViaNonVirtual>();
120 test<true, Derived2a, DerivedTransitiveViaVirtual>();
121 test<true, Derived2b, DerivedTransitiveViaVirtual>();
122 test<false, Base, CrazyDerived<Base>>();
123 test<false, CrazyDerived<Base>, Base>();
124 test<true, Base, CrazyDerivedVirtual<Base>>();
125 test<false, CrazyDerivedVirtual<Base>, Base>();
126 }
127
128 // Test unrelated types
129 {
130 test<false, Base&, Derived&>();
131 test<false, Base[3], Derived[3]>();
132 test<false, Unrelated, Derived>();
133 test<false, Base, Unrelated>();
134 test<false, Base, void>();
135 test<false, void, Derived>();
136 }
137
138 // Test scalar types
139 {
140 test<false, int, Base>();
141 test<false, int, Derived>();
142 test<false, int, Incomplete>();
143 test<false, int, int>();
144
145 test<false, Base, int>();
146 test<false, Derived, int>();
147 test<false, Incomplete, int>();
148
149 test<false, int[], int[]>();
150 test<false, long, int>();
151 test<false, int, long>();
152 }
153
154 // Test unions
155 {
156 test<false, Union, Union>();
157 test<false, IncompleteUnion, IncompleteUnion>();
158 test<false, Union, IncompleteUnion>();
159 test<false, IncompleteUnion, Union>();
160 test<false, Incomplete, IncompleteUnion>();
161 test<false, IncompleteUnion, Incomplete>();
162 test<false, Unrelated, IncompleteUnion>();
163 test<false, IncompleteUnion, Unrelated>();
164 test<false, int, IncompleteUnion>();
165 test<false, IncompleteUnion, int>();
166 test<false, Unrelated, Union>();
167 test<false, Union, Unrelated>();
168 test<false, int, Unrelated>();
169 test<false, Union, int>();
170 }
171
172 return 0;
173}
174

source code of libcxx/test/std/utilities/meta/meta.rel/is_virtual_base_of.pass.cpp