Add translations for various sub-directories
[binutils-gdb.git] / gdb / unittests / enum-flags-selftests.c
blobf192da37b41aa9d6d28a3fba01584bc1c0950988
1 /* Self tests for enum-flags for GDB, the GNU debugger.
3 Copyright (C) 2016-2024 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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/>. */
20 #include "gdbsupport/enum-flags.h"
21 #include "gdbsupport/valid-expr.h"
22 #include "gdbsupport/selftest.h"
24 namespace selftests {
25 namespace enum_flags_tests {
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. */
31 /* A "real enum". */
32 enum RawEnum
34 RawEnum_Flag1 = 1 << 1,
35 RawEnum_Flag2 = 1 << 2,
38 /* Another "real enum". */
39 enum RawEnum2
41 RawEnum2_Flag1 = 1 << 1,
42 RawEnum2_Flag2 = 1 << 2,
45 /* An unsigned "real enum". */
46 enum UnsignedRawEnum : unsigned
48 UnsignedRawEnum_Flag1 = 1 << 1,
49 UnsignedRawEnum_Flag2 = 1 << 2,
50 UnsignedRawEnum_Flag3 = 0xffffffff,
53 /* A non-flags enum. */
54 enum NonFlagsEnum
56 NonFlagsEnum_Flag1 = 1 << 1,
57 NonFlagsEnum_Flag2 = 1 << 2,
60 /* The corresponding "enum flags" types. */
61 DEF_ENUM_FLAGS_TYPE (RawEnum, EnumFlag);
62 DEF_ENUM_FLAGS_TYPE (RawEnum2, EnumFlag2);
63 DEF_ENUM_FLAGS_TYPE (UnsignedRawEnum, UnsignedEnumFlag);
65 /* So that std::vectors of types that have enum_flags fields can
66 reallocate efficiently memcpy. */
67 static_assert (std::is_trivially_copyable<EnumFlag>::value);
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 RawEnum re ATTRIBUTE_UNUSED;
74 static EnumFlag ef ATTRIBUTE_UNUSED;
76 /* First, compile-time tests that:
78 - make sure that incorrect operations with mismatching enum types
79 are caught at compile time.
81 - make sure that the same operations but involving the right enum
82 types do compile and that they return the correct type.
85 #define CHECK_VALID(VALID, EXPR_TYPE, EXPR) \
86 CHECK_VALID_EXPR_6 (EnumFlag, RawEnum, EnumFlag2, RawEnum2, \
87 UnsignedEnumFlag, UnsignedRawEnum, VALID, EXPR_TYPE, \
88 EXPR)
90 using und = std::underlying_type<RawEnum>::type;
92 /* Test construction / conversion from/to different types. */
94 /* RE/EF -> underlying (explicit) */
95 CHECK_VALID (true, und, und (RawEnum ()))
96 CHECK_VALID (true, und, und (EnumFlag ()))
98 /* RE/EF -> int (explicit) */
99 CHECK_VALID (true, int, int (RawEnum ()))
100 CHECK_VALID (true, int, int (EnumFlag ()))
102 /* other -> RE */
104 /* You can construct a raw enum value from an int explicitly to punch
105 a hole in the type system if need to. */
106 CHECK_VALID (true, RawEnum, RawEnum (1))
107 CHECK_VALID (true, RawEnum, RawEnum (RawEnum2 ()))
108 CHECK_VALID (false, void, RawEnum (EnumFlag2 ()))
109 CHECK_VALID (true, RawEnum, RawEnum (RawEnum ()))
110 CHECK_VALID (false, void, RawEnum (EnumFlag ()))
112 /* other -> EF. */
114 /* As expected, enum-flags is a stronger type than the backing raw
115 enum. Unlike with raw enums, you can't construct an enum flags
116 from an integer nor from an unrelated enum type explicitly. Add an
117 intermediate conversion via the raw enum if you really need it. */
118 CHECK_VALID (false, void, EnumFlag (1))
119 CHECK_VALID (false, void, EnumFlag (1u))
120 CHECK_VALID (false, void, EnumFlag (RawEnum2 ()))
121 CHECK_VALID (false, void, EnumFlag (EnumFlag2 ()))
122 CHECK_VALID (true, EnumFlag, EnumFlag (RawEnum ()))
123 CHECK_VALID (true, EnumFlag, EnumFlag (EnumFlag ()))
125 /* Test operators. */
127 /* operator OP (raw_enum, int) */
129 CHECK_VALID (false, void, RawEnum () | 1)
130 CHECK_VALID (false, void, RawEnum () & 1)
131 CHECK_VALID (false, void, RawEnum () ^ 1)
133 /* operator OP (int, raw_enum) */
135 CHECK_VALID (false, void, 1 | RawEnum ())
136 CHECK_VALID (false, void, 1 & RawEnum ())
137 CHECK_VALID (false, void, 1 ^ RawEnum ())
139 /* operator OP (enum_flags, int) */
141 CHECK_VALID (false, void, EnumFlag () | 1)
142 CHECK_VALID (false, void, EnumFlag () & 1)
143 CHECK_VALID (false, void, EnumFlag () ^ 1)
145 /* operator OP (int, enum_flags) */
147 CHECK_VALID (false, void, 1 | EnumFlag ())
148 CHECK_VALID (false, void, 1 & EnumFlag ())
149 CHECK_VALID (false, void, 1 ^ EnumFlag ())
151 /* operator OP (raw_enum, raw_enum) */
153 CHECK_VALID (false, void, RawEnum () | RawEnum2 ())
154 CHECK_VALID (false, void, RawEnum () & RawEnum2 ())
155 CHECK_VALID (false, void, RawEnum () ^ RawEnum2 ())
156 CHECK_VALID (true, RawEnum, RawEnum () | RawEnum ())
157 CHECK_VALID (true, RawEnum, RawEnum () & RawEnum ())
158 CHECK_VALID (true, RawEnum, RawEnum () ^ RawEnum ())
160 /* operator OP (enum_flags, raw_enum) */
162 CHECK_VALID (false, void, EnumFlag () | RawEnum2 ())
163 CHECK_VALID (false, void, EnumFlag () & RawEnum2 ())
164 CHECK_VALID (false, void, EnumFlag () ^ RawEnum2 ())
165 CHECK_VALID (true, EnumFlag, EnumFlag () | RawEnum ())
166 CHECK_VALID (true, EnumFlag, EnumFlag () & RawEnum ())
167 CHECK_VALID (true, EnumFlag, EnumFlag () ^ RawEnum ())
169 /* operator OP= (raw_enum, raw_enum), rvalue ref on the lhs. */
171 CHECK_VALID (false, void, RawEnum () |= RawEnum2 ())
172 CHECK_VALID (false, void, RawEnum () &= RawEnum2 ())
173 CHECK_VALID (false, void, RawEnum () ^= RawEnum2 ())
174 CHECK_VALID (false, void, RawEnum () |= RawEnum ())
175 CHECK_VALID (false, void, RawEnum () &= RawEnum ())
176 CHECK_VALID (false, void, RawEnum () ^= RawEnum ())
178 /* operator OP= (raw_enum, raw_enum), lvalue ref on the lhs. */
180 CHECK_VALID (false, void, re |= RawEnum2 ())
181 CHECK_VALID (false, void, re &= RawEnum2 ())
182 CHECK_VALID (false, void, re ^= RawEnum2 ())
183 CHECK_VALID (true, RawEnum&, re |= RawEnum ())
184 CHECK_VALID (true, RawEnum&, re &= RawEnum ())
185 CHECK_VALID (true, RawEnum&, re ^= RawEnum ())
187 /* operator OP= (enum_flags, raw_enum), rvalue ref on the lhs. */
189 CHECK_VALID (false, void, EnumFlag () |= RawEnum2 ())
190 CHECK_VALID (false, void, EnumFlag () &= RawEnum2 ())
191 CHECK_VALID (false, void, EnumFlag () ^= RawEnum2 ())
192 CHECK_VALID (false, void, EnumFlag () |= RawEnum ())
193 CHECK_VALID (false, void, EnumFlag () &= RawEnum ())
194 CHECK_VALID (false, void, EnumFlag () ^= RawEnum ())
196 /* operator OP= (enum_flags, raw_enum), lvalue ref on the lhs. */
198 CHECK_VALID (false, void, ef |= RawEnum2 ())
199 CHECK_VALID (false, void, ef &= RawEnum2 ())
200 CHECK_VALID (false, void, ef ^= RawEnum2 ())
201 CHECK_VALID (true, EnumFlag&, ef |= EnumFlag ())
202 CHECK_VALID (true, EnumFlag&, ef &= EnumFlag ())
203 CHECK_VALID (true, EnumFlag&, ef ^= EnumFlag ())
205 /* operator OP= (enum_flags, enum_flags), rvalue ref on the lhs. */
207 CHECK_VALID (false, void, EnumFlag () |= EnumFlag2 ())
208 CHECK_VALID (false, void, EnumFlag () &= EnumFlag2 ())
209 CHECK_VALID (false, void, EnumFlag () ^= EnumFlag2 ())
210 CHECK_VALID (false, void, EnumFlag () |= EnumFlag ())
211 CHECK_VALID (false, void, EnumFlag () &= EnumFlag ())
212 CHECK_VALID (false, void, EnumFlag () ^= EnumFlag ())
214 /* operator OP= (enum_flags, enum_flags), lvalue ref on the lhs. */
216 CHECK_VALID (false, void, ef |= EnumFlag2 ())
217 CHECK_VALID (false, void, ef &= EnumFlag2 ())
218 CHECK_VALID (false, void, ef ^= EnumFlag2 ())
219 CHECK_VALID (true, EnumFlag&, ef |= EnumFlag ())
220 CHECK_VALID (true, EnumFlag&, ef &= EnumFlag ())
221 CHECK_VALID (true, EnumFlag&, ef ^= EnumFlag ())
223 /* operator~ (raw_enum) */
225 CHECK_VALID (false, void, ~RawEnum ())
226 CHECK_VALID (true, UnsignedRawEnum, ~UnsignedRawEnum ())
228 /* operator~ (enum_flags) */
230 CHECK_VALID (false, void, ~EnumFlag ())
231 CHECK_VALID (true, UnsignedEnumFlag, ~UnsignedEnumFlag ())
233 /* Check ternary operator. This exercises implicit conversions. */
235 CHECK_VALID (true, EnumFlag, true ? EnumFlag () : RawEnum ())
236 CHECK_VALID (true, EnumFlag, true ? RawEnum () : EnumFlag ())
238 /* Unfortunately this can't work due to the way C++ computes the
239 return type of the ternary conditional operator. int isn't
240 implicitly convertible to the raw enum type, so the type of the
241 expression is int. And then int is not implicitly convertible to
242 enum_flags.
244 GCC 4.8 fails to compile this test with:
245 error: operands to ?: have different types ‘enum_flags<RE>’ and ‘int’
246 Confirmed to work with gcc 4.9, 5.3 and clang 3.7.
248 CHECK_VALID (false, void, true ? EnumFlag () : 0)
249 CHECK_VALID (false, void, true ? 0 : EnumFlag ())
251 /* Check that the ++/--/<</>>/<<=/>>= operators are deleted. */
253 CHECK_VALID (false, void, RawEnum ()++)
254 CHECK_VALID (false, void, ++RawEnum ())
255 CHECK_VALID (false, void, --RawEnum ())
256 CHECK_VALID (false, void, RawEnum ()--)
258 CHECK_VALID (false, void, RawEnum () << 1)
259 CHECK_VALID (false, void, RawEnum () >> 1)
260 CHECK_VALID (false, void, EnumFlag () << 1)
261 CHECK_VALID (false, void, EnumFlag () >> 1)
263 CHECK_VALID (false, void, RawEnum () <<= 1)
264 CHECK_VALID (false, void, RawEnum () >>= 1)
265 CHECK_VALID (false, void, EnumFlag () <<= 1)
266 CHECK_VALID (false, void, EnumFlag () >>= 1)
268 /* Test comparison operators. */
270 CHECK_VALID (false, void, EnumFlag () == EnumFlag2 ())
271 CHECK_VALID (false, void, EnumFlag () == RawEnum2 ())
272 CHECK_VALID (false, void, RawEnum () == EnumFlag2 ())
274 CHECK_VALID (true, bool, EnumFlag (RawEnum (1)) == EnumFlag (RawEnum (1)))
275 CHECK_VALID (true, bool, EnumFlag (RawEnum (1)) == RawEnum (1))
276 CHECK_VALID (true, bool, RawEnum (1) == EnumFlag (RawEnum (1)))
278 CHECK_VALID (false, void, EnumFlag () != EnumFlag2 ())
279 CHECK_VALID (false, void, EnumFlag () != RawEnum2 ())
280 CHECK_VALID (false, void, RawEnum () != EnumFlag2 ())
282 /* Disable -Wenum-compare due to:
284 Clang:
286 "error: comparison of two values with different enumeration types
287 [-Werror,-Wenum-compare]"
289 GCC:
291 "error: comparison between ‘enum selftests::enum_flags_tests::RE’
292 and ‘enum selftests::enum_flags_tests::RE2’
293 [-Werror=enum-compare]"
295 Not a big deal since misuses like these in GDB will be caught by
296 -Werror anyway. This check is here mainly for completeness. */
297 #if defined __GNUC__
298 # pragma GCC diagnostic push
299 # pragma GCC diagnostic ignored "-Wenum-compare"
300 #endif
301 CHECK_VALID (true, bool, RawEnum () == RawEnum2 ())
302 CHECK_VALID (true, bool, RawEnum () != RawEnum2 ())
303 #if defined __GNUC__
304 # pragma GCC diagnostic pop
305 #endif
307 CHECK_VALID (true, bool, EnumFlag (RawEnum (1)) != EnumFlag (RawEnum (2)))
308 CHECK_VALID (true, bool, EnumFlag (RawEnum (1)) != RawEnum (2))
309 CHECK_VALID (true, bool, RawEnum (1) != EnumFlag (RawEnum (2)))
311 CHECK_VALID (true, bool, EnumFlag () == 0)
313 /* Check we didn't disable/delete comparison between non-flags enums
314 and unrelated types by mistake. */
315 CHECK_VALID (true, bool, NonFlagsEnum (1) == NonFlagsEnum (1))
316 CHECK_VALID (true, bool, NonFlagsEnum (1) == int (1))
317 CHECK_VALID (true, bool, NonFlagsEnum (1) == char (1))
319 /* -------------------------------------------------------------------- */
321 /* Follows misc tests that exercise the API. Some are compile time,
322 when possible, others are run time. */
324 enum test_flag
326 FLAG1 = 1 << 0,
327 FLAG2 = 1 << 1,
328 FLAG3 = 1 << 2,
329 FLAG4 = 1 << 3,
332 enum test_uflag : unsigned
334 UFLAG1 = 1 << 0,
335 UFLAG2 = 1 << 1,
336 UFLAG3 = 1 << 2,
337 UFLAG4 = 1 << 3,
340 DEF_ENUM_FLAGS_TYPE (test_flag, test_flags);
341 DEF_ENUM_FLAGS_TYPE (test_uflag, test_uflags);
343 /* to_string enumerator->string mapping functions used to test
344 enum_flags::to_string. These intentionally miss mapping a couple
345 enumerators each (xFLAG2, xFLAG4). */
347 static std::string
348 to_string_flags (test_flags flags)
350 static constexpr test_flags::string_mapping mapping[] = {
351 MAP_ENUM_FLAG (FLAG1),
352 MAP_ENUM_FLAG (FLAG3),
354 return flags.to_string (mapping);
357 static std::string
358 to_string_uflags (test_uflags flags)
360 static constexpr test_uflags::string_mapping mapping[] = {
361 MAP_ENUM_FLAG (UFLAG1),
362 MAP_ENUM_FLAG (UFLAG3),
364 return flags.to_string (mapping);
367 static void
368 self_test ()
370 /* Check that default construction works. */
372 constexpr test_flags f;
374 static_assert (f == 0);
377 /* Check that assignment from zero works. */
379 test_flags f (FLAG1);
381 SELF_CHECK (f == FLAG1);
383 f = 0;
385 SELF_CHECK (f == 0);
388 /* Check that construction from zero works. */
390 constexpr test_flags zero1 = 0;
391 constexpr test_flags zero2 (0);
392 constexpr test_flags zero3 {0};
393 constexpr test_flags zero4 = {0};
395 static_assert (zero1 == 0);
396 static_assert (zero2 == 0);
397 static_assert (zero3 == 0);
398 static_assert (zero4 == 0);
401 /* Check construction from enum value. */
403 static_assert (test_flags (FLAG1) == FLAG1);
404 static_assert (test_flags (FLAG2) != FLAG1);
407 /* Check copy/assignment. */
409 constexpr test_flags src = FLAG1;
411 constexpr test_flags f1 = src;
412 constexpr test_flags f2 (src);
413 constexpr test_flags f3 {src};
414 constexpr test_flags f4 = {src};
416 static_assert (f1 == FLAG1);
417 static_assert (f2 == FLAG1);
418 static_assert (f3 == FLAG1);
419 static_assert (f4 == FLAG1);
422 /* Check moving. */
424 test_flags src = FLAG1;
425 test_flags dst = 0;
427 dst = std::move (src);
428 SELF_CHECK (dst == FLAG1);
431 /* Check construction from an 'or' of multiple bits. For this to
432 work, operator| must be overridden to return an enum type. The
433 builtin version would return int instead and then the conversion
434 to test_flags would fail. */
436 constexpr test_flags f = FLAG1 | FLAG2;
437 static_assert (f == (FLAG1 | FLAG2));
440 /* Similarly, check that "FLAG1 | FLAG2" on the rhs of an assignment
441 operator works. */
443 test_flags f = 0;
444 f |= FLAG1 | FLAG2;
445 SELF_CHECK (f == (FLAG1 | FLAG2));
447 f &= FLAG1 | FLAG2;
448 SELF_CHECK (f == (FLAG1 | FLAG2));
450 f ^= FLAG1 | FLAG2;
451 SELF_CHECK (f == 0);
454 /* Check explicit conversion to int works. */
456 constexpr int some_bits (FLAG1 | FLAG2);
458 /* And comparison with int works too. */
459 static_assert (some_bits == (FLAG1 | FLAG2));
460 static_assert (some_bits == test_flags (FLAG1 | FLAG2));
463 /* Check operator| and operator|=. Particularly interesting is
464 making sure that putting the enum value on the lhs side of the
465 expression works (FLAG | f). */
467 test_flags f = FLAG1;
468 f |= FLAG2;
469 SELF_CHECK (f == (FLAG1 | FLAG2));
472 test_flags f = FLAG1;
473 f = f | FLAG2;
474 SELF_CHECK (f == (FLAG1 | FLAG2));
477 test_flags f = FLAG1;
478 f = FLAG2 | f;
479 SELF_CHECK (f == (FLAG1 | FLAG2));
482 /* Check the &/&= operators. */
484 test_flags f = FLAG1 & FLAG2;
485 SELF_CHECK (f == 0);
487 f = FLAG1 | FLAG2;
488 f &= FLAG2;
489 SELF_CHECK (f == FLAG2);
491 f = FLAG1 | FLAG2;
492 f = f & FLAG2;
493 SELF_CHECK (f == FLAG2);
495 f = FLAG1 | FLAG2;
496 f = FLAG2 & f;
497 SELF_CHECK (f == FLAG2);
500 /* Check the ^/^= operators. */
502 constexpr test_flags f = FLAG1 ^ FLAG2;
503 static_assert (f == (FLAG1 ^ FLAG2));
507 test_flags f = FLAG1 ^ FLAG2;
508 f ^= FLAG3;
509 SELF_CHECK (f == (FLAG1 | FLAG2 | FLAG3));
510 f = f ^ FLAG3;
511 SELF_CHECK (f == (FLAG1 | FLAG2));
512 f = FLAG3 ^ f;
513 SELF_CHECK (f == (FLAG1 | FLAG2 | FLAG3));
516 /* Check operator~. Note this only compiles with unsigned
517 flags. */
519 constexpr test_uflags f1 = ~UFLAG1;
520 constexpr test_uflags f2 = ~f1;
521 static_assert (f2 == UFLAG1);
524 /* Check the ternary operator. */
527 /* raw enum, raw enum */
528 constexpr test_flags f1 = true ? FLAG1 : FLAG2;
529 static_assert (f1 == FLAG1);
530 constexpr test_flags f2 = false ? FLAG1 : FLAG2;
531 static_assert (f2 == FLAG2);
535 /* enum flags, raw enum */
536 constexpr test_flags src = FLAG1;
537 constexpr test_flags f1 = true ? src : FLAG2;
538 static_assert (f1 == FLAG1);
539 constexpr test_flags f2 = false ? src : FLAG2;
540 static_assert (f2 == FLAG2);
544 /* enum flags, enum flags */
545 constexpr test_flags src1 = FLAG1;
546 constexpr test_flags src2 = FLAG2;
547 constexpr test_flags f1 = true ? src1 : src2;
548 static_assert (f1 == src1);
549 constexpr test_flags f2 = false ? src1 : src2;
550 static_assert (f2 == src2);
553 /* Check that we can use flags in switch expressions (requires
554 unambiguous conversion to integer). Also check that we can use
555 operator| in switch cases, where only constants are allowed.
556 This should work because operator| is constexpr. */
558 test_flags f = FLAG1 | FLAG2;
559 bool ok = false;
561 switch (f)
563 case FLAG1:
564 break;
565 case FLAG2:
566 break;
567 case FLAG1 | FLAG2:
568 ok = true;
569 break;
572 SELF_CHECK (ok);
575 /* Check string conversion. */
577 SELF_CHECK (to_string_uflags (0)
578 == "0x0 []");
579 SELF_CHECK (to_string_uflags (UFLAG1)
580 == "0x1 [UFLAG1]");
581 SELF_CHECK (to_string_uflags (UFLAG1 | UFLAG3)
582 == "0x5 [UFLAG1 UFLAG3]");
583 SELF_CHECK (to_string_uflags (UFLAG1 | UFLAG2 | UFLAG3)
584 == "0x7 [UFLAG1 UFLAG3 0x2]");
585 SELF_CHECK (to_string_uflags (UFLAG2)
586 == "0x2 [0x2]");
587 /* Check that even with multiple unmapped flags, we only print one
588 unmapped hex number (0xa, in this case). */
589 SELF_CHECK (to_string_uflags (UFLAG1 | UFLAG2 | UFLAG3 | UFLAG4)
590 == "0xf [UFLAG1 UFLAG3 0xa]");
592 SELF_CHECK (to_string_flags (0)
593 == "0x0 []");
594 SELF_CHECK (to_string_flags (FLAG1)
595 == "0x1 [FLAG1]");
596 SELF_CHECK (to_string_flags (FLAG1 | FLAG3)
597 == "0x5 [FLAG1 FLAG3]");
598 SELF_CHECK (to_string_flags (FLAG1 | FLAG2 | FLAG3)
599 == "0x7 [FLAG1 FLAG3 0x2]");
600 SELF_CHECK (to_string_flags (FLAG2)
601 == "0x2 [0x2]");
602 SELF_CHECK (to_string_flags (FLAG1 | FLAG2 | FLAG3 | FLAG4)
603 == "0xf [FLAG1 FLAG3 0xa]");
607 } /* namespace enum_flags_tests */
608 } /* namespace selftests */
610 void _initialize_enum_flags_selftests ();
612 void
613 _initialize_enum_flags_selftests ()
615 selftests::register_test ("enum-flags",
616 selftests::enum_flags_tests::self_test);