1 | //===- llvm/unittest/ADT/BitmaskEnumTest.cpp - BitmaskEnum unit tests -----===// |
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 | #include "llvm/ADT/BitmaskEnum.h" |
10 | #include "gtest/gtest.h" |
11 | |
12 | using namespace llvm; |
13 | |
14 | namespace { |
15 | enum Flags { |
16 | F0 = 0, |
17 | F1 = 1, |
18 | F2 = 2, |
19 | F3 = 4, |
20 | F4 = 8, |
21 | LLVM_MARK_AS_BITMASK_ENUM(F4) |
22 | }; |
23 | |
24 | static_assert(is_bitmask_enum<Flags>::value != 0); |
25 | static_assert(largest_bitmask_enum_bit<Flags>::value == Flags::F4); |
26 | |
27 | enum Flags2 { V0 = 0, V1 = 1, V2 = 2, V3 = 4, V4 = 8 }; |
28 | } // namespace |
29 | |
30 | namespace llvm { |
31 | LLVM_DECLARE_ENUM_AS_BITMASK(Flags2, V4); |
32 | } |
33 | |
34 | static_assert(is_bitmask_enum<Flags>::value != 0); |
35 | static_assert(largest_bitmask_enum_bit<Flags>::value == Flags::F4); |
36 | |
37 | namespace { |
38 | TEST(BitmaskEnumTest, BitwiseOr) { |
39 | Flags f = F1 | F2; |
40 | EXPECT_EQ(3, f); |
41 | |
42 | f = f | F3; |
43 | EXPECT_EQ(7, f); |
44 | |
45 | Flags2 f2 = V1 | V2; |
46 | EXPECT_EQ(3, f2); |
47 | |
48 | f2 = f2 | V3; |
49 | EXPECT_EQ(7, f2); |
50 | } |
51 | |
52 | TEST(BitmaskEnumTest, BitwiseOrEquals) { |
53 | Flags f = F1; |
54 | f |= F3; |
55 | EXPECT_EQ(5, f); |
56 | |
57 | // |= should return a reference to the LHS. |
58 | f = F2; |
59 | (f |= F3) = F1; |
60 | EXPECT_EQ(F1, f); |
61 | |
62 | Flags2 f2 = V1; |
63 | f2 |= V3; |
64 | EXPECT_EQ(5, f2); |
65 | |
66 | f2 = V2; |
67 | (f2 |= V3) = V1; |
68 | EXPECT_EQ(V1, f2); |
69 | } |
70 | |
71 | TEST(BitmaskEnumTest, BitwiseAnd) { |
72 | Flags f = static_cast<Flags>(3) & F2; |
73 | EXPECT_EQ(F2, f); |
74 | |
75 | f = (f | F3) & (F1 | F2 | F3); |
76 | EXPECT_EQ(6, f); |
77 | |
78 | Flags2 f2 = static_cast<Flags2>(3) & V2; |
79 | EXPECT_EQ(V2, f2); |
80 | |
81 | f2 = (f2 | V3) & (V1 | V2 | V3); |
82 | EXPECT_EQ(6, f2); |
83 | } |
84 | |
85 | TEST(BitmaskEnumTest, BitwiseAndEquals) { |
86 | Flags f = F1 | F2 | F3; |
87 | f &= F1 | F2; |
88 | EXPECT_EQ(3, f); |
89 | |
90 | // &= should return a reference to the LHS. |
91 | (f &= F1) = F3; |
92 | EXPECT_EQ(F3, f); |
93 | |
94 | Flags2 f2 = V1 | V2 | V3; |
95 | f2 &= V1 | V2; |
96 | EXPECT_EQ(3, f2); |
97 | |
98 | (f2 &= V1) = V3; |
99 | EXPECT_EQ(V3, f2); |
100 | } |
101 | |
102 | TEST(BitmaskEnumTest, BitwiseXor) { |
103 | Flags f = (F1 | F2) ^ (F2 | F3); |
104 | EXPECT_EQ(5, f); |
105 | |
106 | f = f ^ F1; |
107 | EXPECT_EQ(4, f); |
108 | |
109 | Flags2 f2 = (V1 | V2) ^ (V2 | V3); |
110 | EXPECT_EQ(5, f2); |
111 | |
112 | f2 = f2 ^ V1; |
113 | EXPECT_EQ(4, f2); |
114 | } |
115 | |
116 | TEST(BitmaskEnumTest, BitwiseXorEquals) { |
117 | Flags f = (F1 | F2); |
118 | f ^= (F2 | F4); |
119 | EXPECT_EQ(9, f); |
120 | |
121 | // ^= should return a reference to the LHS. |
122 | (f ^= F4) = F3; |
123 | EXPECT_EQ(F3, f); |
124 | |
125 | Flags2 f2 = (V1 | V2); |
126 | f2 ^= (V2 | V4); |
127 | EXPECT_EQ(9, f2); |
128 | |
129 | (f2 ^= V4) = V3; |
130 | EXPECT_EQ(V3, f2); |
131 | } |
132 | |
133 | TEST(BitmaskEnumTest, ConstantExpression) { |
134 | constexpr Flags f1 = ~F1; |
135 | constexpr Flags f2 = F1 | F2; |
136 | constexpr Flags f3 = F1 & F2; |
137 | constexpr Flags f4 = F1 ^ F2; |
138 | EXPECT_EQ(f1, ~F1); |
139 | EXPECT_EQ(f2, F1 | F2); |
140 | EXPECT_EQ(f3, F1 & F2); |
141 | EXPECT_EQ(f4, F1 ^ F2); |
142 | |
143 | constexpr Flags2 f21 = ~V1; |
144 | constexpr Flags2 f22 = V1 | V2; |
145 | constexpr Flags2 f23 = V1 & V2; |
146 | constexpr Flags2 f24 = V1 ^ V2; |
147 | EXPECT_EQ(f21, ~V1); |
148 | EXPECT_EQ(f22, V1 | V2); |
149 | EXPECT_EQ(f23, V1 & V2); |
150 | EXPECT_EQ(f24, V1 ^ V2); |
151 | } |
152 | |
153 | TEST(BitmaskEnumTest, BitwiseNot) { |
154 | Flags f = ~F1; |
155 | EXPECT_EQ(14, f); // Largest value for f is 15. |
156 | EXPECT_EQ(15, ~F0); |
157 | |
158 | Flags2 f2 = ~V1; |
159 | EXPECT_EQ(14, f2); |
160 | EXPECT_EQ(15, ~V0); |
161 | } |
162 | |
163 | enum class FlagsClass { |
164 | F0 = 0, |
165 | F1 = 1, |
166 | F2 = 2, |
167 | F3 = 4, |
168 | LLVM_MARK_AS_BITMASK_ENUM(F3) |
169 | }; |
170 | |
171 | TEST(BitmaskEnumTest, ScopedEnum) { |
172 | FlagsClass f = (FlagsClass::F1 & ~FlagsClass::F0) | FlagsClass::F2; |
173 | f |= FlagsClass::F3; |
174 | EXPECT_EQ(7, static_cast<int>(f)); |
175 | } |
176 | |
177 | struct Container { |
178 | enum Flags { F0 = 0, F1 = 1, F2 = 2, F3 = 4, LLVM_MARK_AS_BITMASK_ENUM(F3) }; |
179 | |
180 | static Flags getFlags() { |
181 | Flags f = F0 | F1; |
182 | f |= F2; |
183 | return f; |
184 | } |
185 | }; |
186 | |
187 | TEST(BitmaskEnumTest, EnumInStruct) { EXPECT_EQ(3, Container::getFlags()); } |
188 | |
189 | } // namespace |
190 | |
191 | namespace foo { |
192 | namespace bar { |
193 | namespace { |
194 | enum FlagsInNamespace { |
195 | F0 = 0, |
196 | F1 = 1, |
197 | F2 = 2, |
198 | F3 = 4, |
199 | LLVM_MARK_AS_BITMASK_ENUM(F3) |
200 | }; |
201 | } // namespace |
202 | } // namespace foo |
203 | } // namespace bar |
204 | |
205 | namespace { |
206 | TEST(BitmaskEnumTest, EnumInNamespace) { |
207 | foo::bar::FlagsInNamespace f = ~foo::bar::F0 & (foo::bar::F1 | foo::bar::F2); |
208 | f |= foo::bar::F3; |
209 | EXPECT_EQ(7, f); |
210 | } |
211 | } // namespace |
212 | |