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