tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestTypedEnum.cpp (18992B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/Assertions.h"
      8 #include "mozilla/TypedEnumBits.h"
      9 
     10 #include <stdint.h>
     11 #include <type_traits>
     12 
     13 // A rough feature check for is_literal_type. Not very carefully checked.
     14 // Feel free to amend as needed. is_literal_type was removed in C++20.
     15 // We leave ANDROID out because it's using stlport which doesn't have
     16 // std::is_literal_type.
     17 #if __cplusplus >= 201103L && __cplusplus < 202002L && !defined(ANDROID)
     18 #  if defined(__clang__)
     19 /*
     20 * Per Clang documentation, "Note that marketing version numbers should not
     21 * be used to check for language features, as different vendors use different
     22 * numbering schemes. Instead, use the feature checking macros."
     23 */
     24 #    ifndef __has_extension
     25 #      define __has_extension \
     26        __has_feature /* compatibility, for older versions of clang */
     27 #    endif
     28 #    if __has_extension(is_literal) && __has_include(<type_traits>)
     29 #      define MOZ_HAVE_IS_LITERAL
     30 #    endif
     31 #  elif defined(__GNUC__) || defined(_MSC_VER)
     32 #    define MOZ_HAVE_IS_LITERAL
     33 #  endif
     34 #endif
     35 
     36 #if defined(MOZ_HAVE_IS_LITERAL) && defined(MOZ_HAVE_CXX11_CONSTEXPR)
     37 #  include <type_traits>
     38 template <typename T>
     39 void RequireLiteralType() {
     40  static_assert(std::is_literal_type<T>::value, "Expected a literal type");
     41 }
     42 #else  // not MOZ_HAVE_IS_LITERAL
     43 template <typename T>
     44 void RequireLiteralType() {}
     45 #endif
     46 
     47 template <typename T>
     48 void RequireLiteralType(const T&) {
     49  RequireLiteralType<T>();
     50 }
     51 
     52 enum class AutoEnum { A, B = -3, C };
     53 
     54 enum class CharEnum : char { A, B = 3, C };
     55 
     56 enum class AutoEnumBitField { A = 0x10, B = 0x20, C };
     57 
     58 enum class CharEnumBitField : char { A = 0x10, B, C = 0x40 };
     59 
     60 struct Nested {
     61  enum class AutoEnum { A, B, C = -1 };
     62 
     63  enum class CharEnum : char { A = 4, B, C = 1 };
     64 
     65  enum class AutoEnumBitField { A, B = 0x20, C };
     66 
     67  enum class CharEnumBitField : char { A = 1, B = 1, C = 1 };
     68 };
     69 
     70 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(AutoEnumBitField)
     71 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(CharEnumBitField)
     72 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Nested::AutoEnumBitField)
     73 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Nested::CharEnumBitField)
     74 
     75 #define MAKE_STANDARD_BITFIELD_FOR_TYPE(IntType) \
     76  enum class BitFieldFor_##IntType : IntType{    \
     77      A = 1,                                     \
     78      B = 2,                                     \
     79      C = 4,                                     \
     80  };                                             \
     81  MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(BitFieldFor_##IntType)
     82 
     83 MAKE_STANDARD_BITFIELD_FOR_TYPE(int8_t)
     84 MAKE_STANDARD_BITFIELD_FOR_TYPE(uint8_t)
     85 MAKE_STANDARD_BITFIELD_FOR_TYPE(int16_t)
     86 MAKE_STANDARD_BITFIELD_FOR_TYPE(uint16_t)
     87 MAKE_STANDARD_BITFIELD_FOR_TYPE(int32_t)
     88 MAKE_STANDARD_BITFIELD_FOR_TYPE(uint32_t)
     89 MAKE_STANDARD_BITFIELD_FOR_TYPE(int64_t)
     90 MAKE_STANDARD_BITFIELD_FOR_TYPE(uint64_t)
     91 MAKE_STANDARD_BITFIELD_FOR_TYPE(char)
     92 typedef signed char signed_char;
     93 MAKE_STANDARD_BITFIELD_FOR_TYPE(signed_char)
     94 typedef unsigned char unsigned_char;
     95 MAKE_STANDARD_BITFIELD_FOR_TYPE(unsigned_char)
     96 MAKE_STANDARD_BITFIELD_FOR_TYPE(short)
     97 typedef unsigned short unsigned_short;
     98 MAKE_STANDARD_BITFIELD_FOR_TYPE(unsigned_short)
     99 MAKE_STANDARD_BITFIELD_FOR_TYPE(int)
    100 typedef unsigned int unsigned_int;
    101 MAKE_STANDARD_BITFIELD_FOR_TYPE(unsigned_int)
    102 MAKE_STANDARD_BITFIELD_FOR_TYPE(long)
    103 typedef unsigned long unsigned_long;
    104 MAKE_STANDARD_BITFIELD_FOR_TYPE(unsigned_long)
    105 typedef long long long_long;
    106 MAKE_STANDARD_BITFIELD_FOR_TYPE(long_long)
    107 typedef unsigned long long unsigned_long_long;
    108 MAKE_STANDARD_BITFIELD_FOR_TYPE(unsigned_long_long)
    109 
    110 #undef MAKE_STANDARD_BITFIELD_FOR_TYPE
    111 
    112 template <typename T>
    113 void TestNonConvertibilityForOneType() {
    114  static_assert(!std::is_convertible_v<T, bool>, "should not be convertible");
    115  static_assert(!std::is_convertible_v<T, int>, "should not be convertible");
    116  static_assert(!std::is_convertible_v<T, uint64_t>,
    117                "should not be convertible");
    118 
    119  static_assert(!std::is_convertible_v<bool, T>, "should not be convertible");
    120  static_assert(!std::is_convertible_v<int, T>, "should not be convertible");
    121  static_assert(!std::is_convertible_v<uint64_t, T>,
    122                "should not be convertible");
    123 }
    124 
    125 template <typename TypedEnum>
    126 void TestTypedEnumBasics() {
    127  const TypedEnum a = TypedEnum::A;
    128  int unused = int(a);
    129  (void)unused;
    130  RequireLiteralType(TypedEnum::A);
    131  RequireLiteralType(a);
    132  TestNonConvertibilityForOneType<TypedEnum>();
    133 }
    134 
    135 // Op wraps a bitwise binary operator, passed as a char template parameter,
    136 // and applies it to its arguments (aT1, aT2). For example,
    137 //
    138 //   Op<'|'>(aT1, aT2)
    139 //
    140 // is the same as
    141 //
    142 //   aT1 | aT2.
    143 //
    144 template <char o, typename T1, typename T2>
    145 auto Op(const T1& aT1, const T2& aT2)
    146    -> decltype(aT1 | aT2)  // See the static_assert's below --- the return type
    147                            // depends solely on the operands type, not on the
    148                            // choice of operation.
    149 {
    150  static_assert(std::is_same_v<decltype(aT1 | aT2), decltype(aT1 & aT2)>,
    151                "binary ops should have the same result type");
    152  static_assert(std::is_same_v<decltype(aT1 | aT2), decltype(aT1 ^ aT2)>,
    153                "binary ops should have the same result type");
    154 
    155  static_assert(o == '|' || o == '&' || o == '^',
    156                "unexpected operator character");
    157 
    158  return o == '|' ? aT1 | aT2 : o == '&' ? aT1 & aT2 : aT1 ^ aT2;
    159 }
    160 
    161 // OpAssign wraps a bitwise binary operator, passed as a char template
    162 // parameter, and applies the corresponding compound-assignment operator to its
    163 // arguments (aT1, aT2). For example,
    164 //
    165 //   OpAssign<'|'>(aT1, aT2)
    166 //
    167 // is the same as
    168 //
    169 //   aT1 |= aT2.
    170 //
    171 template <char o, typename T1, typename T2>
    172 T1& OpAssign(T1& aT1, const T2& aT2) {
    173  static_assert(o == '|' || o == '&' || o == '^',
    174                "unexpected operator character");
    175 
    176  switch (o) {
    177    case '|':
    178      return aT1 |= aT2;
    179    case '&':
    180      return aT1 &= aT2;
    181    case '^':
    182      return aT1 ^= aT2;
    183    default:
    184      MOZ_CRASH();
    185  }
    186 }
    187 
    188 // Tests a single binary bitwise operator, using a single set of three operands.
    189 // The operations tested are:
    190 //
    191 //   result = aT1 Op aT2;
    192 //   result Op= aT3;
    193 //
    194 // Where Op is the operator specified by the char template parameter 'o' and
    195 // can be any of '|', '&', '^'.
    196 //
    197 // Note that the operands aT1, aT2, aT3 are intentionally passed with free
    198 // types (separate template parameters for each) because their type may
    199 // actually be different from TypedEnum:
    200 //
    201 //   1) Their type could be CastableTypedEnumResult<TypedEnum> if they are
    202 //      the result of a bitwise operation themselves;
    203 //   2) In the non-c++11 legacy path, the type of enum values is also
    204 //      different from TypedEnum.
    205 //
    206 template <typename TypedEnum, char o, typename T1, typename T2, typename T3>
    207 void TestBinOp(const T1& aT1, const T2& aT2, const T3& aT3) {
    208  typedef typename mozilla::detail::UnsignedIntegerTypeForEnum<TypedEnum>::Type
    209      UnsignedIntegerType;
    210 
    211  // Part 1:
    212  // Test the bitwise binary operator i.e.
    213  //   result = aT1 Op aT2;
    214  auto result = Op<o>(aT1, aT2);
    215 
    216  typedef decltype(result) ResultType;
    217 
    218  RequireLiteralType<ResultType>();
    219  TestNonConvertibilityForOneType<ResultType>();
    220 
    221  UnsignedIntegerType unsignedIntegerResult =
    222      Op<o>(UnsignedIntegerType(aT1), UnsignedIntegerType(aT2));
    223 
    224  MOZ_RELEASE_ASSERT(unsignedIntegerResult == UnsignedIntegerType(result));
    225  MOZ_RELEASE_ASSERT(TypedEnum(unsignedIntegerResult) == TypedEnum(result));
    226  MOZ_RELEASE_ASSERT((!unsignedIntegerResult) == (!result));
    227  MOZ_RELEASE_ASSERT((!!unsignedIntegerResult) == (!!result));
    228  MOZ_RELEASE_ASSERT(bool(unsignedIntegerResult) == bool(result));
    229 
    230  // Part 2:
    231  // Test the compound-assignment operator, i.e.
    232  //   result Op= aT3;
    233  TypedEnum newResult = result;
    234  OpAssign<o>(newResult, aT3);
    235  UnsignedIntegerType unsignedIntegerNewResult = unsignedIntegerResult;
    236  OpAssign<o>(unsignedIntegerNewResult, UnsignedIntegerType(aT3));
    237  MOZ_RELEASE_ASSERT(TypedEnum(unsignedIntegerNewResult) == newResult);
    238 
    239  // Part 3:
    240  // Test additional boolean operators that we unfortunately had to add to
    241  // CastableTypedEnumResult at some point to please some compiler,
    242  // even though bool convertibility should have been enough.
    243  MOZ_RELEASE_ASSERT(result == TypedEnum(result));
    244  MOZ_RELEASE_ASSERT(!(result != TypedEnum(result)));
    245  MOZ_RELEASE_ASSERT((result && true) == bool(result));
    246  MOZ_RELEASE_ASSERT((result && false) == false);
    247  MOZ_RELEASE_ASSERT((true && result) == bool(result));
    248  MOZ_RELEASE_ASSERT((false && result && false) == false);
    249  MOZ_RELEASE_ASSERT((result || false) == bool(result));
    250  MOZ_RELEASE_ASSERT((result || true) == true);
    251  MOZ_RELEASE_ASSERT((false || result) == bool(result));
    252  MOZ_RELEASE_ASSERT((true || result) == true);
    253 
    254  // Part 4:
    255  // Test short-circuit evaluation.
    256  auto Explode = [] {
    257    // This function should never be called. Return an arbitrary value.
    258    MOZ_RELEASE_ASSERT(false);
    259    return false;
    260  };
    261  if (result) {
    262    MOZ_RELEASE_ASSERT(result || Explode());
    263    MOZ_RELEASE_ASSERT(!(!result && Explode()));
    264  } else {
    265    MOZ_RELEASE_ASSERT(!(result && Explode()));
    266    MOZ_RELEASE_ASSERT(!result || Explode());
    267  }
    268 }
    269 
    270 // Similar to TestBinOp but testing the unary ~ operator.
    271 template <typename TypedEnum, typename T>
    272 void TestTilde(const T& aT) {
    273  typedef typename mozilla::detail::UnsignedIntegerTypeForEnum<TypedEnum>::Type
    274      UnsignedIntegerType;
    275 
    276  auto result = ~aT;
    277 
    278  typedef decltype(result) ResultType;
    279 
    280  RequireLiteralType<ResultType>();
    281  TestNonConvertibilityForOneType<ResultType>();
    282 
    283  UnsignedIntegerType unsignedIntegerResult = ~(UnsignedIntegerType(aT));
    284 
    285  MOZ_RELEASE_ASSERT(unsignedIntegerResult == UnsignedIntegerType(result));
    286  MOZ_RELEASE_ASSERT(TypedEnum(unsignedIntegerResult) == TypedEnum(result));
    287  MOZ_RELEASE_ASSERT((!unsignedIntegerResult) == (!result));
    288  MOZ_RELEASE_ASSERT((!!unsignedIntegerResult) == (!!result));
    289  MOZ_RELEASE_ASSERT(bool(unsignedIntegerResult) == bool(result));
    290 }
    291 
    292 // Helper dispatching a given triple of operands to all operator-specific
    293 // testing functions.
    294 template <typename TypedEnum, typename T1, typename T2, typename T3>
    295 void TestAllOpsForGivenOperands(const T1& aT1, const T2& aT2, const T3& aT3) {
    296  TestBinOp<TypedEnum, '|'>(aT1, aT2, aT3);
    297  TestBinOp<TypedEnum, '&'>(aT1, aT2, aT3);
    298  TestBinOp<TypedEnum, '^'>(aT1, aT2, aT3);
    299  TestTilde<TypedEnum>(aT1);
    300 }
    301 
    302 // Helper building various triples of operands using a given operator,
    303 // and testing all operators with them.
    304 template <typename TypedEnum, char o>
    305 void TestAllOpsForOperandsBuiltUsingGivenOp() {
    306  // The type of enum values like TypedEnum::A may be different from
    307  // TypedEnum. That is the case in the legacy non-C++11 path. We want to
    308  // ensure good test coverage even when these two types are distinct.
    309  // To that effect, we have both 'auto' typed variables, preserving the
    310  // original type of enum values, and 'plain' typed variables, that
    311  // are plain TypedEnum's.
    312 
    313  const TypedEnum a_plain = TypedEnum::A;
    314  const TypedEnum b_plain = TypedEnum::B;
    315  const TypedEnum c_plain = TypedEnum::C;
    316 
    317  auto a_auto = TypedEnum::A;
    318  auto b_auto = TypedEnum::B;
    319  auto c_auto = TypedEnum::C;
    320 
    321  auto ab_plain = Op<o>(a_plain, b_plain);
    322  auto bc_plain = Op<o>(b_plain, c_plain);
    323  auto ab_auto = Op<o>(a_auto, b_auto);
    324  auto bc_auto = Op<o>(b_auto, c_auto);
    325 
    326  // On each row below, we pass a triple of operands. Keep in mind that this
    327  // is going to be received as (aT1, aT2, aT3) and the actual tests performed
    328  // will be of the form
    329  //
    330  //   result = aT1 Op aT2;
    331  //   result Op= aT3;
    332  //
    333  // For this reason, we carefully ensure that the values of (aT1, aT2)
    334  // systematically cover all types of such pairs; to limit complexity,
    335  // we are not so careful with aT3, and we just try to pass aT3's
    336  // that may lead to nontrivial bitwise operations.
    337  TestAllOpsForGivenOperands<TypedEnum>(a_plain, b_plain, c_plain);
    338  TestAllOpsForGivenOperands<TypedEnum>(a_plain, bc_plain, b_auto);
    339  TestAllOpsForGivenOperands<TypedEnum>(ab_plain, c_plain, a_plain);
    340  TestAllOpsForGivenOperands<TypedEnum>(ab_plain, bc_plain, a_auto);
    341 
    342  TestAllOpsForGivenOperands<TypedEnum>(a_plain, b_auto, c_plain);
    343  TestAllOpsForGivenOperands<TypedEnum>(a_plain, bc_auto, b_auto);
    344  TestAllOpsForGivenOperands<TypedEnum>(ab_plain, c_auto, a_plain);
    345  TestAllOpsForGivenOperands<TypedEnum>(ab_plain, bc_auto, a_auto);
    346 
    347  TestAllOpsForGivenOperands<TypedEnum>(a_auto, b_plain, c_plain);
    348  TestAllOpsForGivenOperands<TypedEnum>(a_auto, bc_plain, b_auto);
    349  TestAllOpsForGivenOperands<TypedEnum>(ab_auto, c_plain, a_plain);
    350  TestAllOpsForGivenOperands<TypedEnum>(ab_auto, bc_plain, a_auto);
    351 
    352  TestAllOpsForGivenOperands<TypedEnum>(a_auto, b_auto, c_plain);
    353  TestAllOpsForGivenOperands<TypedEnum>(a_auto, bc_auto, b_auto);
    354  TestAllOpsForGivenOperands<TypedEnum>(ab_auto, c_auto, a_plain);
    355  TestAllOpsForGivenOperands<TypedEnum>(ab_auto, bc_auto, a_auto);
    356 }
    357 
    358 // Tests all bitwise operations on a given TypedEnum bitfield.
    359 template <typename TypedEnum>
    360 void TestTypedEnumBitField() {
    361  TestTypedEnumBasics<TypedEnum>();
    362 
    363  TestAllOpsForOperandsBuiltUsingGivenOp<TypedEnum, '|'>();
    364  TestAllOpsForOperandsBuiltUsingGivenOp<TypedEnum, '&'>();
    365  TestAllOpsForOperandsBuiltUsingGivenOp<TypedEnum, '^'>();
    366 }
    367 
    368 // Checks that enum bitwise expressions have the same non-convertibility
    369 // properties as c++11 enum classes do, i.e. not implicitly convertible to
    370 // anything (though *explicitly* convertible).
    371 void TestNoConversionsBetweenUnrelatedTypes() {
    372  // Two typed enum classes having the same underlying integer type, to ensure
    373  // that we would catch bugs accidentally allowing conversions in that case.
    374  typedef CharEnumBitField T1;
    375  typedef Nested::CharEnumBitField T2;
    376 
    377  static_assert(!std::is_convertible_v<T1, T2>, "should not be convertible");
    378  static_assert(!std::is_convertible_v<T1, decltype(T2::A)>,
    379                "should not be convertible");
    380  static_assert(!std::is_convertible_v<T1, decltype(T2::A | T2::B)>,
    381                "should not be convertible");
    382 
    383  static_assert(!std::is_convertible_v<decltype(T1::A), T2>,
    384                "should not be convertible");
    385  static_assert(!std::is_convertible_v<decltype(T1::A), decltype(T2::A)>,
    386                "should not be convertible");
    387  static_assert(
    388      !std::is_convertible_v<decltype(T1::A), decltype(T2::A | T2::B)>,
    389      "should not be convertible");
    390 
    391  static_assert(!std::is_convertible_v<decltype(T1::A | T1::B), T2>,
    392                "should not be convertible");
    393  static_assert(
    394      !std::is_convertible_v<decltype(T1::A | T1::B), decltype(T2::A)>,
    395      "should not be convertible");
    396  static_assert(
    397      !std::is_convertible_v<decltype(T1::A | T1::B), decltype(T2::A | T2::B)>,
    398      "should not be convertible");
    399 }
    400 
    401 enum class Int8EnumWithHighBits : int8_t { A = 0x20, B = 0x40 };
    402 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Int8EnumWithHighBits)
    403 
    404 enum class Uint8EnumWithHighBits : uint8_t { A = 0x40, B = 0x80 };
    405 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Uint8EnumWithHighBits)
    406 
    407 enum class Int16EnumWithHighBits : int16_t { A = 0x2000, B = 0x4000 };
    408 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Int16EnumWithHighBits)
    409 
    410 enum class Uint16EnumWithHighBits : uint16_t { A = 0x4000, B = 0x8000 };
    411 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Uint16EnumWithHighBits)
    412 
    413 enum class Int32EnumWithHighBits : int32_t { A = 0x20000000, B = 0x40000000 };
    414 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Int32EnumWithHighBits)
    415 
    416 enum class Uint32EnumWithHighBits : uint32_t {
    417  A = 0x40000000u,
    418  B = 0x80000000u
    419 };
    420 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Uint32EnumWithHighBits)
    421 
    422 enum class Int64EnumWithHighBits : int64_t {
    423  A = 0x2000000000000000ll,
    424  B = 0x4000000000000000ll
    425 };
    426 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Int64EnumWithHighBits)
    427 
    428 enum class Uint64EnumWithHighBits : uint64_t {
    429  A = 0x4000000000000000ull,
    430  B = 0x8000000000000000ull
    431 };
    432 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Uint64EnumWithHighBits)
    433 
    434 // Checks that we don't accidentally truncate high bits by coercing to the wrong
    435 // integer type internally when implementing bitwise ops.
    436 template <typename EnumType, typename IntType>
    437 void TestIsNotTruncated() {
    438  EnumType a = EnumType::A;
    439  EnumType b = EnumType::B;
    440  MOZ_RELEASE_ASSERT(IntType(a));
    441  MOZ_RELEASE_ASSERT(IntType(b));
    442  MOZ_RELEASE_ASSERT(a | EnumType::B);
    443  MOZ_RELEASE_ASSERT(a | b);
    444  MOZ_RELEASE_ASSERT(EnumType::A | EnumType::B);
    445  EnumType c = EnumType::A | EnumType::B;
    446  MOZ_RELEASE_ASSERT(IntType(c));
    447  MOZ_RELEASE_ASSERT(c & c);
    448  MOZ_RELEASE_ASSERT(c | c);
    449  MOZ_RELEASE_ASSERT(c == (EnumType::A | EnumType::B));
    450  MOZ_RELEASE_ASSERT(a != (EnumType::A | EnumType::B));
    451  MOZ_RELEASE_ASSERT(b != (EnumType::A | EnumType::B));
    452  MOZ_RELEASE_ASSERT(c & EnumType::A);
    453  MOZ_RELEASE_ASSERT(c & EnumType::B);
    454  EnumType d = EnumType::A;
    455  d |= EnumType::B;
    456  MOZ_RELEASE_ASSERT(d == c);
    457 }
    458 
    459 int main() {
    460  TestTypedEnumBasics<AutoEnum>();
    461  TestTypedEnumBasics<CharEnum>();
    462  TestTypedEnumBasics<Nested::AutoEnum>();
    463  TestTypedEnumBasics<Nested::CharEnum>();
    464 
    465  TestTypedEnumBitField<AutoEnumBitField>();
    466  TestTypedEnumBitField<CharEnumBitField>();
    467  TestTypedEnumBitField<Nested::AutoEnumBitField>();
    468  TestTypedEnumBitField<Nested::CharEnumBitField>();
    469 
    470  TestTypedEnumBitField<BitFieldFor_uint8_t>();
    471  TestTypedEnumBitField<BitFieldFor_int8_t>();
    472  TestTypedEnumBitField<BitFieldFor_uint16_t>();
    473  TestTypedEnumBitField<BitFieldFor_int16_t>();
    474  TestTypedEnumBitField<BitFieldFor_uint32_t>();
    475  TestTypedEnumBitField<BitFieldFor_int32_t>();
    476  TestTypedEnumBitField<BitFieldFor_uint64_t>();
    477  TestTypedEnumBitField<BitFieldFor_int64_t>();
    478  TestTypedEnumBitField<BitFieldFor_char>();
    479  TestTypedEnumBitField<BitFieldFor_signed_char>();
    480  TestTypedEnumBitField<BitFieldFor_unsigned_char>();
    481  TestTypedEnumBitField<BitFieldFor_short>();
    482  TestTypedEnumBitField<BitFieldFor_unsigned_short>();
    483  TestTypedEnumBitField<BitFieldFor_int>();
    484  TestTypedEnumBitField<BitFieldFor_unsigned_int>();
    485  TestTypedEnumBitField<BitFieldFor_long>();
    486  TestTypedEnumBitField<BitFieldFor_unsigned_long>();
    487  TestTypedEnumBitField<BitFieldFor_long_long>();
    488  TestTypedEnumBitField<BitFieldFor_unsigned_long_long>();
    489 
    490  TestNoConversionsBetweenUnrelatedTypes();
    491 
    492  TestIsNotTruncated<Int8EnumWithHighBits, int8_t>();
    493  TestIsNotTruncated<Int16EnumWithHighBits, int16_t>();
    494  TestIsNotTruncated<Int32EnumWithHighBits, int32_t>();
    495  TestIsNotTruncated<Int64EnumWithHighBits, int64_t>();
    496  TestIsNotTruncated<Uint8EnumWithHighBits, uint8_t>();
    497  TestIsNotTruncated<Uint16EnumWithHighBits, uint16_t>();
    498  TestIsNotTruncated<Uint32EnumWithHighBits, uint32_t>();
    499  TestIsNotTruncated<Uint64EnumWithHighBits, uint64_t>();
    500 
    501  return 0;
    502 }