211 lines
4.1 KiB
C++
211 lines
4.1 KiB
C++
//===- llvm/unittest/ADT/BitmaskEnumTest.cpp - BitmaskEnum unit tests -----===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/ADT/BitmaskEnum.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
enum Flags {
|
|
F0 = 0,
|
|
F1 = 1,
|
|
F2 = 2,
|
|
F3 = 4,
|
|
F4 = 8,
|
|
LLVM_MARK_AS_BITMASK_ENUM(F4)
|
|
};
|
|
|
|
static_assert(is_bitmask_enum<Flags>::value != 0);
|
|
static_assert(largest_bitmask_enum_bit<Flags>::value == Flags::F4);
|
|
|
|
enum Flags2 { V0 = 0, V1 = 1, V2 = 2, V3 = 4, V4 = 8 };
|
|
} // namespace
|
|
|
|
namespace llvm {
|
|
LLVM_DECLARE_ENUM_AS_BITMASK(Flags2, V4);
|
|
}
|
|
|
|
static_assert(is_bitmask_enum<Flags>::value != 0);
|
|
static_assert(largest_bitmask_enum_bit<Flags>::value == Flags::F4);
|
|
|
|
namespace {
|
|
TEST(BitmaskEnumTest, BitwiseOr) {
|
|
Flags f = F1 | F2;
|
|
EXPECT_EQ(3, f);
|
|
|
|
f = f | F3;
|
|
EXPECT_EQ(7, f);
|
|
|
|
Flags2 f2 = V1 | V2;
|
|
EXPECT_EQ(3, f2);
|
|
|
|
f2 = f2 | V3;
|
|
EXPECT_EQ(7, f2);
|
|
}
|
|
|
|
TEST(BitmaskEnumTest, BitwiseOrEquals) {
|
|
Flags f = F1;
|
|
f |= F3;
|
|
EXPECT_EQ(5, f);
|
|
|
|
// |= should return a reference to the LHS.
|
|
f = F2;
|
|
(f |= F3) = F1;
|
|
EXPECT_EQ(F1, f);
|
|
|
|
Flags2 f2 = V1;
|
|
f2 |= V3;
|
|
EXPECT_EQ(5, f2);
|
|
|
|
f2 = V2;
|
|
(f2 |= V3) = V1;
|
|
EXPECT_EQ(V1, f2);
|
|
}
|
|
|
|
TEST(BitmaskEnumTest, BitwiseAnd) {
|
|
Flags f = static_cast<Flags>(3) & F2;
|
|
EXPECT_EQ(F2, f);
|
|
|
|
f = (f | F3) & (F1 | F2 | F3);
|
|
EXPECT_EQ(6, f);
|
|
|
|
Flags2 f2 = static_cast<Flags2>(3) & V2;
|
|
EXPECT_EQ(V2, f2);
|
|
|
|
f2 = (f2 | V3) & (V1 | V2 | V3);
|
|
EXPECT_EQ(6, f2);
|
|
}
|
|
|
|
TEST(BitmaskEnumTest, BitwiseAndEquals) {
|
|
Flags f = F1 | F2 | F3;
|
|
f &= F1 | F2;
|
|
EXPECT_EQ(3, f);
|
|
|
|
// &= should return a reference to the LHS.
|
|
(f &= F1) = F3;
|
|
EXPECT_EQ(F3, f);
|
|
|
|
Flags2 f2 = V1 | V2 | V3;
|
|
f2 &= V1 | V2;
|
|
EXPECT_EQ(3, f2);
|
|
|
|
(f2 &= V1) = V3;
|
|
EXPECT_EQ(V3, f2);
|
|
}
|
|
|
|
TEST(BitmaskEnumTest, BitwiseXor) {
|
|
Flags f = (F1 | F2) ^ (F2 | F3);
|
|
EXPECT_EQ(5, f);
|
|
|
|
f = f ^ F1;
|
|
EXPECT_EQ(4, f);
|
|
|
|
Flags2 f2 = (V1 | V2) ^ (V2 | V3);
|
|
EXPECT_EQ(5, f2);
|
|
|
|
f2 = f2 ^ V1;
|
|
EXPECT_EQ(4, f2);
|
|
}
|
|
|
|
TEST(BitmaskEnumTest, BitwiseXorEquals) {
|
|
Flags f = (F1 | F2);
|
|
f ^= (F2 | F4);
|
|
EXPECT_EQ(9, f);
|
|
|
|
// ^= should return a reference to the LHS.
|
|
(f ^= F4) = F3;
|
|
EXPECT_EQ(F3, f);
|
|
|
|
Flags2 f2 = (V1 | V2);
|
|
f2 ^= (V2 | V4);
|
|
EXPECT_EQ(9, f2);
|
|
|
|
(f2 ^= V4) = V3;
|
|
EXPECT_EQ(V3, f2);
|
|
}
|
|
|
|
TEST(BitmaskEnumTest, ConstantExpression) {
|
|
constexpr Flags f1 = ~F1;
|
|
constexpr Flags f2 = F1 | F2;
|
|
constexpr Flags f3 = F1 & F2;
|
|
constexpr Flags f4 = F1 ^ F2;
|
|
EXPECT_EQ(f1, ~F1);
|
|
EXPECT_EQ(f2, F1 | F2);
|
|
EXPECT_EQ(f3, F1 & F2);
|
|
EXPECT_EQ(f4, F1 ^ F2);
|
|
|
|
constexpr Flags2 f21 = ~V1;
|
|
constexpr Flags2 f22 = V1 | V2;
|
|
constexpr Flags2 f23 = V1 & V2;
|
|
constexpr Flags2 f24 = V1 ^ V2;
|
|
EXPECT_EQ(f21, ~V1);
|
|
EXPECT_EQ(f22, V1 | V2);
|
|
EXPECT_EQ(f23, V1 & V2);
|
|
EXPECT_EQ(f24, V1 ^ V2);
|
|
}
|
|
|
|
TEST(BitmaskEnumTest, BitwiseNot) {
|
|
Flags f = ~F1;
|
|
EXPECT_EQ(14, f); // Largest value for f is 15.
|
|
EXPECT_EQ(15, ~F0);
|
|
|
|
Flags2 f2 = ~V1;
|
|
EXPECT_EQ(14, f2);
|
|
EXPECT_EQ(15, ~V0);
|
|
}
|
|
|
|
enum class FlagsClass {
|
|
F0 = 0,
|
|
F1 = 1,
|
|
F2 = 2,
|
|
F3 = 4,
|
|
LLVM_MARK_AS_BITMASK_ENUM(F3)
|
|
};
|
|
|
|
TEST(BitmaskEnumTest, ScopedEnum) {
|
|
FlagsClass f = (FlagsClass::F1 & ~FlagsClass::F0) | FlagsClass::F2;
|
|
f |= FlagsClass::F3;
|
|
EXPECT_EQ(7, static_cast<int>(f));
|
|
}
|
|
|
|
struct Container {
|
|
enum Flags { F0 = 0, F1 = 1, F2 = 2, F3 = 4, LLVM_MARK_AS_BITMASK_ENUM(F3) };
|
|
|
|
static Flags getFlags() {
|
|
Flags f = F0 | F1;
|
|
f |= F2;
|
|
return f;
|
|
}
|
|
};
|
|
|
|
TEST(BitmaskEnumTest, EnumInStruct) { EXPECT_EQ(3, Container::getFlags()); }
|
|
|
|
} // namespace
|
|
|
|
namespace foo {
|
|
namespace bar {
|
|
namespace {
|
|
enum FlagsInNamespace {
|
|
F0 = 0,
|
|
F1 = 1,
|
|
F2 = 2,
|
|
F3 = 4,
|
|
LLVM_MARK_AS_BITMASK_ENUM(F3)
|
|
};
|
|
} // namespace
|
|
} // namespace foo
|
|
} // namespace bar
|
|
|
|
namespace {
|
|
TEST(BitmaskEnumTest, EnumInNamespace) {
|
|
foo::bar::FlagsInNamespace f = ~foo::bar::F0 & (foo::bar::F1 | foo::bar::F2);
|
|
f |= foo::bar::F3;
|
|
EXPECT_EQ(7, f);
|
|
}
|
|
} // namespace
|