1fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar/*
2fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * Copyright 2016 The Android Open Source Project
3fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar *
4fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * Licensed under the Apache License, Version 2.0 (the "License");
5fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * you may not use this file except in compliance with the License.
6fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * You may obtain a copy of the License at
7fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar *
8fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar *      http://www.apache.org/licenses/LICENSE-2.0
9fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar *
10fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * Unless required by applicable law or agreed to in writing, software
11fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * distributed under the License is distributed on an "AS IS" BASIS,
12fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * See the License for the specific language governing permissions and
14fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * limitations under the License.
15fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar */
16fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
17fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar//#define LOG_NDEBUG 0
18fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar#define LOG_TAG "Flagged_test"
19fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
20fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar#include <gtest/gtest.h>
21fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
22fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar#include <media/stagefright/foundation/Flagged.h>
23fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
24fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnarnamespace android {
25fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
26fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar/**
27fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * Helper template that can be used to print values in static_assert error messages.
28fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar *
29fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * Use integers here.
30fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar */
31fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnartemplate<bool, int ...N>
32fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnarstruct _print_as_warning { };
33fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
34fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnartemplate<int ...N>
35fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnarstruct _print_as_warning<true, N...> : std::true_type { };
36fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
37fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar#define static_assert_equals(a, b, msg) \
38fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnarstatic_assert(_print_as_warning<(a) == (b), a, b>::value, msg)
39fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
40fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnarclass FlaggedTest : public ::testing::Test {
41fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnarprotected:
42fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // empty structs
43fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    struct A0 { };
44fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    struct A1 { };
45fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    struct A_A0 : public A0 { };
46fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
47fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // simple struct
48fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    struct BB {
49fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar        int32_t i;
50fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar        uint32_t u;
51fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    };
52fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
53fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // struct inheriting from A0
54fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    struct BB_A0 : public A0 {
55fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar        int32_t i;
56fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar        uint32_t u;
57fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    };
58fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
59fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // struct inheriting from struct inheriting A0
60fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    struct BB_AA0 : public A_A0 {
61fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar        int32_t i;
62fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar        uint32_t u;
63fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    };
64fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
65fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // struct that wraps
66fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    struct WBBA0 {
67fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar        BB_A0 b;
68fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    };
69fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
70fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    struct WBBA0_A1 : public A1 {
71fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar        BB_A0 b;
72fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    };
73fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
74fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    struct WBBA0_A0 : public A0 {
75fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar        BB_A0 b;
76fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    };
77fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
78fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    struct WBB_A0 : public A0 {
79fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar        BB b;
80fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    };
81fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
82fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    struct WBBA0_AA0 : public A_A0 {
83fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar        BB_A0 b;
84fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    };
85fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
86fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    struct WBBAA0_A0 : public A0 {
87fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar        BB_AA0 b;
88fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    };
89fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
90fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    struct WWBBA0_A0 : public A0 {
91fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar        WBBA0 b;
92fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    };
93fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar};
94fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
95fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar/**
96fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * This test is here to confirm the handling of wrapping classes that inherit from an interface
97fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * while also inheriting from that same interface. While we no longer use this construct, we want
98fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar * to track if this defect is ever fixed.
99fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar */
100fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos MolnarTEST_F(FlaggedTest, StaticSanityTests) {
101fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(sizeof(A0) == 1, "");
102fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(sizeof(A1) == 1, "");
103fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(sizeof(A_A0) == 1, "");
104fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
105fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static constexpr size_t size = sizeof(BB); // original [pair]
106fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
107fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // inheriting from A0 does not increase size
108fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(sizeof(BB_A0) == size, ""); // [pair]:A0
109fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(sizeof(BB_AA0) == size, ""); // [pair]:[:A0]
110fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
111fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar     // wrapping a class that inherits from A0 does not increase size
112fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(sizeof(WBBA0) == size, ""); // [ [pair]:[:A0] ]
113fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
114fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // wrapping a class that inherits from A0 while also inheriting from A1 does not increase size
115fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(sizeof(WBBA0_A1) == size, ""); // [ [pair]:A0 ]:A1
116fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
117fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // wrapping a class that inherits from A0 while also inheriting from A0 DOES increase size
118fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_GT(sizeof(WBBA0_A0), size); // [ [pair]:A0 ]:A0
119fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
120fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // wrapping a class that does not inherit from A0 while inheriting from A0 does not increase
121fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // size
122fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(sizeof(WBB_A0) == size, ""); // [[pair]]:A0
123fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
124fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // wrapping a class that inherits from A0 while also inheriting from a class that inherits
125fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // from A0 does increase size
126fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_GT(sizeof(WBBA0_AA0), size); // [ [pair]:A0 ]:[:A0]
127fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
128fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // wrapping a class that indirectly inherits from A0 while also inheriting from A0 does
129fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // increase size
130fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_GT(sizeof(WBBAA0_A0), size); // [ [pair]:[:A0] ]:A0
131fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
132fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // wrapping a class that inherits from A0 while also inheriting A0 does increase size
133fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_GT(sizeof(WWBBA0_A0), size); //  [ [pair]:A0 ]:A0
134fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar}
135fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
136fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnarenum FLAG : int32_t {
137fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    kMask0 = 0x0FF,
138fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    kFlag0_A = 0x0AA,
139fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    kFlag0_B = 0x0BB,
140fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    kFlag0_C = 0x0CC,
141fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    kMask1 = 0xFF0,
142fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    kFlag1_A = 0xAA0,
143fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    kFlag1_B = 0xBB0,
144fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    kFlag1_C = 0xCC0,
145fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    kMaskCommon = 0x0F0,
146fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar};
147fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
148fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos MolnarTEST_F(FlaggedTest, BasicExample) {
149fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    enum SafeFlags : uint32_t {
150fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar      kUnsafe,
151fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar      kSafe,
152fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar      kSafeMask = _Flagged_helper::minMask(kSafe),
153fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    };
154fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef Flagged<int32_t, SafeFlags, kSafeMask> safeInt32;
155fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
156fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    safeInt32 a(kUnsafe);
157fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    a.setFlags(kSafe);
158fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    a.get() = 15;
159fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(a.flags(), kSafe);
160fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(a.get(), 15);
161fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
162fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    enum OriginFlags : uint32_t {
163fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar      kUnknown,
164fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar      kConst,
165fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar      kCalculated,
166fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar      kComponent,
167fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar      kApplication,
168fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar      kFile,
169fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar      kBinder,
170fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar      kOriginMask = _Flagged_helper::minMask(kBinder),
171fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    };
172fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef Flagged<safeInt32, OriginFlags, kOriginMask>
173fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar             trackedSafeInt32;
174fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
175fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(sizeof(trackedSafeInt32) == sizeof(safeInt32), "");
176fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
177fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    trackedSafeInt32 b(kConst, kSafe, 1);
178fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(b.flags(), kConst);
179fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(b.get().flags(), kSafe);
180fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(b.get().get(), 1);
181fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    b.setFlags(kCalculated);
182fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    volatile bool overflow = true;
183fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    b.get().setFlags(overflow ? kUnsafe : kSafe);
184fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
185fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    enum ValidatedFlags : uint32_t {
186fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar      kUnsafeV = kUnsafe,
187fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar      kSafeV = kSafe,
188fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar      kValidated = kSafe | 2,
189fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar      kSharedMaskV = kSafeMask,
190fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar      kValidatedMask = _Flagged_helper::minMask(kValidated),
191fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    };
192fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef Flagged<safeInt32, ValidatedFlags, kValidatedMask, kSharedMaskV> validatedInt32;
193fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
194fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    validatedInt32 v(kUnsafeV, kSafe, 10);
195fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(v.flags(), kUnsafeV);
196fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(v.get().flags(), kUnsafe);  // !kUnsafeV overrides kSafe
197fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(v.get().get(), 10);
198fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    v.setFlags(kValidated);
199fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(v.flags(), kValidated);
200fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(v.get().flags(), kSafe);
201fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    v.get().setFlags(kUnsafe);
202fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(v.flags(), 2);  // NOTE: sharing masks with enums allows strange situations to occur
203fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar}
204fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
205fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos MolnarTEST_F(FlaggedTest, _Flagged_helper_Test) {
206fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    using helper = _Flagged_helper;
207fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
208fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    using i32 = int32_t;
209fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    using u32 = uint32_t;
210fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    using u8 = uint8_t;
211fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
212fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // base2
213fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 0u, 0u, 0>::sFlagMask == 0u, "");
214fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 0u, 0u, 0>::sFlagShift == 0, "");
215fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 0u, 0u, 0>::sEffectiveMask == 0u, "");
216fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
217fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 0u, 0u, 10>::sFlagMask == 0u, "");
218fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 0u, 0u, 10>::sFlagShift == 10, "");
219fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 0u, 0u, 10>::sEffectiveMask == 0u, "");
220fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
221fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 0u, 0u, -1>::sFlagMask == 0u, "");
222fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 0u, 0u, -1>::sFlagShift == 0, "");
223fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 0u, 0u, -1>::sEffectiveMask == 0u, "");
224fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
225fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 99u, 0u, 0>::sFlagMask == 99u, "");
226fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 99u, 0u, 0>::sFlagShift == 0, "");
227fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 99u, 0u, 0>::sEffectiveMask == 99u, "");
228fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
229fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 0x99u, 0u, 12>::sFlagMask == 0x99u, "");
230fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 0x99u, 0u, 12>::sFlagShift == 12, "");
231fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 0x99u, 0u, 12>::sEffectiveMask == 0x99000u, "");
232fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
233fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 99u, 0u, -1>::sFlagMask == 99u, "");
234fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 99u, 0u, -1>::sFlagShift == 0, "");
235fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(Flagged<i32, u32, 99u, 0u, -1>::sEffectiveMask == 99u, "");
236fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
237fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // mask_of<T, Flag>
238fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // also Flagged<> no default
239fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef Flagged<i32, u32, 0x800F /* mask */, 0 /* shared mask */, 0 /* shift */> i32_800f_0;
240fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef Flagged<i32, u32, 0x800F /* mask */, 0 /* shared mask */, 4 /* shift */> i32_800f_4;
241fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // this also tests that these types can be instantiated
242fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(sizeof(i32_800f_0) >= sizeof(i32) + sizeof(u32),
243fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "should be at least size of component types");
244fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(sizeof(i32_800f_4) == sizeof(i32_800f_0), "regardless of shift");
245fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!i32_800f_0::sFlagCombined, "");
246fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!i32_800f_4::sFlagCombined, "");
247fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
248fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::mask_of<i32_800f_0, u32>::value == 0x800F, "incorrect mask");
249fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::mask_of<i32_800f_0, i32>::value == 0,
250fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "mask should be 0 when types mismatch");
251fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::mask_of<i32_800f_0, u32>::effective_value == 0x800F, "incorrect mask");
252fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::mask_of<i32_800f_0, i32>::effective_value == 0,
253fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "mask should be 0 when types mismatch");
254fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::mask_of<i32_800f_0, u32>::shift == 0, "incorrect shift");
255fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::mask_of<i32_800f_0, i32>::shift == 0,
256fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "shift should be 0 when types mismatch");
257fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
258fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::mask_of<i32_800f_4, u32>::value == 0x800F, "incorrect mask");
259fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::mask_of<i32_800f_4, i32>::value == 0,
260fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "mask should be 0 when types mismatch");
261fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::mask_of<i32_800f_4, u32>::effective_value == 0x800F0, "incorrect mask");
262fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::mask_of<i32_800f_4, i32>::effective_value == 0,
263fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "mask should be 0 when types mismatch");
264fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::mask_of<i32_800f_4, u32>::shift == 4, "incorrect shift");
265fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::mask_of<i32_800f_4, i32>::shift == 0,
266fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "shift should be 0 when types mismatch");
267fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::mask_of<i32, u32>::value == 0, "mask should be 0 if not masked");
268fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::mask_of<i32, i32>::value == 0, "mask should be 0 if not masked");
269fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
270fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // lshift(value, n)
271fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::lshift(0U, 0) == 0U, "");
272fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::lshift(0U, 30) == 0U, "");
273fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::lshift(1U, 0) == 1U, "");
274fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::lshift(1U, 10) == 1024U, "");
275fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::lshift(10U, 10) == 10240U, "");
276fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::lshift(10, 10) == 10240, "");
277fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::lshift(-10, 0) == -10, "");
278fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // static_assert(helper::lshift(-10, 10) == -10240, ""); // error: left shift of negative value
279fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
280fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // minMask(maxValue)
281fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::minMask(0U) == 0U, "lowest 0 bits");
282fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::minMask(1U) == 1U, "lowest 1 bit");
283fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::minMask(2U) == 3U, "lowest 2 bits");
284fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::minMask(3U) == 3U, "lowest 2 bits");
285fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::minMask(4U) == 7U, "lowest 3 bits");
286fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::minMask(~0U) == ~0U, "all bits");
287fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // static_assert(helper::minMask(10) == 0xF, "all bits"); // error: must be unsigned
288fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
289fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // topBits(n)
290fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::topBits<u32>(0) == 0U, "top 0 bit");
291fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::topBits<u32>(1) == 0x80000000U, "top 1 bit");
292fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::topBits<u32>(2) == 0xC0000000U, "top 2 bits");
293fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::topBits<u32>(12) == 0xFFF00000U, "top 12 bits");
294fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::topBits<u32>(32) == 0xFFFFFFFFU, "all bits");
295fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // static_assert(helper::topBits<u32>(33) == 0xFFFFFFFFU, ""); // should OVERFLOW
296fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
297fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::topBits<u8>(0) == 0U, "top 0 bit");
298fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::topBits<u8>(1) == 0x80U, "top 1 bit");
299fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::topBits<u8>(2) == 0xC0U, "top 2 bit");
300fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::topBits<u8>(8) == 0xFFU, "all bits");
301fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // static_assert(helper::topBits<u8>(9) == 0xFFU, ""); // should OVERFLOW
302fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
303fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // getShift(mask, base, shared, base-shift, base-effective)
304fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0u, 0u, 0u, 0, 0u) == 0, "no flag require no shift");
305fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0u, 0u, 1u, 0, 0u) == -1,
306fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "shared must be within mask and base mask");
307fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0u, 1u, 1u, 0, 1u) == -1, "shared must be within mask");
308fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0u, 1u, 0u, 0, 1u) == 0,
309fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "no flags require no shift even with base mask");
310fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0u, 1u, 0u, 1, 2u) == 0,
311fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "no flags require no shift even with shifted base mask");
312fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(1u, 0u, 0u, 0, 0u) == 0, "no base mask requires no shift");
313fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(1u, 1u, 0u, 0, 1u) == 1,
314fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "overlapping mask and basemask requires shift");
315fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(1u, 1u, 0u, 0, 1u) == 1,
316fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "overlapping mask and basemask requires shift");
317fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(1u, 1u, 1u, 0, 1u) == 0,
318fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "shared mask requires using base shift");
319fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(1u, 1u, 1u, 1, 2u) == 1,
320fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "shared mask requires using base shift");
321fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(3u, 5u, 1u, 0, 5u) == 0,
322fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "mask and basemask that overlap only in shared region requires no shift");
323fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(3u, 7u, 1u, 0, 7u) == -1,
324fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "mask and basemask must not overlap in more than shared region");
325fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(1u, 0u, 1u, 0, 0u) == -1, "shared must be within base mask");
326fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
327fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0u, 1u, 0u, 1, 1u) == -2, "effective mask must cover base mask");
328fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0u, 5u, 0u, 1, 2u) == -2, "effective mask must cover base mask");
329fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0u, 5u, 0u, 1, 10u) == 0, "");
330fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0u, 5u, 0u, 1, 31u) == 0,
331fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "effective mask can be larger than base mask");
332fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
333fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0x800Fu, 0x800Fu, 0x800Fu, 0, 0x800Fu) == 0,
334fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "(0x800F << 0) & 0x800F == 0x800F");
335fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0x800Fu, 0x800Fu, 0x800Fu, 16, 0x800F0000u) == 16,
336fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "(0x800F << 0) & 0x800F == 0x800F");
337fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0x1800Fu, 0x800Fu, 0x800Fu, 0, 0x800Fu) == 0,
338fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "(0x1800F << 0) & 0x800F == 0x800F");
339fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0x1800Fu, 0x800Fu, 0x800Fu, 16, 0x800F0000u) == -1,
340fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "(0x1800F << 16) overflows");
341fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
342fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // verify that when not sharing masks, effective mask makes the difference
343fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0x800Fu, 0u, 0u, 0, 0x800Fu) == 4,
344fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "(0x800F << 4) & 0x800F == 0");
345fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0x800Fu, 0x2u, 0u, 0, 0x8002u) == 2,
346fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "(0x800F << 2) & 0x8002 == 0");
347fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0x800Fu, 0x1u, 0u, 15, 0x8001u) == 1,
348fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "(0x800F << 1) & 0x8001 == 0");
349fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0x800Fu, 0x800Fu, 0u, 16, 0x800F0000u) == 0,
350fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "0x800F & 0x800F0000 == 0");
351fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0x800Fu, 0x800F8000u, 0u, 0, 0x800F8000u) == 5,
352fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "(0x800F << 5) & 0x800F8000 == 0");
353fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0x800Fu, 0xF0000u, 0u, 0, 0x800F8000u) == 5,
354fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "(0x800F << 5) & 0x800F8000 == 0");
355fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0x800Fu, 0x1Fu, 0u, 15, 0x800F8000u) == 5,
356fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "(0x800F << 5) & 0x800F8000 == 0");
357fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0xFFu, 0x80808080u, 0u, 0, 0x80808080u) == -1,
358fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "0xFF always overlaps with 0x80808080");
359fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0xFFu, 0x10001000u, 0u, 3, 0x80808080u) == -1,
360fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "0xFF always overlaps with 0x80808080");
361fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0xFFu, 0x80808040u, 0u, 0, 0x80808040u) == 7,
362fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "(0xFF << 7) & 0x 80808040 == 0");
363fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
364fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // verify min_shift (mask must be positive or no shift can be required)
365fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0xFF, 0x40808040, 0, 0, 0x40808040) == 7, "");
366fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift((i32)0x800000FF, 0x40808040, 0, 0, 0x40808040) == -1, "");
367fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0x100000FF, 0x40808040, 0, 0, 0x40808040) == -1, "");
368fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift(0xFF, (i32)0x80808040, 0, 0, (i32)0x80808040) == 7, "");
369fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift((i32)0x80007F80, 0x40808040, 0, 0, 0x40808040) == 0, "");
370fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
371fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // shared mask can also be negative (but not shift can be required)
372fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift((i32)0x80007F80, (i32)0xC0808040, (i32)0x80000000,
373fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                                   0, (i32)0xC0808040) == 0, "");
374fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift((i32)0x80007F80, (i32)0xC0808040, (i32)0xC0000000,
375fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                                   0, (i32)0xC0808040) == -1, "");
376fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::getShift((i32)0x80007F80, (i32)0x60404020, (i32)0x60000000,
377fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                                   1, (i32)0xC0808040) == -1, "");
378fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
379fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // min_shift
380fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef Flagged<i32, u32, 0u> i32_0_0;
381fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef Flagged<i32, u32, 1u> i32_1_0;
382fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef Flagged<i32, u32, 1u, 0u, 1> i32_1_1;
383fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
384fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // this is a wrapper over getShift, so same test cases apply when T is flagged
385fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32_0_0, u32, 0u, 0u>::value == 0, "");
386fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32_0_0, u32, 0u, 1u>::value == -1, "");
387fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32_1_0, u32, 0u, 1u>::value == -1, "");
388fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32_1_0, u32, 0u, 0u>::value == 0, "");
389fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32_0_0, u32, 1u, 0u>::value == 0, "");
390fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32_1_0, u32, 1u, 0u>::value == 1, "");
391fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32_1_0, u32, 1u, 1u>::value == 0, "");
392fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32_1_1, u32, 1u, 1u>::value == 1, "");
393fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32_1_1, u32, 3u, 0u>::value == 2, "");
394fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<Flagged<i32, u32, 5u>, u32, 3u, 1u>::value == 0, "");
395fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<Flagged<i32, u32, 7u>, u32, 3u, 1u>::value == -1, "");
396fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32_0_0, u32, 1u, 1u>::value == -1, "");
397fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
398fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32_800f_0, u32, 0x800Fu, 0u>::value == 4, "");
399fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32_800f_4, u32, 0x1800Fu, 0x800Fu>::value == 4, "");
400fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32_800f_4, u32, 0x800Fu, 0u>::value == 0, "");
401fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<Flagged<i32, u32, 0x8002u>, u32, 0x800Fu, 0u>::value == 2, "");
402fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<Flagged<i32, u32, 0x8001u>, u32, 0x800Fu, 0u>::value == 1, "");
403fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(
404fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar            helper::min_shift<Flagged<i32, u32, 0x800Fu, 0u, 16>, u32, 0x800Fu, 0u>::value == 0, "");
405fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(
406fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar            helper::min_shift<Flagged<i32, u32, 0x800F8000u>, u32, 0x800Fu, 0u>::value == 5, "");
407fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(
408fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar            helper::min_shift<Flagged<i32, u32, 0x80808080u>, u32, 0xFFu, 0u>::value == -1, "");
409fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(
410fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar            helper::min_shift<Flagged<i32, u32, 0x80808040u>, u32, 0xFFu, 0u>::value == 7, "");
411fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
412fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // for min_shift, non-tagged type behaves as if having base mask of 0
413fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32, u32, 0u, 0u>::value == 0, "");
414fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<u32, u32, 0u, 0u>::value == 0, "");
415fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32, u32, 0u, 0u>::value == 0, "");
416fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32, u32, 0u, 1u>::value == -1, "");
417fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32, u32, 1u, 0u>::value == 0, "");
418fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<i32, u32, 1u, 1u>::value == -1, "");
419fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
420fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // verify min_shift (mask must be positive or no shift can be required)
421fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<Flagged<i32, i32, 0x40808040>, i32, 0xFF, 0>::value == 7, "");
422fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<Flagged<i32, i32, 0x40808040>,
423fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                                    i32, (i32)0x800000FF, 0>::value == -1, "");
424fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<Flagged<i32, i32, 0x40808040>,
425fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                                    i32, 0x100000FF, 0>::value == -1, "");
426fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<Flagged<i32, i32, (i32)0x80808040>,
427fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                                    i32, 0xFF, 0>::value == 7, "");
428fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<Flagged<i32, i32, 0x40808040>,
429fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                                    i32, (i32)0x80007F80, 0>::value == 0, "");
430fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
431fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<Flagged<i32, i32, (i32)0x80808040>,
432fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                                    i32, (i32)0x80007F80, (i32)0x80000000>::value == 0, "");
433fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<Flagged<i32, i32, (i32)0xC0808040>,
434fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                                    i32, (i32)0x80007F80, (i32)0xC0000000>::value == -1, "");
435fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // note: cannot create a flagged type with signed flag and shift
436fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // static_assert(helper::min_shift<Flagged<i32, i32, (i32)0x60404020, 0, 1>,
437fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    //                                i32, (i32)0x40003FC0, (i32)0x40000000>::value == -1, "");
438fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
439fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef Flagged<i32, u32, 0x800F /* mask */, 0 /* shared mask */, 16 /* shift */> i32_800f_16;
440fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert_equals(sizeof(i32_800f_16), sizeof(i32_800f_0), "");
441fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // shifted mask overflows!
442fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // typedef Flagged<i32, u32, 0x800F /* mask */, 0 /* shared mask */, 17 /* shift */> i32_800f_17;
443fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // static_assert(sizeof(i32_800f_17) == sizeof(i32_800f_0), "");
444fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef Flagged<i32, i32, 0x800F /* mask */, 0 /* shared mask */, 15 /* shift */> i32_800f_15i;
445fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert_equals(sizeof(i32_800f_15i), sizeof(i32_800f_0), "");
446fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // shifted mask overflows!
447fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // typedef Flagged<i32, i32, 0x800F /* mask */, 0 /* shared mask */, 16 /* shift */> i32_800f_16i;
448fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // static_assert(sizeof(i32_800f_16i) == sizeof(i32_800f_0), "");
449fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
450fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // canCombine(mask, base, shared, shift, base-shift, base-effective)
451fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(0u, 0u, 0u, 0, 0, 0u), "using no mask is valid");
452fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(0u, 0u, 0u, 0, 0, 0u), "");
453fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(0u, 0u, 0u, 4, 0, 0u), "");
454fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine(0u, 0u, 1u, 0, 0, 0u),
455fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "shared mask must be the overlap of masks");
456fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(1u, 0u, 0u, 0, 0, 0u), "");
457fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(1u, 0u, 0u, 4, 0, 0u), "");
458fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(3u, 5u, 1u, 0, 0, 5u), "");
459fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine(3u, 3u, 3u, 1, 0, 3u), "shift must match when sharing mask");
460fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(3u, 3u, 3u, 1, 1, 6u), "");
461fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine(3u, 3u, 3u, 1, 2, 12u), "shift must match when sharing mask");
462fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine(3u, 7u, 1u, 0, 0, 7u), "");
463fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine(1u, 0u, 1u, 0, 0, 0u), "");
464fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
465fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine(0u, 1u, 1u, 0, 0, 1u),
466fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "shared mask must be the overlap of masks");
467fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(0u, 1u, 0u, 0, 0, 1u), "");
468fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(0u, 1u, 0u, 4, 0, 1u), "");
469fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(1u, 1u, 0u, 1, 0, 1u), "");
470fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine(1u, 1u, 0u, 0, 0, 1u), "");
471fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(1u, 1u, 0u, 1, 0, 1u), "");
472fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(1u, 1u, 1u, 0, 0, 1u), "");
473fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine(1u, 1u, 1u, 1, 0, 1u), "shift must match when sharing mask");
474fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
475fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(0x800Fu, 0x800Fu, 0u, 4, 0, 0x800Fu), "");
476fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine(0x800Fu, 0x800Fu, 0u, 1, 0, 0x800Fu), "");
477fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(0x800Fu, 0x8002u, 0u, 2, 0, 0x8002u), "");
478fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(0x800Fu, 0x8001u, 0u, 1, 0, 0x8001u), "");
479fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(0x800Fu, 0x800Fu, 0u, 0, 16, 0x800F0000u), "");
480fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(0x800Fu, 0x800Fu, 0x800Fu, 16, 16, 0x800F0000u), "");
481fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine(0x1800Fu, 0x800Fu, 0u, 0, 16, 0x800F0000u), "");
482fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine(0x1800Fu, 0x800Fu, 0x800Fu, 16, 16, 0x800F0000u), "");
483fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(0x800Fu, 0x800F8000u, 0u, 8, 0, 0x800F8000u), "");
484fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine(0xFFu, 0x80808080u, 0u, -1, 0, 0x80808080u), "");
485fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(0xFFu, 0x80808040u, 0u, 7, 0, 0x80808040u), "");
486fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(0xFFu, 0x8000u, 0u, 7, 0, 0x80808040u), "");
487fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(0xFFu, 0x101u, 0u, 7, 15, 0x80808040u), "");
488fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
489fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // can combine signed-flagged types only if mask is positive or no shift is required
490fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine(0xFF, 0x40808040, 0, 0, 0, 0x40808040), "");
491fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(0xFF, 0x40808040, 0, 7, 0, 0x40808040), "");
492fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine((i32)0x800000FF, 0x40808040, 0, 0, 0, 0x40808040), "");
493fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine((i32)0x800000FF, 0x40808040, 0, 7, 0, 0x40808040), "");
494fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine(0x100000FF, 0x40808040, 0, 0, 0, 0x40808040), "");
495fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine(0x100000FF, 0x40808040, 0, 7, 0, 0x40808040), "");
496fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine(0xFF, (i32)0x80808040, 0, 0, 0, (i32)0x80808040), "");
497fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine(0xFF, (i32)0x80808040, 0, 7, 0, (i32)0x80808040), "");
498fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine((i32)0x80007F80, 0x40808040, 0, 0, 0, 0x40808040), "");
499fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
500fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::canCombine((i32)0x80007F80, (i32)0x80808040, (i32)0x80000000, 0, 0, (i32)0x80808040), "");
501fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine((i32)0xC0007F80, (i32)0x80808040, (i32)0xC0000000, 0, 0, (i32)0x80808040), "");
502fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine((i32)0x80007F80, (i32)0x80808040, (i32)0x80000000, 1, 0, (i32)0x80808040), "");
503fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::canCombine((i32)0xC0007F80, (i32)0x80808040, (i32)0xC0000000, 1, 0, (i32)0x80808040), "");
504fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
505fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // can_combine<T, Flag, MASK, [SHARED_MASK], [SHIFT]
506fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<i32_0_0, u32, 0u>::value, "");
507fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<i32_0_0, u32, 0u, 0u>::value, "");
508fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<i32_0_0, u32, 0u, 0u, 4>::value, "");
509fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::can_combine<i32_0_0, u32, 0u, 1u>::value, "");
510fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<i32_0_0, u32, 1u, 0u>::value, "");
511fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<i32_0_0, u32, 1u, 0u, 4>::value, "");
512fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::can_combine<i32_0_0, u32, 1u, 1u>::value, "");
513fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
514fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::can_combine<i32_1_0, u32, 0u, 1u>::value, "");
515fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<i32_1_0, u32, 0u, 0u>::value, "");
516fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<i32_1_0, u32, 0u, 0u, 4>::value, "");
517fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<i32_1_0, u32, 1u, 0u>::value, "");
518fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::can_combine<i32_1_0, u32, 1u, 0u, 0>::value, "");
519fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<i32_1_0, u32, 1u, 0u, 1>::value, "");
520fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<i32_1_0, u32, 1u, 1u>::value, "");
521fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<i32_1_0, u32, 1u, 1u, 0>::value, "");
522fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::can_combine<i32_1_0, u32, 1u, 1u, 1>::value,
523fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                  "shouldn't be able to use SHIFT with SHARED_MASK");
524fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
525fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<i32_800f_0, u32, 0x800Fu, 0u, 4>::value, "");
526fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::can_combine<i32_800f_0, u32, 0x800Fu, 0u, 1>::value, "");
527fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<i32_800f_0, u32, 0x800Fu, 0u>::value, "");
528fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<Flagged<i32, u32, 0x8002u>, u32, 0x800Fu, 0u>::value, "");
529fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<Flagged<i32, u32, 0x8001u>, u32, 0x800Fu, 0u>::value, "");
530fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<Flagged<i32, u32, 0x800F0000u>, u32, 0x800Fu, 0u>::value, "");
531fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<Flagged<i32, u32, 0x800F8000u>, u32, 0x800Fu, 0u>::value, "");
532fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::can_combine<Flagged<i32, u32, 0x80808080u>, u32, 0xFFu, 0u>::value, "");
533fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<Flagged<i32, u32, 0x80808040u>, u32, 0xFFu, 0u>::value, "");
534fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
535fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // can combine signed-flagged types only if mask is positive or no shift is required
536fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<Flagged<i32, i32, 0x40808040>, i32, 0xFF, 0>::value, "");
537fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::can_combine<Flagged<i32, i32, 0x40808040>,
538fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                                       i32, (i32)0x800000FF, 0>::value, "");
539fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::can_combine<Flagged<i32, i32, 0x40808040>,
540fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                                       i32, 0x100000FF, 0>::value, "");
541fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<Flagged<i32, i32, (i32)0x80808040>, i32, 0xFF, 0>::value, "");
542fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<Flagged<i32, i32, 0x40808040>,
543fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                                      i32, (i32)0x80007F80, 0>::value, "");
544fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
545fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<Flagged<i32, i32, (i32)0x80808040>,
546fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                                      i32, (i32)0x80007F80, (i32)0x80000000>::value, "");
547fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::can_combine<Flagged<i32, i32, (i32)0xC0808040>,
548fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                                       i32, (i32)0x80007F80, (i32)0xC0000000>::value, "");
549fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
550fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::min_shift<Flagged<i32, FLAG, (FLAG)0x80808040>,
551fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                                    FLAG, (FLAG)0x80007F80, (FLAG)0x80000000>::value == 0, "");
552fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(helper::can_combine<Flagged<i32, FLAG, (FLAG)0x80808040>,
553fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar                                      FLAG, (FLAG)0x80007F80, (FLAG)0x80000000>::value, "");
554fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
555fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // cannot combine non-tagged types
556fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::can_combine<i32, u32, 0u, 0u>::value, "");
557fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::can_combine<u32, u32, 0u, 0u>::value, "");
558fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::can_combine<i32, u32, 0u, 0u>::value, "");
559fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::can_combine<i32, u32, 0u, 1u>::value, "");
560fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::can_combine<i32, u32, 1u, 0u>::value, "");
561fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!helper::can_combine<i32, u32, 1u, 1u>::value, "");
562fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
563fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef Flagged<i32_800f_0, u32, 0x800F /* mask */, 0 /* shared mask */> i32_800f_800f;
564fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(i32_800f_800f::sFlagMask == 0x800F, "");
565fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(i32_800f_800f::sFlagShift == 4, "");
566fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(i32_800f_800f::sEffectiveMask == 0x880FF, "");
567fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!i32_800f_0::sFlagCombined, "");
568fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!i32_800f_4::sFlagCombined, "");
569fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
570fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(i32_800f_800f::sFlagCombined, "");
571fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert_equals(sizeof(i32_800f_800f), sizeof(i32_800f_0), "");
572fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
573fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef Flagged<i32_800f_0, u32, 0x1FFFF /* mask */> i32_800f_1ffff;
574fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(i32_800f_1ffff::sFlagMask == 0x1FFFF, "");
575fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(i32_800f_1ffff::sFlagShift == 0, "");
576fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(i32_800f_1ffff::sEffectiveMask == 0x1FFFF, "");
577fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(!i32_800f_1ffff::sFlagCombined, "");
578fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
579fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // operational tests
580fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    i32_800f_800f val(0x8000, 0x1234, 56);
581fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(val.get().get(), 56);
582fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(val.flags(), 0x8000u);
583fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(val.get().flags(), 0x1234u & 0x800F);
584fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    val.setFlags(0x12345);
585fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(val.flags(), 0x12345u & 0x800F);
586fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(val.get().flags(), 0x1234u & 0x800F);
587fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    val.get().setFlags(0x54321);
588fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(val.flags(), 0x12345u & 0x800F);
589fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(val.get().flags(), 0x54321u & 0x800F);
590fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(val.get().get(), 56);
591fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
592fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef Flagged<i32_800f_4, u32, 0x800F /* mask */, 0 /* shared mask */> i32_800f_800f_B;
593fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(i32_800f_800f_B::sFlagMask == 0x800F, "");
594fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(i32_800f_800f_B::sFlagShift == 0, "");
595fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(i32_800f_800f_B::sEffectiveMask == 0x880FF, "");
596fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
597fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    i32_800f_800f_B valB(0x8000, 0x1234, -987);
598fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valB.get().get(), -987);
599fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valB.flags(), 0x8000u);
600fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valB.get().flags(), 0x1234u & 0x800F);
601fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    valB.setFlags(0x12345);
602fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valB.flags(), 0x12345u & 0x800F);
603fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valB.get().flags(), 0x1234u & 0x800F);
604fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    valB.get().setFlags(0x5C321);
605fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valB.flags(), 0x12345u & 0x800F);
606fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valB.get().flags(), 0x5C321u & 0x800F);
607fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valB.get().get(), -987);
608fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
609fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef Flagged<Flagged<i32, u32, 0xFF>, u32, 0xFF0, 0xF0> i32_ff_ff0;
610fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    i32_ff_ff0 valC(0xABCD, 0x1234, 101);
611fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valC.get().get(), 101);
612fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valC.flags(), 0xBC0u);
613fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valC.get().flags(), 0xC4u);
614fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    valC.setFlags(0x12345);
615fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valC.flags(), 0x340u);
616fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valC.get().flags(), 0x44u);
617fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    valC.get().setFlags(0x54321);
618fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valC.flags(), 0x320u);
619fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valC.get().flags(), 0x21u);
620fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valC.get().get(), 101);
621fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
622fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    // when combining flags (with no shift), it should work with signed flags
623fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    typedef Flagged<Flagged<i32, FLAG, kMask0>, FLAG, kMask1, kMaskCommon> i32_F_ff_ff0;
624fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    static_assert(i32_F_ff_ff0::sFlagCombined, "flags should be combined");
625fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
626fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    i32_F_ff_ff0 valD(kFlag1_A, kFlag0_A, 1023);
627fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valD.get().get(), 1023);
628fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valD.flags(), kFlag1_A);
629fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valD.get().flags(), kFlag0_A);
630fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    valD.setFlags(kFlag1_B);
631fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valD.flags(), kFlag1_B);
632fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valD.get().flags(), FLAG(0x0BA));
633fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    valD.get().setFlags(kFlag0_C);
634fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valD.flags(), FLAG(0xBC0));
635fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valD.get().flags(), kFlag0_C);
636fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar    EXPECT_EQ(valD.get().get(), 1023);
637fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar}
638fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar
639fba972f9d7f87c47ac0820b7f99420acc7e5dc36Lajos Molnar} // namespace android
640