msg_130.c revision 1.15
11.15Srillig/* $NetBSD: msg_130.c,v 1.15 2022/06/16 16:58:36 rillig Exp $ */ 21.1Srillig# 3 "msg_130.c" 31.1Srillig 41.5Srillig// Test for message: enum type mismatch: '%s' '%s' '%s' [130] 51.1Srillig 61.7Srillig/* See also msg_241.c, which covers unusual operators on enums. */ 71.7Srillig 81.2Srilligenum color { 91.4Srillig RED = 1 << 0, 101.4Srillig GREEN = 1 << 1, 111.4Srillig BLUE = 1 << 2 121.4Srillig}; 131.4Srillig 141.4Srilligenum size { 151.4Srillig SMALL, 161.4Srillig MEDIUM, 171.4Srillig LARGE 181.2Srillig}; 191.2Srillig 201.2Srilligenum daytime { 211.2Srillig NIGHT, MORNING, NOON, EVENING 221.2Srillig}; 231.2Srillig 241.4Srilligvoid sink(_Bool); 251.4Srillig 261.4Srilligvoid 271.4Srilligexample(_Bool cond, enum color c, enum size s) 281.2Srillig{ 291.15Srillig /* expect+1: warning: enum type mismatch: 'enum color' ':' 'enum daytime' [130] */ 301.15Srillig sink(cond ? GREEN : MORNING); 311.15Srillig /* expect+1: warning: enum type mismatch: 'enum color' '!=' 'enum size' [130] */ 321.15Srillig sink(c != s); 331.15Srillig /* expect+1: warning: enum type mismatch: 'enum color' '==' 'enum size' [130] */ 341.15Srillig sink(c == s); 351.4Srillig sink((c & MEDIUM) != 0); /* might be useful to warn about */ 361.4Srillig sink((c | MEDIUM) != 0); /* might be useful to warn about */ 371.4Srillig 381.4Srillig c |= MEDIUM; /* might be useful to warn about */ 391.4Srillig c &= MEDIUM; /* might be useful to warn about */ 401.4Srillig 411.4Srillig /* The cast to unsigned is required by GCC at WARNS=6. */ 421.4Srillig c &= ~(unsigned)MEDIUM; /* might be useful to warn about */ 431.2Srillig} 441.6Srillig 451.6Srilligvoid 461.6Srilligswitch_example(enum color c) 471.6Srillig{ 481.6Srillig switch (c) { 491.11Srillig case EVENING: /* maybe someday expect: 130 */ 501.11Srillig case LARGE: /* maybe someday expect: 130 */ 511.11Srillig case 0: /* maybe someday expect: 130 */ 521.6Srillig sink(1 == 1); 531.6Srillig break; 541.6Srillig default: 551.6Srillig break; 561.6Srillig } 571.6Srillig} 581.9Srillig 591.9Srillig/* 601.9Srillig * Unnamed enum types can be used as a container for constants, especially 611.9Srillig * since in C90 and C99, even after the declaration 'static const int x = 3', 621.9Srillig * 'x' is not a constant expression. 631.9Srillig */ 641.9Srilligenum { 651.9Srillig sizeof_int = sizeof(int), 661.14Srillig sizeof_short = sizeof(short) 671.9Srillig}; 681.9Srillig 691.9Srilligenum { 701.9Srillig sizeof_uint = sizeof(unsigned int) 711.9Srillig}; 721.9Srillig 731.9Srilligint 741.9Srilligenum_constant_from_unnamed_type(int x) 751.9Srillig{ 761.11Srillig /* using an enum constant as constant-expression */ 771.9Srillig switch (x) { 781.11Srillig case sizeof_int: 791.9Srillig return 1; 801.14Srillig case sizeof_short: 811.9Srillig return 2; 821.9Srillig default: 831.9Srillig break; 841.9Srillig } 851.9Srillig 861.9Srillig if (x == sizeof_int) 871.9Srillig return 4; 881.9Srillig if (x > sizeof_int) 891.9Srillig return 5; 901.9Srillig 911.15Srillig /* FIXME */ 921.15Srillig /* expect+1: warning: enum type mismatch: 'enum <unnamed>' '==' 'enum <unnamed>' [130] */ 931.15Srillig if (sizeof_int == sizeof_uint) 941.9Srillig return 6; 951.9Srillig 961.15Srillig /* expect+1: warning: statement not reached [193] */ 971.15Srillig return 0; 981.9Srillig} 991.10Srillig 1001.10Srillig/* 1011.10Srillig * A typical legitimate use case for an anonymous enum type that should not 1021.10Srillig * be mixed with other types is a state machine. 1031.10Srillig * 1041.10Srillig * This example demonstrates that the type of the 'switch' expression can be 1051.10Srillig * an anonymous enum. 1061.10Srillig */ 1071.10Srilligvoid 1081.10Srilligstate_machine(const char *str) 1091.10Srillig{ 1101.10Srillig enum { 1111.10Srillig begin, 1121.10Srillig seen_letter, 1131.10Srillig seen_letter_digit, 1141.10Srillig error 1151.10Srillig } state = begin; 1161.10Srillig 1171.10Srillig for (const char *p = str; *p != '\0'; p++) { 1181.10Srillig switch (state) { 1191.10Srillig case begin: 1201.10Srillig state = *p == 'A' ? seen_letter : error; 1211.10Srillig break; 1221.10Srillig case seen_letter: 1231.10Srillig state = *p == '1' ? seen_letter_digit : error; 1241.10Srillig break; 1251.10Srillig default: 1261.10Srillig state = error; 1271.10Srillig } 1281.10Srillig } 1291.10Srillig 1301.10Srillig if (state == 2) /* might be worth a warning */ 1311.10Srillig return; 1321.15Srillig /* expect+1: warning: enum type mismatch: 'enum <unnamed>' '==' 'enum <unnamed>' [130] */ 1331.15Srillig if (state == sizeof_int) 1341.10Srillig return; 1351.10Srillig} 1361.13Srillig 1371.13Srillig/* 1381.13Srillig * For check_case_label_enum, a warning only makes sense if the type of the 1391.13Srillig * enum can actually be specified somehow, either explicitly by using a tag 1401.13Srillig * name or a typedef name, or implicitly by using a variable in a switch 1411.13Srillig * expression. 1421.13Srillig */ 1431.13Srillig 1441.13Srilligtypedef enum { 1451.13Srillig has_typedef = 1001 1461.13Srillig} typedef_name; 1471.13Srillig 1481.13Srilligenum tag_name { 1491.13Srillig has_tag = 1002 1501.13Srillig}; 1511.13Srillig 1521.13Srilligenum { 1531.13Srillig has_variable = 1003 1541.13Srillig} variable; 1551.13Srillig 1561.13Srilligenum { 1571.13Srillig inaccessible = 1004 1581.13Srillig}; 1591.13Srillig 1601.13Srillig/* 1611.13Srillig * This check is already done by Clang, so it may not be necessary to add it 1621.13Srillig * to lint as well. Except if there are some cases that Clang didn't 1631.13Srillig * implement. 1641.13Srillig */ 1651.13Srilligvoid 1661.13Srilligtest_check_case_label_enum(enum color color) 1671.13Srillig{ 1681.13Srillig switch (color) 1691.13Srillig { 1701.13Srillig case has_typedef: 1711.13Srillig case has_tag: 1721.13Srillig case has_variable: 1731.13Srillig case inaccessible: 1741.13Srillig return; 1751.13Srillig } 1761.13Srillig} 177