1 /* Self tests for enum-flags for GDB, the GNU debugger.
3 Copyright (C) 2016-2020 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/>. */
21 #include "gdbsupport/enum-flags.h"
22 #include "gdbsupport/valid-expr.h"
23 #include "gdbsupport/selftest.h"
26 namespace enum_flags_tests
{
28 /* The (real) enum types used in CHECK_VALID. Their names match the
29 template parameter names of the templates defined by CHECK_VALID to
30 make it simpler to use. They could be named differently. */
39 /* Another "real enum". */
46 /* An unsigned "real enum". */
51 URE_FLAG3
= 0xffffffff,
54 /* A non-flags enum. */
61 /* The corresponding "enum flags" types. */
62 DEF_ENUM_FLAGS_TYPE (RE
, EF
);
63 DEF_ENUM_FLAGS_TYPE (RE2
, EF2
);
64 DEF_ENUM_FLAGS_TYPE (URE
, UEF
);
66 #if HAVE_IS_TRIVIALLY_COPYABLE
68 /* So that std::vectors of types that have enum_flags fields can
69 reallocate efficiently memcpy. */
70 gdb_static_assert (std::is_trivially_copyable
<EF
>::value
);
74 /* A couple globals used as lvalues in the CHECK_VALID expressions
75 below. Their names (and types) match the uppercase type names
76 exposed by CHECK_VALID just to make the expressions easier to
78 static RE re ATTRIBUTE_UNUSED
;
79 static EF ef ATTRIBUTE_UNUSED
;
81 /* First, compile-time tests that:
83 - make sure that incorrect operations with mismatching enum types
84 are caught at compile time.
86 - make sure that the same operations but involving the right enum
87 types do compile and that they return the correct type.
90 #define CHECK_VALID(VALID, EXPR_TYPE, EXPR) \
91 CHECK_VALID_EXPR_6 (EF, RE, EF2, RE2, UEF, URE, VALID, EXPR_TYPE, EXPR)
93 typedef std::underlying_type
<RE
>::type und
;
95 /* Test construction / conversion from/to different types. */
97 /* RE/EF -> underlying (explicit) */
98 CHECK_VALID (true, und
, und (RE ()))
99 CHECK_VALID (true, und
, und (EF ()))
101 /* RE/EF -> int (explicit) */
102 CHECK_VALID (true, int, int (RE ()))
103 CHECK_VALID (true, int, int (EF ()))
107 /* You can construct a raw enum value from an int explicitly to punch
108 a hole in the type system if need to. */
109 CHECK_VALID (true, RE
, RE (1))
110 CHECK_VALID (true, RE
, RE (RE2 ()))
111 CHECK_VALID (false, void, RE (EF2 ()))
112 CHECK_VALID (true, RE
, RE (RE ()))
113 CHECK_VALID (false, void, RE (EF ()))
117 /* As expected, enum-flags is a stronger type than the backing raw
118 enum. Unlike with raw enums, you can't construct an enum flags
119 from an integer nor from an unrelated enum type explicitly. Add an
120 intermediate conversion via the raw enum if you really need it. */
121 CHECK_VALID (false, void, EF (1))
122 CHECK_VALID (false, void, EF (1u))
123 CHECK_VALID (false, void, EF (RE2 ()))
124 CHECK_VALID (false, void, EF (EF2 ()))
125 CHECK_VALID (true, EF
, EF (RE ()))
126 CHECK_VALID (true, EF
, EF (EF ()))
128 /* Test operators. */
130 /* operator OP (raw_enum, int) */
132 CHECK_VALID (false, void, RE () | 1)
133 CHECK_VALID (false, void, RE () & 1)
134 CHECK_VALID (false, void, RE () ^ 1)
136 /* operator OP (int, raw_enum) */
138 CHECK_VALID (false, void, 1 | RE ())
139 CHECK_VALID (false, void, 1 & RE ())
140 CHECK_VALID (false, void, 1 ^ RE ())
142 /* operator OP (enum_flags, int) */
144 CHECK_VALID (false, void, EF () | 1)
145 CHECK_VALID (false, void, EF () & 1)
146 CHECK_VALID (false, void, EF () ^ 1)
148 /* operator OP (int, enum_flags) */
150 CHECK_VALID (false, void, 1 | EF ())
151 CHECK_VALID (false, void, 1 & EF ())
152 CHECK_VALID (false, void, 1 ^ EF ())
154 /* operator OP (raw_enum, raw_enum) */
156 CHECK_VALID (false, void, RE () | RE2 ())
157 CHECK_VALID (false, void, RE () & RE2 ())
158 CHECK_VALID (false, void, RE () ^ RE2 ())
159 CHECK_VALID (true, RE
, RE () | RE ())
160 CHECK_VALID (true, RE
, RE () & RE ())
161 CHECK_VALID (true, RE
, RE () ^ RE ())
163 /* operator OP (enum_flags, raw_enum) */
165 CHECK_VALID (false, void, EF () | RE2 ())
166 CHECK_VALID (false, void, EF () & RE2 ())
167 CHECK_VALID (false, void, EF () ^ RE2 ())
168 CHECK_VALID (true, EF
, EF () | RE ())
169 CHECK_VALID (true, EF
, EF () & RE ())
170 CHECK_VALID (true, EF
, EF () ^ RE ())
172 /* operator OP= (raw_enum, raw_enum), rvalue ref on the lhs. */
174 CHECK_VALID (false, void, RE () |= RE2 ())
175 CHECK_VALID (false, void, RE () &= RE2 ())
176 CHECK_VALID (false, void, RE () ^= RE2 ())
177 CHECK_VALID (false, void, RE () |= RE ())
178 CHECK_VALID (false, void, RE () &= RE ())
179 CHECK_VALID (false, void, RE () ^= RE ())
181 /* operator OP= (raw_enum, raw_enum), lvalue ref on the lhs. */
183 CHECK_VALID (false, void, re
|= RE2 ())
184 CHECK_VALID (false, void, re
&= RE2 ())
185 CHECK_VALID (false, void, re
^= RE2 ())
186 CHECK_VALID (true, RE
&, re
|= RE ())
187 CHECK_VALID (true, RE
&, re
&= RE ())
188 CHECK_VALID (true, RE
&, re
^= RE ())
190 /* operator OP= (enum_flags, raw_enum), rvalue ref on the lhs. */
192 CHECK_VALID (false, void, EF () |= RE2 ())
193 CHECK_VALID (false, void, EF () &= RE2 ())
194 CHECK_VALID (false, void, EF () ^= RE2 ())
195 CHECK_VALID (false, void, EF () |= RE ())
196 CHECK_VALID (false, void, EF () &= RE ())
197 CHECK_VALID (false, void, EF () ^= RE ())
199 /* operator OP= (enum_flags, raw_enum), lvalue ref on the lhs. */
201 CHECK_VALID (false, void, ef
|= RE2 ())
202 CHECK_VALID (false, void, ef
&= RE2 ())
203 CHECK_VALID (false, void, ef
^= RE2 ())
204 CHECK_VALID (true, EF
&, ef
|= EF ())
205 CHECK_VALID (true, EF
&, ef
&= EF ())
206 CHECK_VALID (true, EF
&, ef
^= EF ())
208 /* operator OP= (enum_flags, enum_flags), rvalue ref on the lhs. */
210 CHECK_VALID (false, void, EF () |= EF2 ())
211 CHECK_VALID (false, void, EF () &= EF2 ())
212 CHECK_VALID (false, void, EF () ^= EF2 ())
213 CHECK_VALID (false, void, EF () |= EF ())
214 CHECK_VALID (false, void, EF () &= EF ())
215 CHECK_VALID (false, void, EF () ^= EF ())
217 /* operator OP= (enum_flags, enum_flags), lvalue ref on the lhs. */
219 CHECK_VALID (false, void, ef
|= EF2 ())
220 CHECK_VALID (false, void, ef
&= EF2 ())
221 CHECK_VALID (false, void, ef
^= EF2 ())
222 CHECK_VALID (true, EF
&, ef
|= EF ())
223 CHECK_VALID (true, EF
&, ef
&= EF ())
224 CHECK_VALID (true, EF
&, ef
^= EF ())
226 /* operator~ (raw_enum) */
228 CHECK_VALID (false, void, ~RE ())
229 CHECK_VALID (true, URE
, ~URE ())
231 /* operator~ (enum_flags) */
233 CHECK_VALID (false, void, ~EF ())
234 CHECK_VALID (true, UEF
, ~UEF ())
236 /* Check ternary operator. This exercises implicit conversions. */
238 CHECK_VALID (true, EF
, true ? EF () : RE ())
239 CHECK_VALID (true, EF
, true ? RE () : EF ())
241 /* These are valid, but it's not a big deal since you won't be able to
242 assign the resulting integer to an enum or an enum_flags without a
245 The latter two tests are disabled on older GCCs because they
246 incorrectly fail with gcc 4.8 and 4.9 at least. Running the test
247 outside a SFINAE context shows:
249 invalid user-defined conversion from ‘EF’ to ‘RE2’
251 They've been confirmed to compile/pass with gcc 5.3, gcc 7.1 and
254 CHECK_VALID (true, int, true ? EF () : EF2 ())
255 CHECK_VALID (true, int, true ? EF2 () : EF ())
256 #if GCC_VERSION >= 5003 || defined __clang__
257 CHECK_VALID (true, int, true ? EF () : RE2 ())
258 CHECK_VALID (true, int, true ? RE2 () : EF ())
261 /* Same, but with an unsigned enum. */
263 typedef unsigned int uns
;
265 CHECK_VALID (true, uns
, true ? EF () : UEF ())
266 CHECK_VALID (true, uns
, true ? UEF () : EF ())
267 #if GCC_VERSION >= 5003 || defined __clang__
268 CHECK_VALID (true, uns
, true ? EF () : URE ())
269 CHECK_VALID (true, uns
, true ? URE () : EF ())
272 /* Unfortunately this can't work due to the way C++ computes the
273 return type of the ternary conditional operator. int isn't
274 implicitly convertible to the raw enum type, so the type of the
275 expression is int. And then int is not implicitly convertible to
278 GCC 4.8 fails to compile this test with:
279 error: operands to ?: have different types ‘enum_flags<RE>’ and ‘int’
280 Confirmed to work with gcc 4.9, 5.3 and clang 3.7.
282 #if GCC_VERSION >= 4009 || defined __clang__
283 CHECK_VALID (false, void, true ? EF () : 0)
284 CHECK_VALID (false, void, true ? 0 : EF ())
287 /* Check that the ++/--/<</>>/<<=/>>= operators are deleted. */
289 CHECK_VALID (false, void, RE ()++)
290 CHECK_VALID (false, void, ++RE ())
291 CHECK_VALID (false, void, --RE ())
292 CHECK_VALID (false, void, RE ()--)
294 CHECK_VALID (false, void, RE () << 1)
295 CHECK_VALID (false, void, RE () >> 1)
296 CHECK_VALID (false, void, EF () << 1)
297 CHECK_VALID (false, void, EF () >> 1)
299 CHECK_VALID (false, void, RE () <<= 1)
300 CHECK_VALID (false, void, RE () >>= 1)
301 CHECK_VALID (false, void, EF () <<= 1)
302 CHECK_VALID (false, void, EF () >>= 1)
304 /* Test comparison operators. */
306 CHECK_VALID (false, void, EF () == EF2 ())
307 CHECK_VALID (false, void, EF () == RE2 ())
308 CHECK_VALID (false, void, RE () == EF2 ())
310 CHECK_VALID (true, bool, EF (RE (1)) == EF (RE (1)))
311 CHECK_VALID (true, bool, EF (RE (1)) == RE (1))
312 CHECK_VALID (true, bool, RE (1) == EF (RE (1)))
314 CHECK_VALID (false, void, EF () != EF2 ())
315 CHECK_VALID (false, void, EF () != RE2 ())
316 CHECK_VALID (false, void, RE () != EF2 ())
318 /* On clang, disable -Wenum-compare due to "error: comparison of two
319 values with different enumeration types [-Werror,-Wenum-compare]".
320 clang doesn't suppress -Wenum-compare in SFINAE contexts. Not a
321 big deal since misuses like these in GDB will be caught by -Werror
322 anyway. This check is here mainly for completeness. */
323 #if defined __clang__
324 # pragma GCC diagnostic push
325 # pragma GCC diagnostic ignored "-Wenum-compare"
327 CHECK_VALID (true, bool, RE () == RE2 ())
328 CHECK_VALID (true, bool, RE () != RE2 ())
329 #if defined __clang__
330 # pragma GCC diagnostic pop
333 CHECK_VALID (true, bool, EF (RE (1)) != EF (RE (2)))
334 CHECK_VALID (true, bool, EF (RE (1)) != RE (2))
335 CHECK_VALID (true, bool, RE (1) != EF (RE (2)))
337 CHECK_VALID (true, bool, EF () == 0)
339 /* Check we didn't disable/delete comparison between non-flags enums
340 and unrelated types by mistake. */
341 CHECK_VALID (true, bool, NF (1) == NF (1))
342 CHECK_VALID (true, bool, NF (1) == int (1))
343 CHECK_VALID (true, bool, NF (1) == char (1))
345 /* -------------------------------------------------------------------- */
347 /* Follows misc tests that exercise the API. Some are compile time,
348 when possible, others are run time. */
357 enum test_uflag
: unsigned
364 DEF_ENUM_FLAGS_TYPE (test_flag
, test_flags
);
365 DEF_ENUM_FLAGS_TYPE (test_uflag
, test_uflags
);
370 /* Check that default construction works. */
372 constexpr test_flags f
;
374 gdb_static_assert (f
== 0);
377 /* Check that assignment from zero works. */
379 test_flags
f (FLAG1
);
381 SELF_CHECK (f
== FLAG1
);
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 gdb_static_assert (zero1
== 0);
396 gdb_static_assert (zero2
== 0);
397 gdb_static_assert (zero3
== 0);
398 gdb_static_assert (zero4
== 0);
401 /* Check construction from enum value. */
403 gdb_static_assert (test_flags (FLAG1
) == FLAG1
);
404 gdb_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 gdb_static_assert (f1
== FLAG1
);
417 gdb_static_assert (f2
== FLAG1
);
418 gdb_static_assert (f3
== FLAG1
);
419 gdb_static_assert (f4
== FLAG1
);
424 test_flags src
= FLAG1
;
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 gdb_static_assert (f
== (FLAG1
| FLAG2
));
440 /* Similarly, check that "FLAG1 | FLAG2" on the rhs of an assignment
445 SELF_CHECK (f
== (FLAG1
| FLAG2
));
448 SELF_CHECK (f
== (FLAG1
| FLAG2
));
454 /* Check explicit conversion to int works. */
456 constexpr int some_bits (FLAG1
| FLAG2
);
458 /* And comparison with int works too. */
459 gdb_static_assert (some_bits
== (FLAG1
| FLAG2
));
460 gdb_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
;
469 SELF_CHECK (f
== (FLAG1
| FLAG2
));
472 test_flags f
= FLAG1
;
474 SELF_CHECK (f
== (FLAG1
| FLAG2
));
477 test_flags f
= FLAG1
;
479 SELF_CHECK (f
== (FLAG1
| FLAG2
));
482 /* Check the &/&= operators. */
484 test_flags f
= FLAG1
& FLAG2
;
489 SELF_CHECK (f
== FLAG2
);
493 SELF_CHECK (f
== FLAG2
);
497 SELF_CHECK (f
== FLAG2
);
500 /* Check the ^/^= operators. */
502 constexpr test_flags f
= FLAG1
^ FLAG2
;
503 gdb_static_assert (f
== (FLAG1
^ FLAG2
));
507 test_flags f
= FLAG1
^ FLAG2
;
509 SELF_CHECK (f
== (FLAG1
| FLAG2
| FLAG3
));
511 SELF_CHECK (f
== (FLAG1
| FLAG2
));
513 SELF_CHECK (f
== (FLAG1
| FLAG2
| FLAG3
));
516 /* Check operator~. Note this only compiles with unsigned
519 constexpr test_uflags f1
= ~UFLAG1
;
520 constexpr test_uflags f2
= ~f1
;
521 gdb_static_assert (f2
== UFLAG1
);
524 /* Check the ternary operator. */
527 /* raw enum, raw enum */
528 constexpr test_flags f1
= true ? FLAG1
: FLAG2
;
529 gdb_static_assert (f1
== FLAG1
);
530 constexpr test_flags f2
= false ? FLAG1
: FLAG2
;
531 gdb_static_assert (f2
== FLAG2
);
535 /* enum flags, raw enum */
536 constexpr test_flags src
= FLAG1
;
537 constexpr test_flags f1
= true ? src
: FLAG2
;
538 gdb_static_assert (f1
== FLAG1
);
539 constexpr test_flags f2
= false ? src
: FLAG2
;
540 gdb_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 gdb_static_assert (f1
== src1
);
549 constexpr test_flags f2
= false ? src1
: src2
;
550 gdb_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
;
576 } /* namespace enum_flags_tests */
577 } /* namespace selftests */
579 void _initialize_enum_flags_selftests ();
582 _initialize_enum_flags_selftests ()
584 selftests::register_test ("enum-flags",
585 selftests::enum_flags_tests::self_test
);
This page took 0.04554 seconds and 4 git commands to generate.