Home | History | Annotate | Line # | Download | only in unittests
      1 /* Self tests for enum-flags for GDB, the GNU debugger.
      2 
      3    Copyright (C) 2016-2024 Free Software Foundation, Inc.
      4 
      5    This file is part of GDB.
      6 
      7    This program is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3 of the License, or
     10    (at your option) any later version.
     11 
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19 
     20 #include "gdbsupport/enum-flags.h"
     21 #include "gdbsupport/valid-expr.h"
     22 #include "gdbsupport/selftest.h"
     23 
     24 namespace selftests {
     25 namespace enum_flags_tests {
     26 
     27 /* The (real) enum types used in CHECK_VALID.  Their names match the
     28    template parameter names of the templates defined by CHECK_VALID to
     29    make it simpler to use.  They could be named differently.  */
     30 
     31 /* A "real enum".  */
     32 enum RE
     33   {
     34     RE_FLAG1 = 1 << 1,
     35     RE_FLAG2 = 1 << 2,
     36   };
     37 
     38 /* Another "real enum".  */
     39 enum RE2
     40   {
     41     RE2_FLAG1 = 1 << 1,
     42     RE2_FLAG2 = 1 << 2,
     43   };
     44 
     45 /* An unsigned "real enum".  */
     46 enum URE : unsigned
     47   {
     48     URE_FLAG1 = 1 << 1,
     49     URE_FLAG2 = 1 << 2,
     50     URE_FLAG3 = 0xffffffff,
     51   };
     52 
     53 /* A non-flags enum.  */
     54 enum NF
     55   {
     56     NF_FLAG1 = 1 << 1,
     57     NF_FLAG2 = 1 << 2,
     58   };
     59 
     60 /* The corresponding "enum flags" types.  */
     61 DEF_ENUM_FLAGS_TYPE (RE, EF);
     62 DEF_ENUM_FLAGS_TYPE (RE2, EF2);
     63 DEF_ENUM_FLAGS_TYPE (URE, UEF);
     64 
     65 /* So that std::vectors of types that have enum_flags fields can
     66    reallocate efficiently memcpy.  */
     67 static_assert (std::is_trivially_copyable<EF>::value);
     68 
     69 /* A couple globals used as lvalues in the CHECK_VALID expressions
     70    below.  Their names (and types) match the uppercase type names
     71    exposed by CHECK_VALID just to make the expressions easier to
     72    follow.  */
     73 static RE re ATTRIBUTE_UNUSED;
     74 static EF ef ATTRIBUTE_UNUSED;
     75 
     76 /* First, compile-time tests that:
     77 
     78    - make sure that incorrect operations with mismatching enum types
     79      are caught at compile time.
     80 
     81    - make sure that the same operations but involving the right enum
     82      types do compile and that they return the correct type.
     83 */
     84 
     85 #define CHECK_VALID(VALID, EXPR_TYPE, EXPR)		\
     86   CHECK_VALID_EXPR_6 (EF, RE, EF2, RE2, UEF, URE, VALID, EXPR_TYPE, EXPR)
     87 
     88 typedef std::underlying_type<RE>::type und;
     89 
     90 /* Test construction / conversion from/to different types.  */
     91 
     92 /* RE/EF -> underlying (explicit) */
     93 CHECK_VALID (true,  und,  und (RE ()))
     94 CHECK_VALID (true,  und,  und (EF ()))
     95 
     96 /* RE/EF -> int (explicit) */
     97 CHECK_VALID (true,  int,  int (RE ()))
     98 CHECK_VALID (true,  int,  int (EF ()))
     99 
    100 /* other -> RE */
    101 
    102 /* You can construct a raw enum value from an int explicitly to punch
    103    a hole in the type system if need to.  */
    104 CHECK_VALID (true,  RE,   RE (1))
    105 CHECK_VALID (true,  RE,   RE (RE2 ()))
    106 CHECK_VALID (false, void, RE (EF2 ()))
    107 CHECK_VALID (true,  RE,   RE (RE ()))
    108 CHECK_VALID (false, void, RE (EF ()))
    109 
    110 /* other -> EF.  */
    111 
    112 /* As expected, enum-flags is a stronger type than the backing raw
    113    enum.  Unlike with raw enums, you can't construct an enum flags
    114    from an integer nor from an unrelated enum type explicitly.  Add an
    115    intermediate conversion via the raw enum if you really need it.  */
    116 CHECK_VALID (false, void, EF (1))
    117 CHECK_VALID (false, void, EF (1u))
    118 CHECK_VALID (false, void, EF (RE2 ()))
    119 CHECK_VALID (false, void, EF (EF2 ()))
    120 CHECK_VALID (true,  EF,   EF (RE ()))
    121 CHECK_VALID (true,  EF,   EF (EF ()))
    122 
    123 /* Test operators.  */
    124 
    125 /* operator OP (raw_enum, int) */
    126 
    127 CHECK_VALID (false, void, RE () | 1)
    128 CHECK_VALID (false, void, RE () & 1)
    129 CHECK_VALID (false, void, RE () ^ 1)
    130 
    131 /* operator OP (int, raw_enum) */
    132 
    133 CHECK_VALID (false, void, 1 | RE ())
    134 CHECK_VALID (false, void, 1 & RE ())
    135 CHECK_VALID (false, void, 1 ^ RE ())
    136 
    137 /* operator OP (enum_flags, int) */
    138 
    139 CHECK_VALID (false, void, EF () | 1)
    140 CHECK_VALID (false, void, EF () & 1)
    141 CHECK_VALID (false, void, EF () ^ 1)
    142 
    143 /* operator OP (int, enum_flags) */
    144 
    145 CHECK_VALID (false, void, 1 | EF ())
    146 CHECK_VALID (false, void, 1 & EF ())
    147 CHECK_VALID (false, void, 1 ^ EF ())
    148 
    149 /* operator OP (raw_enum, raw_enum) */
    150 
    151 CHECK_VALID (false, void, RE () | RE2 ())
    152 CHECK_VALID (false, void, RE () & RE2 ())
    153 CHECK_VALID (false, void, RE () ^ RE2 ())
    154 CHECK_VALID (true,  RE,   RE () | RE ())
    155 CHECK_VALID (true,  RE,   RE () & RE ())
    156 CHECK_VALID (true,  RE,   RE () ^ RE ())
    157 
    158 /* operator OP (enum_flags, raw_enum) */
    159 
    160 CHECK_VALID (false, void, EF () | RE2 ())
    161 CHECK_VALID (false, void, EF () & RE2 ())
    162 CHECK_VALID (false, void, EF () ^ RE2 ())
    163 CHECK_VALID (true,  EF,   EF () | RE ())
    164 CHECK_VALID (true,  EF,   EF () & RE ())
    165 CHECK_VALID (true,  EF,   EF () ^ RE ())
    166 
    167 /* operator OP= (raw_enum, raw_enum), rvalue ref on the lhs. */
    168 
    169 CHECK_VALID (false, void, RE () |= RE2 ())
    170 CHECK_VALID (false, void, RE () &= RE2 ())
    171 CHECK_VALID (false, void, RE () ^= RE2 ())
    172 CHECK_VALID (false, void, RE () |= RE ())
    173 CHECK_VALID (false, void, RE () &= RE ())
    174 CHECK_VALID (false, void, RE () ^= RE ())
    175 
    176 /* operator OP= (raw_enum, raw_enum), lvalue ref on the lhs. */
    177 
    178 CHECK_VALID (false, void, re |= RE2 ())
    179 CHECK_VALID (false, void, re &= RE2 ())
    180 CHECK_VALID (false, void, re ^= RE2 ())
    181 CHECK_VALID (true,  RE&,  re |= RE ())
    182 CHECK_VALID (true,  RE&,  re &= RE ())
    183 CHECK_VALID (true,  RE&,  re ^= RE ())
    184 
    185 /* operator OP= (enum_flags, raw_enum), rvalue ref on the lhs.  */
    186 
    187 CHECK_VALID (false, void, EF () |= RE2 ())
    188 CHECK_VALID (false, void, EF () &= RE2 ())
    189 CHECK_VALID (false, void, EF () ^= RE2 ())
    190 CHECK_VALID (false, void, EF () |= RE ())
    191 CHECK_VALID (false, void, EF () &= RE ())
    192 CHECK_VALID (false, void, EF () ^= RE ())
    193 
    194 /* operator OP= (enum_flags, raw_enum), lvalue ref on the lhs.  */
    195 
    196 CHECK_VALID (false, void, ef |= RE2 ())
    197 CHECK_VALID (false, void, ef &= RE2 ())
    198 CHECK_VALID (false, void, ef ^= RE2 ())
    199 CHECK_VALID (true,  EF&,  ef |= EF ())
    200 CHECK_VALID (true,  EF&,  ef &= EF ())
    201 CHECK_VALID (true,  EF&,  ef ^= EF ())
    202 
    203 /* operator OP= (enum_flags, enum_flags), rvalue ref on the lhs.  */
    204 
    205 CHECK_VALID (false, void, EF () |= EF2 ())
    206 CHECK_VALID (false, void, EF () &= EF2 ())
    207 CHECK_VALID (false, void, EF () ^= EF2 ())
    208 CHECK_VALID (false, void, EF () |= EF ())
    209 CHECK_VALID (false, void, EF () &= EF ())
    210 CHECK_VALID (false, void, EF () ^= EF ())
    211 
    212 /* operator OP= (enum_flags, enum_flags), lvalue ref on the lhs.  */
    213 
    214 CHECK_VALID (false, void, ef |= EF2 ())
    215 CHECK_VALID (false, void, ef &= EF2 ())
    216 CHECK_VALID (false, void, ef ^= EF2 ())
    217 CHECK_VALID (true,  EF&,  ef |= EF ())
    218 CHECK_VALID (true,  EF&,  ef &= EF ())
    219 CHECK_VALID (true,  EF&,  ef ^= EF ())
    220 
    221 /* operator~ (raw_enum) */
    222 
    223 CHECK_VALID (false,  void,   ~RE ())
    224 CHECK_VALID (true,   URE,    ~URE ())
    225 
    226 /* operator~ (enum_flags) */
    227 
    228 CHECK_VALID (false,  void,   ~EF ())
    229 CHECK_VALID (true,   UEF,    ~UEF ())
    230 
    231 /* Check ternary operator.  This exercises implicit conversions.  */
    232 
    233 CHECK_VALID (true,  EF,   true ? EF () : RE ())
    234 CHECK_VALID (true,  EF,   true ? RE () : EF ())
    235 
    236 /* These are valid, but it's not a big deal since you won't be able to
    237    assign the resulting integer to an enum or an enum_flags without a
    238    cast.
    239 
    240    The latter two tests are disabled on older GCCs because they
    241    incorrectly fail with gcc 4.8 and 4.9 at least.  Running the test
    242    outside a SFINAE context shows:
    243 
    244     invalid user-defined conversion from EF to RE2
    245 
    246    They've been confirmed to compile/pass with gcc 5.3, gcc 7.1 and
    247    clang 3.7.  */
    248 
    249 CHECK_VALID (true,  int,  true ? EF () : EF2 ())
    250 CHECK_VALID (true,  int,  true ? EF2 () : EF ())
    251 CHECK_VALID (true,  int,  true ? EF () : RE2 ())
    252 CHECK_VALID (true,  int,  true ? RE2 () : EF ())
    253 
    254 /* Same, but with an unsigned enum.  */
    255 
    256 typedef unsigned int uns;
    257 
    258 CHECK_VALID (true,  uns,  true ? EF () : UEF ())
    259 CHECK_VALID (true,  uns,  true ? UEF () : EF ())
    260 CHECK_VALID (true,  uns,  true ? EF () : URE ())
    261 CHECK_VALID (true,  uns,  true ? URE () : EF ())
    262 
    263 /* Unfortunately this can't work due to the way C++ computes the
    264    return type of the ternary conditional operator.  int isn't
    265    implicitly convertible to the raw enum type, so the type of the
    266    expression is int.  And then int is not implicitly convertible to
    267    enum_flags.
    268 
    269    GCC 4.8 fails to compile this test with:
    270      error: operands to ?: have different types enum_flags<RE> and int
    271    Confirmed to work with gcc 4.9, 5.3 and clang 3.7.
    272 */
    273 CHECK_VALID (false, void, true ? EF () : 0)
    274 CHECK_VALID (false, void, true ? 0 : EF ())
    275 
    276 /* Check that the ++/--/<</>>/<<=/>>= operators are deleted.  */
    277 
    278 CHECK_VALID (false, void, RE ()++)
    279 CHECK_VALID (false, void, ++RE ())
    280 CHECK_VALID (false, void, --RE ())
    281 CHECK_VALID (false, void, RE ()--)
    282 
    283 CHECK_VALID (false, void, RE () << 1)
    284 CHECK_VALID (false, void, RE () >> 1)
    285 CHECK_VALID (false, void, EF () << 1)
    286 CHECK_VALID (false, void, EF () >> 1)
    287 
    288 CHECK_VALID (false, void, RE () <<= 1)
    289 CHECK_VALID (false, void, RE () >>= 1)
    290 CHECK_VALID (false, void, EF () <<= 1)
    291 CHECK_VALID (false, void, EF () >>= 1)
    292 
    293 /* Test comparison operators.  */
    294 
    295 CHECK_VALID (false, void, EF () == EF2 ())
    296 CHECK_VALID (false, void, EF () == RE2 ())
    297 CHECK_VALID (false, void, RE () == EF2 ())
    298 
    299 CHECK_VALID (true,  bool, EF (RE (1)) == EF (RE (1)))
    300 CHECK_VALID (true,  bool, EF (RE (1)) == RE (1))
    301 CHECK_VALID (true,  bool, RE (1)      == EF (RE (1)))
    302 
    303 CHECK_VALID (false, void, EF () != EF2 ())
    304 CHECK_VALID (false, void, EF () != RE2 ())
    305 CHECK_VALID (false, void, RE () != EF2 ())
    306 
    307 /* Disable -Wenum-compare due to:
    308 
    309    Clang:
    310 
    311     "error: comparison of two values with different enumeration types
    312     [-Werror,-Wenum-compare]"
    313 
    314    GCC:
    315 
    316     "error: comparison between enum selftests::enum_flags_tests::RE
    317      and enum selftests::enum_flags_tests::RE2
    318      [-Werror=enum-compare]"
    319 
    320    Not a big deal since misuses like these in GDB will be caught by
    321    -Werror anyway.  This check is here mainly for completeness.  */
    322 #if defined __GNUC__
    323 # pragma GCC diagnostic push
    324 # pragma GCC diagnostic ignored "-Wenum-compare"
    325 #endif
    326 CHECK_VALID (true,  bool, RE () == RE2 ())
    327 CHECK_VALID (true,  bool, RE () != RE2 ())
    328 #if defined __GNUC__
    329 # pragma GCC diagnostic pop
    330 #endif
    331 
    332 CHECK_VALID (true,  bool, EF (RE (1)) != EF (RE (2)))
    333 CHECK_VALID (true,  bool, EF (RE (1)) != RE (2))
    334 CHECK_VALID (true,  bool, RE (1)      != EF (RE (2)))
    335 
    336 CHECK_VALID (true,  bool, EF () == 0)
    337 
    338 /* Check we didn't disable/delete comparison between non-flags enums
    339    and unrelated types by mistake.  */
    340 CHECK_VALID (true,  bool, NF (1) == NF (1))
    341 CHECK_VALID (true,  bool, NF (1) == int (1))
    342 CHECK_VALID (true,  bool, NF (1) == char (1))
    343 
    344 /* -------------------------------------------------------------------- */
    345 
    346 /* Follows misc tests that exercise the API.  Some are compile time,
    347    when possible, others are run time.  */
    348 
    349 enum test_flag
    350   {
    351     FLAG1 = 1 << 0,
    352     FLAG2 = 1 << 1,
    353     FLAG3 = 1 << 2,
    354     FLAG4 = 1 << 3,
    355   };
    356 
    357 enum test_uflag : unsigned
    358   {
    359     UFLAG1 = 1 << 0,
    360     UFLAG2 = 1 << 1,
    361     UFLAG3 = 1 << 2,
    362     UFLAG4 = 1 << 3,
    363   };
    364 
    365 DEF_ENUM_FLAGS_TYPE (test_flag, test_flags);
    366 DEF_ENUM_FLAGS_TYPE (test_uflag, test_uflags);
    367 
    368 /* to_string enumerator->string mapping functions used to test
    369    enum_flags::to_string.  These intentionally miss mapping a couple
    370    enumerators each (xFLAG2, xFLAG4).  */
    371 
    372 static std::string
    373 to_string_flags (test_flags flags)
    374 {
    375   static constexpr test_flags::string_mapping mapping[] = {
    376     MAP_ENUM_FLAG (FLAG1),
    377     MAP_ENUM_FLAG (FLAG3),
    378   };
    379   return flags.to_string (mapping);
    380 }
    381 
    382 static std::string
    383 to_string_uflags (test_uflags flags)
    384 {
    385   static constexpr test_uflags::string_mapping mapping[] = {
    386     MAP_ENUM_FLAG (UFLAG1),
    387     MAP_ENUM_FLAG (UFLAG3),
    388   };
    389   return flags.to_string (mapping);
    390 }
    391 
    392 static void
    393 self_test ()
    394 {
    395   /* Check that default construction works.  */
    396   {
    397     constexpr test_flags f;
    398 
    399     static_assert (f == 0);
    400   }
    401 
    402   /* Check that assignment from zero works.  */
    403   {
    404     test_flags f (FLAG1);
    405 
    406     SELF_CHECK (f == FLAG1);
    407 
    408     f = 0;
    409 
    410     SELF_CHECK (f == 0);
    411   }
    412 
    413   /* Check that construction from zero works.  */
    414   {
    415     constexpr test_flags zero1 = 0;
    416     constexpr test_flags zero2 (0);
    417     constexpr test_flags zero3 {0};
    418     constexpr test_flags zero4 = {0};
    419 
    420     static_assert (zero1 == 0);
    421     static_assert (zero2 == 0);
    422     static_assert (zero3 == 0);
    423     static_assert (zero4 == 0);
    424   }
    425 
    426   /* Check construction from enum value.  */
    427   {
    428     static_assert (test_flags (FLAG1) == FLAG1);
    429     static_assert (test_flags (FLAG2) != FLAG1);
    430   }
    431 
    432   /* Check copy/assignment.  */
    433   {
    434     constexpr test_flags src = FLAG1;
    435 
    436     constexpr test_flags f1 = src;
    437     constexpr test_flags f2 (src);
    438     constexpr test_flags f3 {src};
    439     constexpr test_flags f4 = {src};
    440 
    441     static_assert (f1 == FLAG1);
    442     static_assert (f2 == FLAG1);
    443     static_assert (f3 == FLAG1);
    444     static_assert (f4 == FLAG1);
    445   }
    446 
    447   /* Check moving.  */
    448   {
    449     test_flags src = FLAG1;
    450     test_flags dst = 0;
    451 
    452     dst = std::move (src);
    453     SELF_CHECK (dst == FLAG1);
    454   }
    455 
    456   /* Check construction from an 'or' of multiple bits.  For this to
    457      work, operator| must be overridden to return an enum type.  The
    458      builtin version would return int instead and then the conversion
    459      to test_flags would fail.  */
    460   {
    461     constexpr test_flags f = FLAG1 | FLAG2;
    462     static_assert (f == (FLAG1 | FLAG2));
    463   }
    464 
    465   /* Similarly, check that "FLAG1 | FLAG2" on the rhs of an assignment
    466      operator works.  */
    467   {
    468     test_flags f = 0;
    469     f |= FLAG1 | FLAG2;
    470     SELF_CHECK (f == (FLAG1 | FLAG2));
    471 
    472     f &= FLAG1 | FLAG2;
    473     SELF_CHECK (f == (FLAG1 | FLAG2));
    474 
    475     f ^= FLAG1 | FLAG2;
    476     SELF_CHECK (f == 0);
    477   }
    478 
    479   /* Check explicit conversion to int works.  */
    480   {
    481     constexpr int some_bits (FLAG1 | FLAG2);
    482 
    483     /* And comparison with int works too.  */
    484     static_assert (some_bits == (FLAG1 | FLAG2));
    485     static_assert (some_bits == test_flags (FLAG1 | FLAG2));
    486   }
    487 
    488   /* Check operator| and operator|=.  Particularly interesting is
    489      making sure that putting the enum value on the lhs side of the
    490      expression works (FLAG | f).  */
    491   {
    492     test_flags f = FLAG1;
    493     f |= FLAG2;
    494     SELF_CHECK (f == (FLAG1 | FLAG2));
    495   }
    496   {
    497     test_flags f = FLAG1;
    498     f = f | FLAG2;
    499     SELF_CHECK (f == (FLAG1 | FLAG2));
    500   }
    501   {
    502     test_flags f = FLAG1;
    503     f = FLAG2 | f;
    504     SELF_CHECK (f == (FLAG1 | FLAG2));
    505   }
    506 
    507   /* Check the &/&= operators.  */
    508   {
    509     test_flags f = FLAG1 & FLAG2;
    510     SELF_CHECK (f == 0);
    511 
    512     f = FLAG1 | FLAG2;
    513     f &= FLAG2;
    514     SELF_CHECK (f == FLAG2);
    515 
    516     f = FLAG1 | FLAG2;
    517     f = f & FLAG2;
    518     SELF_CHECK (f == FLAG2);
    519 
    520     f = FLAG1 | FLAG2;
    521     f = FLAG2 & f;
    522     SELF_CHECK (f == FLAG2);
    523   }
    524 
    525   /* Check the ^/^= operators.  */
    526   {
    527     constexpr test_flags f = FLAG1 ^ FLAG2;
    528     static_assert (f == (FLAG1 ^ FLAG2));
    529   }
    530 
    531   {
    532     test_flags f = FLAG1 ^ FLAG2;
    533     f ^= FLAG3;
    534     SELF_CHECK (f == (FLAG1 | FLAG2 | FLAG3));
    535     f = f ^ FLAG3;
    536     SELF_CHECK (f == (FLAG1 | FLAG2));
    537     f = FLAG3 ^ f;
    538     SELF_CHECK (f == (FLAG1 | FLAG2 | FLAG3));
    539   }
    540 
    541   /* Check operator~.  Note this only compiles with unsigned
    542      flags.  */
    543   {
    544     constexpr test_uflags f1 = ~UFLAG1;
    545     constexpr test_uflags f2 = ~f1;
    546     static_assert (f2 == UFLAG1);
    547   }
    548 
    549   /* Check the ternary operator.  */
    550 
    551   {
    552     /* raw enum, raw enum */
    553     constexpr test_flags f1 = true ? FLAG1 : FLAG2;
    554     static_assert (f1 == FLAG1);
    555     constexpr test_flags f2 = false ? FLAG1 : FLAG2;
    556     static_assert (f2 == FLAG2);
    557   }
    558 
    559   {
    560     /* enum flags, raw enum */
    561     constexpr test_flags src = FLAG1;
    562     constexpr test_flags f1 = true ? src : FLAG2;
    563     static_assert (f1 == FLAG1);
    564     constexpr test_flags f2 = false ? src : FLAG2;
    565     static_assert (f2 == FLAG2);
    566   }
    567 
    568   {
    569     /* enum flags, enum flags */
    570     constexpr test_flags src1 = FLAG1;
    571     constexpr test_flags src2 = FLAG2;
    572     constexpr test_flags f1 = true ? src1 : src2;
    573     static_assert (f1 == src1);
    574     constexpr test_flags f2 = false ? src1 : src2;
    575     static_assert (f2 == src2);
    576   }
    577 
    578   /* Check that we can use flags in switch expressions (requires
    579      unambiguous conversion to integer).  Also check that we can use
    580      operator| in switch cases, where only constants are allowed.
    581      This should work because operator| is constexpr.  */
    582   {
    583     test_flags f = FLAG1 | FLAG2;
    584     bool ok = false;
    585 
    586     switch (f)
    587       {
    588       case FLAG1:
    589 	break;
    590       case FLAG2:
    591 	break;
    592       case FLAG1 | FLAG2:
    593 	ok = true;
    594 	break;
    595       }
    596 
    597     SELF_CHECK (ok);
    598   }
    599 
    600   /* Check string conversion.  */
    601   {
    602     SELF_CHECK (to_string_uflags (0)
    603 		== "0x0 []");
    604     SELF_CHECK (to_string_uflags (UFLAG1)
    605 		== "0x1 [UFLAG1]");
    606     SELF_CHECK (to_string_uflags (UFLAG1 | UFLAG3)
    607 		== "0x5 [UFLAG1 UFLAG3]");
    608     SELF_CHECK (to_string_uflags (UFLAG1 | UFLAG2 | UFLAG3)
    609 		== "0x7 [UFLAG1 UFLAG3 0x2]");
    610     SELF_CHECK (to_string_uflags (UFLAG2)
    611 		== "0x2 [0x2]");
    612     /* Check that even with multiple unmapped flags, we only print one
    613        unmapped hex number (0xa, in this case).  */
    614     SELF_CHECK (to_string_uflags (UFLAG1 | UFLAG2 | UFLAG3 | UFLAG4)
    615 		== "0xf [UFLAG1 UFLAG3 0xa]");
    616 
    617     SELF_CHECK (to_string_flags (0)
    618 		== "0x0 []");
    619     SELF_CHECK (to_string_flags (FLAG1)
    620 		== "0x1 [FLAG1]");
    621     SELF_CHECK (to_string_flags (FLAG1 | FLAG3)
    622 		== "0x5 [FLAG1 FLAG3]");
    623     SELF_CHECK (to_string_flags (FLAG1 | FLAG2 | FLAG3)
    624 		== "0x7 [FLAG1 FLAG3 0x2]");
    625     SELF_CHECK (to_string_flags (FLAG2)
    626 		== "0x2 [0x2]");
    627     SELF_CHECK (to_string_flags (FLAG1 | FLAG2 | FLAG3 | FLAG4)
    628 		== "0xf [FLAG1 FLAG3 0xa]");
    629   }
    630 }
    631 
    632 } /* namespace enum_flags_tests */
    633 } /* namespace selftests */
    634 
    635 void _initialize_enum_flags_selftests ();
    636 
    637 void
    638 _initialize_enum_flags_selftests ()
    639 {
    640   selftests::register_test ("enum-flags",
    641 			    selftests::enum_flags_tests::self_test);
    642 }
    643