xref: /llvm-project/llvm/unittests/ADT/BitmaskEnumTest.cpp (revision baaf1115ca007f95fd08c52dc8bec54d310f5b27)
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, BitwiseShift) {
134   Flags f = (F1 << F1);
135   EXPECT_EQ(f, F2);
136 
137   Flags f2 = F1;
138   f2 <<= F1;
139   EXPECT_EQ(f2, F2);
140 
141   Flags f3 = (F1 >> F1);
142   EXPECT_EQ(f3, F0);
143 
144   Flags f4 = F1;
145   f4 >>= F1;
146   EXPECT_EQ(f4, F0);
147 }
148 
149 TEST(BitmaskEnumTest, ConstantExpression) {
150   constexpr Flags f1 = ~F1;
151   constexpr Flags f2 = F1 | F2;
152   constexpr Flags f3 = F1 & F2;
153   constexpr Flags f4 = F1 ^ F2;
154   EXPECT_EQ(f1, ~F1);
155   EXPECT_EQ(f2, F1 | F2);
156   EXPECT_EQ(f3, F1 & F2);
157   EXPECT_EQ(f4, F1 ^ F2);
158 
159   constexpr Flags2 f21 = ~V1;
160   constexpr Flags2 f22 = V1 | V2;
161   constexpr Flags2 f23 = V1 & V2;
162   constexpr Flags2 f24 = V1 ^ V2;
163   EXPECT_EQ(f21, ~V1);
164   EXPECT_EQ(f22, V1 | V2);
165   EXPECT_EQ(f23, V1 & V2);
166   EXPECT_EQ(f24, V1 ^ V2);
167 }
168 
169 TEST(BitmaskEnumTest, BitwiseNot) {
170   Flags f = ~F1;
171   EXPECT_EQ(14, f); // Largest value for f is 15.
172   EXPECT_EQ(15, ~F0);
173 
174   Flags2 f2 = ~V1;
175   EXPECT_EQ(14, f2);
176   EXPECT_EQ(15, ~V0);
177 }
178 
179 enum class FlagsClass {
180   F0 = 0,
181   F1 = 1,
182   F2 = 2,
183   F3 = 4,
184   LLVM_MARK_AS_BITMASK_ENUM(F3)
185 };
186 
187 TEST(BitmaskEnumTest, ScopedEnum) {
188   FlagsClass f = (FlagsClass::F1 & ~FlagsClass::F0) | FlagsClass::F2;
189   f |= FlagsClass::F3;
190   EXPECT_EQ(7, static_cast<int>(f));
191 }
192 
193 struct Container {
194   enum Flags { F0 = 0, F1 = 1, F2 = 2, F3 = 4, LLVM_MARK_AS_BITMASK_ENUM(F3) };
195 
196   static Flags getFlags() {
197     Flags f = F0 | F1;
198     f |= F2;
199     return f;
200   }
201 };
202 
203 TEST(BitmaskEnumTest, EnumInStruct) { EXPECT_EQ(3, Container::getFlags()); }
204 
205 } // namespace
206 
207 namespace foo {
208 namespace bar {
209 namespace {
210 enum FlagsInNamespace {
211   F0 = 0,
212   F1 = 1,
213   F2 = 2,
214   F3 = 4,
215   LLVM_MARK_AS_BITMASK_ENUM(F3)
216 };
217 } // namespace
218 } // namespace foo
219 } // namespace bar
220 
221 namespace {
222 TEST(BitmaskEnumTest, EnumInNamespace) {
223   foo::bar::FlagsInNamespace f = ~foo::bar::F0 & (foo::bar::F1 | foo::bar::F2);
224   f |= foo::bar::F3;
225   EXPECT_EQ(7, f);
226 }
227 } // namespace
228