xref: /llvm-project/libcxx/test/std/input.output/filesystems/fs.enum/check_bitmask_types.h (revision 0f3efc4aab9748ea4791ed47530a9ea7174b97e3)
1 #ifndef TEST_BITMASK_TYPE_H
2 #define TEST_BITMASK_TYPE_H
3 
4 #include <type_traits>
5 #include <cassert>
6 
7 #include "test_macros.h"
8 
9 
10 template <class EnumType, EnumType Val1, EnumType Val2,
11           class UT = typename std::underlying_type<EnumType>::type,
12           UT UVal1 = static_cast<UT>(Val1),
13           UT UVal2 = static_cast<UT>(Val2),
14           UT UZero = static_cast<UT>(0),
15           EnumType Zero = static_cast<EnumType>(0)
16         >
17 struct check_bitmask_type {
18 
dcastcheck_bitmask_type19   static constexpr UT dcast(EnumType e) { return static_cast<UT>(e); }
unpromotecheck_bitmask_type20   static constexpr UT unpromote(decltype((~UZero)) promoted) { return static_cast<UT>(promoted); }
21   // We need two values that are non-zero and share at least one bit.
22   static_assert(Val1 != Zero && Val2 != Zero, "");
23   static_assert(Val1 != Val2, "");
24   static_assert((UVal1 & UVal2) == 0, "");
25 
26 
checkcheck_bitmask_type27   static bool check()
28   {
29     {
30       EnumType ValRef = Val1;
31       ASSERT_SAME_TYPE(EnumType, decltype(Val1 & Val2));
32       ASSERT_SAME_TYPE(EnumType, decltype(Val1 | Val2));
33       ASSERT_SAME_TYPE(EnumType, decltype(Val1 ^ Val2));
34       ASSERT_SAME_TYPE(EnumType, decltype((~Val1)));
35       ASSERT_SAME_TYPE(EnumType&, decltype(ValRef &= Val2));
36       ASSERT_SAME_TYPE(EnumType&, decltype(ValRef |= Val2));
37       ASSERT_SAME_TYPE(EnumType&, decltype(ValRef ^= Val2));
38     }
39 
40     static_assert((Val1 & Zero) == Zero, "");
41     static_assert((Val1 & Val1) == Val1, "");
42     static_assert(dcast(Val1 & Val2) == (UVal1 & UVal2), "");
43 
44     static_assert((Val1 | Zero) == Val1, "");
45     static_assert(dcast(Val1 | Val2) == (UVal1 | UVal2), "");
46 
47     static_assert((Val1 ^ Zero) == Val1, "");
48     static_assert(dcast(Val1 ^ Val2) == (UVal1 ^ UVal2), "");
49 
50     static_assert(dcast(~Zero) == unpromote(~UZero), "");
51     static_assert(dcast(~Val1) == unpromote(~UVal1), "");
52 
53     {
54       EnumType e = Val1;
55       EnumType& eref = (e &= Val2);
56       assert(&eref == &e);
57       assert(dcast(eref) == (UVal1 & UVal2));
58     }
59     {
60       EnumType e = Val1;
61       EnumType& eref = (e |= Val2);
62       assert(&eref == &e);
63       assert(dcast(eref) == (UVal1 | UVal2));
64     }
65     {
66       EnumType e = Val1;
67       EnumType& eref = (e ^= Val2);
68       assert(&eref == &e);
69       assert(dcast(eref) == (UVal1 ^ UVal2));
70     }
71     return true;
72   }
73 };
74 
75 #endif // TEST_BITMASK_TYPE
76