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 
TEST(BitmaskEnumTest,BitwiseOr)24 TEST(BitmaskEnumTest, BitwiseOr) {
25   Flags f = F1 | F2;
26   EXPECT_EQ(3, f);
27 
28   f = f | F3;
29   EXPECT_EQ(7, f);
30 }
31 
TEST(BitmaskEnumTest,BitwiseOrEquals)32 TEST(BitmaskEnumTest, BitwiseOrEquals) {
33   Flags f = F1;
34   f |= F3;
35   EXPECT_EQ(5, f);
36 
37   // |= should return a reference to the LHS.
38   f = F2;
39   (f |= F3) = F1;
40   EXPECT_EQ(F1, f);
41 }
42 
TEST(BitmaskEnumTest,BitwiseAnd)43 TEST(BitmaskEnumTest, BitwiseAnd) {
44   Flags f = static_cast<Flags>(3) & F2;
45   EXPECT_EQ(F2, f);
46 
47   f = (f | F3) & (F1 | F2 | F3);
48   EXPECT_EQ(6, f);
49 }
50 
TEST(BitmaskEnumTest,BitwiseAndEquals)51 TEST(BitmaskEnumTest, BitwiseAndEquals) {
52   Flags f = F1 | F2 | F3;
53   f &= F1 | F2;
54   EXPECT_EQ(3, f);
55 
56   // &= should return a reference to the LHS.
57   (f &= F1) = F3;
58   EXPECT_EQ(F3, f);
59 }
60 
TEST(BitmaskEnumTest,BitwiseXor)61 TEST(BitmaskEnumTest, BitwiseXor) {
62   Flags f = (F1 | F2) ^ (F2 | F3);
63   EXPECT_EQ(5, f);
64 
65   f = f ^ F1;
66   EXPECT_EQ(4, f);
67 }
68 
TEST(BitmaskEnumTest,BitwiseXorEquals)69 TEST(BitmaskEnumTest, BitwiseXorEquals) {
70   Flags f = (F1 | F2);
71   f ^= (F2 | F4);
72   EXPECT_EQ(9, f);
73 
74   // ^= should return a reference to the LHS.
75   (f ^= F4) = F3;
76   EXPECT_EQ(F3, f);
77 }
78 
TEST(BitmaskEnumTest,ConstantExpression)79 TEST(BitmaskEnumTest, ConstantExpression) {
80   constexpr Flags f1 = ~F1;
81   constexpr Flags f2 = F1 | F2;
82   constexpr Flags f3 = F1 & F2;
83   constexpr Flags f4 = F1 ^ F2;
84   EXPECT_EQ(f1, ~F1);
85   EXPECT_EQ(f2, F1 | F2);
86   EXPECT_EQ(f3, F1 & F2);
87   EXPECT_EQ(f4, F1 ^ F2);
88 }
89 
TEST(BitmaskEnumTest,BitwiseNot)90 TEST(BitmaskEnumTest, BitwiseNot) {
91   Flags f = ~F1;
92   EXPECT_EQ(14, f); // Largest value for f is 15.
93   EXPECT_EQ(15, ~F0);
94 }
95 
96 enum class FlagsClass {
97   F0 = 0,
98   F1 = 1,
99   F2 = 2,
100   F3 = 4,
101   LLVM_MARK_AS_BITMASK_ENUM(F3)
102 };
103 
TEST(BitmaskEnumTest,ScopedEnum)104 TEST(BitmaskEnumTest, ScopedEnum) {
105   FlagsClass f = (FlagsClass::F1 & ~FlagsClass::F0) | FlagsClass::F2;
106   f |= FlagsClass::F3;
107   EXPECT_EQ(7, static_cast<int>(f));
108 }
109 
110 struct Container {
111   enum Flags { F0 = 0, F1 = 1, F2 = 2, F3 = 4, LLVM_MARK_AS_BITMASK_ENUM(F3) };
112 
getFlags__anon49895ee40111::Container113   static Flags getFlags() {
114     Flags f = F0 | F1;
115     f |= F2;
116     return f;
117   }
118 };
119 
TEST(BitmaskEnumTest,EnumInStruct)120 TEST(BitmaskEnumTest, EnumInStruct) { EXPECT_EQ(3, Container::getFlags()); }
121 
122 } // namespace
123 
124 namespace foo {
125 namespace bar {
126 namespace {
127 enum FlagsInNamespace {
128   F0 = 0,
129   F1 = 1,
130   F2 = 2,
131   F3 = 4,
132   LLVM_MARK_AS_BITMASK_ENUM(F3)
133 };
134 } // namespace
135 } // namespace foo
136 } // namespace bar
137 
138 namespace {
TEST(BitmaskEnumTest,EnumInNamespace)139 TEST(BitmaskEnumTest, EnumInNamespace) {
140   foo::bar::FlagsInNamespace f = ~foo::bar::F0 & (foo::bar::F1 | foo::bar::F2);
141   f |= foo::bar::F3;
142   EXPECT_EQ(7, f);
143 }
144 } // namespace
145