1/* Self tests for enum-flags for GDB, the GNU debugger.
2
3   Copyright (C) 2016-2023 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 "defs.h"
21#include "gdbsupport/enum-flags.h"
22#include "gdbsupport/valid-expr.h"
23#include "gdbsupport/selftest.h"
24
25namespace selftests {
26namespace enum_flags_tests {
27
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.  */
31
32/* A "real enum".  */
33enum RE
34  {
35    RE_FLAG1 = 1 << 1,
36    RE_FLAG2 = 1 << 2,
37  };
38
39/* Another "real enum".  */
40enum RE2
41  {
42    RE2_FLAG1 = 1 << 1,
43    RE2_FLAG2 = 1 << 2,
44  };
45
46/* An unsigned "real enum".  */
47enum URE : unsigned
48  {
49    URE_FLAG1 = 1 << 1,
50    URE_FLAG2 = 1 << 2,
51    URE_FLAG3 = 0xffffffff,
52  };
53
54/* A non-flags enum.  */
55enum NF
56  {
57    NF_FLAG1 = 1 << 1,
58    NF_FLAG2 = 1 << 2,
59  };
60
61/* The corresponding "enum flags" types.  */
62DEF_ENUM_FLAGS_TYPE (RE, EF);
63DEF_ENUM_FLAGS_TYPE (RE2, EF2);
64DEF_ENUM_FLAGS_TYPE (URE, UEF);
65
66#if HAVE_IS_TRIVIALLY_COPYABLE
67
68/* So that std::vectors of types that have enum_flags fields can
69   reallocate efficiently memcpy.  */
70gdb_static_assert (std::is_trivially_copyable<EF>::value);
71
72#endif
73
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
77   follow.  */
78static RE re ATTRIBUTE_UNUSED;
79static EF ef ATTRIBUTE_UNUSED;
80
81/* First, compile-time tests that:
82
83   - make sure that incorrect operations with mismatching enum types
84     are caught at compile time.
85
86   - make sure that the same operations but involving the right enum
87     types do compile and that they return the correct type.
88*/
89
90#define CHECK_VALID(VALID, EXPR_TYPE, EXPR)		\
91  CHECK_VALID_EXPR_6 (EF, RE, EF2, RE2, UEF, URE, VALID, EXPR_TYPE, EXPR)
92
93typedef std::underlying_type<RE>::type und;
94
95/* Test construction / conversion from/to different types.  */
96
97/* RE/EF -> underlying (explicit) */
98CHECK_VALID (true,  und,  und (RE ()))
99CHECK_VALID (true,  und,  und (EF ()))
100
101/* RE/EF -> int (explicit) */
102CHECK_VALID (true,  int,  int (RE ()))
103CHECK_VALID (true,  int,  int (EF ()))
104
105/* other -> RE */
106
107/* You can construct a raw enum value from an int explicitly to punch
108   a hole in the type system if need to.  */
109CHECK_VALID (true,  RE,   RE (1))
110CHECK_VALID (true,  RE,   RE (RE2 ()))
111CHECK_VALID (false, void, RE (EF2 ()))
112CHECK_VALID (true,  RE,   RE (RE ()))
113CHECK_VALID (false, void, RE (EF ()))
114
115/* other -> EF.  */
116
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.  */
121CHECK_VALID (false, void, EF (1))
122CHECK_VALID (false, void, EF (1u))
123CHECK_VALID (false, void, EF (RE2 ()))
124CHECK_VALID (false, void, EF (EF2 ()))
125CHECK_VALID (true,  EF,   EF (RE ()))
126CHECK_VALID (true,  EF,   EF (EF ()))
127
128/* Test operators.  */
129
130/* operator OP (raw_enum, int) */
131
132CHECK_VALID (false, void, RE () | 1)
133CHECK_VALID (false, void, RE () & 1)
134CHECK_VALID (false, void, RE () ^ 1)
135
136/* operator OP (int, raw_enum) */
137
138CHECK_VALID (false, void, 1 | RE ())
139CHECK_VALID (false, void, 1 & RE ())
140CHECK_VALID (false, void, 1 ^ RE ())
141
142/* operator OP (enum_flags, int) */
143
144CHECK_VALID (false, void, EF () | 1)
145CHECK_VALID (false, void, EF () & 1)
146CHECK_VALID (false, void, EF () ^ 1)
147
148/* operator OP (int, enum_flags) */
149
150CHECK_VALID (false, void, 1 | EF ())
151CHECK_VALID (false, void, 1 & EF ())
152CHECK_VALID (false, void, 1 ^ EF ())
153
154/* operator OP (raw_enum, raw_enum) */
155
156CHECK_VALID (false, void, RE () | RE2 ())
157CHECK_VALID (false, void, RE () & RE2 ())
158CHECK_VALID (false, void, RE () ^ RE2 ())
159CHECK_VALID (true,  RE,   RE () | RE ())
160CHECK_VALID (true,  RE,   RE () & RE ())
161CHECK_VALID (true,  RE,   RE () ^ RE ())
162
163/* operator OP (enum_flags, raw_enum) */
164
165CHECK_VALID (false, void, EF () | RE2 ())
166CHECK_VALID (false, void, EF () & RE2 ())
167CHECK_VALID (false, void, EF () ^ RE2 ())
168CHECK_VALID (true,  EF,   EF () | RE ())
169CHECK_VALID (true,  EF,   EF () & RE ())
170CHECK_VALID (true,  EF,   EF () ^ RE ())
171
172/* operator OP= (raw_enum, raw_enum), rvalue ref on the lhs. */
173
174CHECK_VALID (false, void, RE () |= RE2 ())
175CHECK_VALID (false, void, RE () &= RE2 ())
176CHECK_VALID (false, void, RE () ^= RE2 ())
177CHECK_VALID (false, void, RE () |= RE ())
178CHECK_VALID (false, void, RE () &= RE ())
179CHECK_VALID (false, void, RE () ^= RE ())
180
181/* operator OP= (raw_enum, raw_enum), lvalue ref on the lhs. */
182
183CHECK_VALID (false, void, re |= RE2 ())
184CHECK_VALID (false, void, re &= RE2 ())
185CHECK_VALID (false, void, re ^= RE2 ())
186CHECK_VALID (true,  RE&,  re |= RE ())
187CHECK_VALID (true,  RE&,  re &= RE ())
188CHECK_VALID (true,  RE&,  re ^= RE ())
189
190/* operator OP= (enum_flags, raw_enum), rvalue ref on the lhs.  */
191
192CHECK_VALID (false, void, EF () |= RE2 ())
193CHECK_VALID (false, void, EF () &= RE2 ())
194CHECK_VALID (false, void, EF () ^= RE2 ())
195CHECK_VALID (false, void, EF () |= RE ())
196CHECK_VALID (false, void, EF () &= RE ())
197CHECK_VALID (false, void, EF () ^= RE ())
198
199/* operator OP= (enum_flags, raw_enum), lvalue ref on the lhs.  */
200
201CHECK_VALID (false, void, ef |= RE2 ())
202CHECK_VALID (false, void, ef &= RE2 ())
203CHECK_VALID (false, void, ef ^= RE2 ())
204CHECK_VALID (true,  EF&,  ef |= EF ())
205CHECK_VALID (true,  EF&,  ef &= EF ())
206CHECK_VALID (true,  EF&,  ef ^= EF ())
207
208/* operator OP= (enum_flags, enum_flags), rvalue ref on the lhs.  */
209
210CHECK_VALID (false, void, EF () |= EF2 ())
211CHECK_VALID (false, void, EF () &= EF2 ())
212CHECK_VALID (false, void, EF () ^= EF2 ())
213CHECK_VALID (false, void, EF () |= EF ())
214CHECK_VALID (false, void, EF () &= EF ())
215CHECK_VALID (false, void, EF () ^= EF ())
216
217/* operator OP= (enum_flags, enum_flags), lvalue ref on the lhs.  */
218
219CHECK_VALID (false, void, ef |= EF2 ())
220CHECK_VALID (false, void, ef &= EF2 ())
221CHECK_VALID (false, void, ef ^= EF2 ())
222CHECK_VALID (true,  EF&,  ef |= EF ())
223CHECK_VALID (true,  EF&,  ef &= EF ())
224CHECK_VALID (true,  EF&,  ef ^= EF ())
225
226/* operator~ (raw_enum) */
227
228CHECK_VALID (false,  void,   ~RE ())
229CHECK_VALID (true,   URE,    ~URE ())
230
231/* operator~ (enum_flags) */
232
233CHECK_VALID (false,  void,   ~EF ())
234CHECK_VALID (true,   UEF,    ~UEF ())
235
236/* Check ternary operator.  This exercises implicit conversions.  */
237
238CHECK_VALID (true,  EF,   true ? EF () : RE ())
239CHECK_VALID (true,  EF,   true ? RE () : EF ())
240
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
243   cast.
244
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:
248
249    invalid user-defined conversion from ���EF��� to ���RE2���
250
251   They've been confirmed to compile/pass with gcc 5.3, gcc 7.1 and
252   clang 3.7.  */
253
254CHECK_VALID (true,  int,  true ? EF () : EF2 ())
255CHECK_VALID (true,  int,  true ? EF2 () : EF ())
256#if GCC_VERSION >= 5003 || defined __clang__
257CHECK_VALID (true,  int,  true ? EF () : RE2 ())
258CHECK_VALID (true,  int,  true ? RE2 () : EF ())
259#endif
260
261/* Same, but with an unsigned enum.  */
262
263typedef unsigned int uns;
264
265CHECK_VALID (true,  uns,  true ? EF () : UEF ())
266CHECK_VALID (true,  uns,  true ? UEF () : EF ())
267#if GCC_VERSION >= 5003 || defined __clang__
268CHECK_VALID (true,  uns,  true ? EF () : URE ())
269CHECK_VALID (true,  uns,  true ? URE () : EF ())
270#endif
271
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
276   enum_flags.
277
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.
281*/
282#if GCC_VERSION >= 4009 || defined __clang__
283CHECK_VALID (false, void, true ? EF () : 0)
284CHECK_VALID (false, void, true ? 0 : EF ())
285#endif
286
287/* Check that the ++/--/<</>>/<<=/>>= operators are deleted.  */
288
289CHECK_VALID (false, void, RE ()++)
290CHECK_VALID (false, void, ++RE ())
291CHECK_VALID (false, void, --RE ())
292CHECK_VALID (false, void, RE ()--)
293
294CHECK_VALID (false, void, RE () << 1)
295CHECK_VALID (false, void, RE () >> 1)
296CHECK_VALID (false, void, EF () << 1)
297CHECK_VALID (false, void, EF () >> 1)
298
299CHECK_VALID (false, void, RE () <<= 1)
300CHECK_VALID (false, void, RE () >>= 1)
301CHECK_VALID (false, void, EF () <<= 1)
302CHECK_VALID (false, void, EF () >>= 1)
303
304/* Test comparison operators.  */
305
306CHECK_VALID (false, void, EF () == EF2 ())
307CHECK_VALID (false, void, EF () == RE2 ())
308CHECK_VALID (false, void, RE () == EF2 ())
309
310CHECK_VALID (true,  bool, EF (RE (1)) == EF (RE (1)))
311CHECK_VALID (true,  bool, EF (RE (1)) == RE (1))
312CHECK_VALID (true,  bool, RE (1)      == EF (RE (1)))
313
314CHECK_VALID (false, void, EF () != EF2 ())
315CHECK_VALID (false, void, EF () != RE2 ())
316CHECK_VALID (false, void, RE () != EF2 ())
317
318/* Disable -Wenum-compare due to:
319
320   Clang:
321
322    "error: comparison of two values with different enumeration types
323    [-Werror,-Wenum-compare]"
324
325   GCC:
326
327    "error: comparison between ���enum selftests::enum_flags_tests::RE���
328     and ���enum selftests::enum_flags_tests::RE2���
329     [-Werror=enum-compare]"
330
331   Not a big deal since misuses like these in GDB will be caught by
332   -Werror anyway.  This check is here mainly for completeness.  */
333#if defined __GNUC__
334# pragma GCC diagnostic push
335# pragma GCC diagnostic ignored "-Wenum-compare"
336#endif
337CHECK_VALID (true,  bool, RE () == RE2 ())
338CHECK_VALID (true,  bool, RE () != RE2 ())
339#if defined __GNUC__
340# pragma GCC diagnostic pop
341#endif
342
343CHECK_VALID (true,  bool, EF (RE (1)) != EF (RE (2)))
344CHECK_VALID (true,  bool, EF (RE (1)) != RE (2))
345CHECK_VALID (true,  bool, RE (1)      != EF (RE (2)))
346
347CHECK_VALID (true,  bool, EF () == 0)
348
349/* Check we didn't disable/delete comparison between non-flags enums
350   and unrelated types by mistake.  */
351CHECK_VALID (true,  bool, NF (1) == NF (1))
352CHECK_VALID (true,  bool, NF (1) == int (1))
353CHECK_VALID (true,  bool, NF (1) == char (1))
354
355/* -------------------------------------------------------------------- */
356
357/* Follows misc tests that exercise the API.  Some are compile time,
358   when possible, others are run time.  */
359
360enum test_flag
361  {
362    FLAG1 = 1 << 1,
363    FLAG2 = 1 << 2,
364    FLAG3 = 1 << 3,
365  };
366
367enum test_uflag : unsigned
368  {
369    UFLAG1 = 1 << 1,
370    UFLAG2 = 1 << 2,
371    UFLAG3 = 1 << 3,
372  };
373
374DEF_ENUM_FLAGS_TYPE (test_flag, test_flags);
375DEF_ENUM_FLAGS_TYPE (test_uflag, test_uflags);
376
377static void
378self_test ()
379{
380  /* Check that default construction works.  */
381  {
382    constexpr test_flags f;
383
384    gdb_static_assert (f == 0);
385  }
386
387  /* Check that assignment from zero works.  */
388  {
389    test_flags f (FLAG1);
390
391    SELF_CHECK (f == FLAG1);
392
393    f = 0;
394
395    SELF_CHECK (f == 0);
396  }
397
398  /* Check that construction from zero works.  */
399  {
400    constexpr test_flags zero1 = 0;
401    constexpr test_flags zero2 (0);
402    constexpr test_flags zero3 {0};
403    constexpr test_flags zero4 = {0};
404
405    gdb_static_assert (zero1 == 0);
406    gdb_static_assert (zero2 == 0);
407    gdb_static_assert (zero3 == 0);
408    gdb_static_assert (zero4 == 0);
409  }
410
411  /* Check construction from enum value.  */
412  {
413    gdb_static_assert (test_flags (FLAG1) == FLAG1);
414    gdb_static_assert (test_flags (FLAG2) != FLAG1);
415  }
416
417  /* Check copy/assignment.  */
418  {
419    constexpr test_flags src = FLAG1;
420
421    constexpr test_flags f1 = src;
422    constexpr test_flags f2 (src);
423    constexpr test_flags f3 {src};
424    constexpr test_flags f4 = {src};
425
426    gdb_static_assert (f1 == FLAG1);
427    gdb_static_assert (f2 == FLAG1);
428    gdb_static_assert (f3 == FLAG1);
429    gdb_static_assert (f4 == FLAG1);
430  }
431
432  /* Check moving.  */
433  {
434    test_flags src = FLAG1;
435    test_flags dst = 0;
436
437    dst = std::move (src);
438    SELF_CHECK (dst == FLAG1);
439  }
440
441  /* Check construction from an 'or' of multiple bits.  For this to
442     work, operator| must be overridden to return an enum type.  The
443     builtin version would return int instead and then the conversion
444     to test_flags would fail.  */
445  {
446    constexpr test_flags f = FLAG1 | FLAG2;
447    gdb_static_assert (f == (FLAG1 | FLAG2));
448  }
449
450  /* Similarly, check that "FLAG1 | FLAG2" on the rhs of an assignment
451     operator works.  */
452  {
453    test_flags f = 0;
454    f |= FLAG1 | FLAG2;
455    SELF_CHECK (f == (FLAG1 | FLAG2));
456
457    f &= FLAG1 | FLAG2;
458    SELF_CHECK (f == (FLAG1 | FLAG2));
459
460    f ^= FLAG1 | FLAG2;
461    SELF_CHECK (f == 0);
462  }
463
464  /* Check explicit conversion to int works.  */
465  {
466    constexpr int some_bits (FLAG1 | FLAG2);
467
468    /* And comparison with int works too.  */
469    gdb_static_assert (some_bits == (FLAG1 | FLAG2));
470    gdb_static_assert (some_bits == test_flags (FLAG1 | FLAG2));
471  }
472
473  /* Check operator| and operator|=.  Particularly interesting is
474     making sure that putting the enum value on the lhs side of the
475     expression works (FLAG | f).  */
476  {
477    test_flags f = FLAG1;
478    f |= FLAG2;
479    SELF_CHECK (f == (FLAG1 | FLAG2));
480  }
481  {
482    test_flags f = FLAG1;
483    f = f | FLAG2;
484    SELF_CHECK (f == (FLAG1 | FLAG2));
485  }
486  {
487    test_flags f = FLAG1;
488    f = FLAG2 | f;
489    SELF_CHECK (f == (FLAG1 | FLAG2));
490  }
491
492  /* Check the &/&= operators.  */
493  {
494    test_flags f = FLAG1 & FLAG2;
495    SELF_CHECK (f == 0);
496
497    f = FLAG1 | FLAG2;
498    f &= FLAG2;
499    SELF_CHECK (f == FLAG2);
500
501    f = FLAG1 | FLAG2;
502    f = f & FLAG2;
503    SELF_CHECK (f == FLAG2);
504
505    f = FLAG1 | FLAG2;
506    f = FLAG2 & f;
507    SELF_CHECK (f == FLAG2);
508  }
509
510  /* Check the ^/^= operators.  */
511  {
512    constexpr test_flags f = FLAG1 ^ FLAG2;
513    gdb_static_assert (f == (FLAG1 ^ FLAG2));
514  }
515
516  {
517    test_flags f = FLAG1 ^ FLAG2;
518    f ^= FLAG3;
519    SELF_CHECK (f == (FLAG1 | FLAG2 | FLAG3));
520    f = f ^ FLAG3;
521    SELF_CHECK (f == (FLAG1 | FLAG2));
522    f = FLAG3 ^ f;
523    SELF_CHECK (f == (FLAG1 | FLAG2 | FLAG3));
524  }
525
526  /* Check operator~.  Note this only compiles with unsigned
527     flags.  */
528  {
529    constexpr test_uflags f1 = ~UFLAG1;
530    constexpr test_uflags f2 = ~f1;
531    gdb_static_assert (f2 == UFLAG1);
532  }
533
534  /* Check the ternary operator.  */
535
536  {
537    /* raw enum, raw enum */
538    constexpr test_flags f1 = true ? FLAG1 : FLAG2;
539    gdb_static_assert (f1 == FLAG1);
540    constexpr test_flags f2 = false ? FLAG1 : FLAG2;
541    gdb_static_assert (f2 == FLAG2);
542  }
543
544  {
545    /* enum flags, raw enum */
546    constexpr test_flags src = FLAG1;
547    constexpr test_flags f1 = true ? src : FLAG2;
548    gdb_static_assert (f1 == FLAG1);
549    constexpr test_flags f2 = false ? src : FLAG2;
550    gdb_static_assert (f2 == FLAG2);
551  }
552
553  {
554    /* enum flags, enum flags */
555    constexpr test_flags src1 = FLAG1;
556    constexpr test_flags src2 = FLAG2;
557    constexpr test_flags f1 = true ? src1 : src2;
558    gdb_static_assert (f1 == src1);
559    constexpr test_flags f2 = false ? src1 : src2;
560    gdb_static_assert (f2 == src2);
561  }
562
563  /* Check that we can use flags in switch expressions (requires
564     unambiguous conversion to integer).  Also check that we can use
565     operator| in switch cases, where only constants are allowed.
566     This should work because operator| is constexpr.  */
567  {
568    test_flags f = FLAG1 | FLAG2;
569    bool ok = false;
570
571    switch (f)
572      {
573      case FLAG1:
574	break;
575      case FLAG2:
576	break;
577      case FLAG1 | FLAG2:
578	ok = true;
579	break;
580      }
581
582    SELF_CHECK (ok);
583  }
584}
585
586} /* namespace enum_flags_tests */
587} /* namespace selftests */
588
589void _initialize_enum_flags_selftests ();
590
591void
592_initialize_enum_flags_selftests ()
593{
594  selftests::register_test ("enum-flags",
595			    selftests::enum_flags_tests::self_test);
596}
597