mfbt/tests/TestTypedEnum.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial