msg_130.c revision 1.17
11.17Srillig/* $NetBSD: msg_130.c,v 1.17 2024/11/13 04:32:49 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.16Srillig/* lint1-extra-flags: -X 351 */ 91.16Srillig 101.2Srilligenum color { 111.4Srillig RED = 1 << 0, 121.4Srillig GREEN = 1 << 1, 131.4Srillig BLUE = 1 << 2 141.4Srillig}; 151.4Srillig 161.4Srilligenum size { 171.4Srillig SMALL, 181.4Srillig MEDIUM, 191.4Srillig LARGE 201.2Srillig}; 211.2Srillig 221.2Srilligenum daytime { 231.2Srillig NIGHT, MORNING, NOON, EVENING 241.2Srillig}; 251.2Srillig 261.4Srilligvoid sink(_Bool); 271.4Srillig 281.4Srilligvoid 291.4Srilligexample(_Bool cond, enum color c, enum size s) 301.2Srillig{ 311.15Srillig /* expect+1: warning: enum type mismatch: 'enum color' ':' 'enum daytime' [130] */ 321.15Srillig sink(cond ? GREEN : MORNING); 331.15Srillig /* expect+1: warning: enum type mismatch: 'enum color' '!=' 'enum size' [130] */ 341.15Srillig sink(c != s); 351.15Srillig /* expect+1: warning: enum type mismatch: 'enum color' '==' 'enum size' [130] */ 361.15Srillig sink(c == s); 371.4Srillig sink((c & MEDIUM) != 0); /* might be useful to warn about */ 381.4Srillig sink((c | MEDIUM) != 0); /* might be useful to warn about */ 391.4Srillig 401.4Srillig c |= MEDIUM; /* might be useful to warn about */ 411.4Srillig c &= MEDIUM; /* might be useful to warn about */ 421.4Srillig 431.4Srillig /* The cast to unsigned is required by GCC at WARNS=6. */ 441.4Srillig c &= ~(unsigned)MEDIUM; /* might be useful to warn about */ 451.2Srillig} 461.6Srillig 471.6Srilligvoid 481.6Srilligswitch_example(enum color c) 491.6Srillig{ 501.6Srillig switch (c) { 511.11Srillig case EVENING: /* maybe someday expect: 130 */ 521.11Srillig case LARGE: /* maybe someday expect: 130 */ 531.11Srillig case 0: /* maybe someday expect: 130 */ 541.6Srillig sink(1 == 1); 551.6Srillig break; 561.6Srillig default: 571.6Srillig break; 581.6Srillig } 591.6Srillig} 601.9Srillig 611.9Srillig/* 621.9Srillig * Unnamed enum types can be used as a container for constants, especially 631.9Srillig * since in C90 and C99, even after the declaration 'static const int x = 3', 641.9Srillig * 'x' is not a constant expression. 651.9Srillig */ 661.9Srilligenum { 671.9Srillig sizeof_int = sizeof(int), 681.14Srillig sizeof_short = sizeof(short) 691.9Srillig}; 701.9Srillig 711.9Srilligenum { 721.9Srillig sizeof_uint = sizeof(unsigned int) 731.9Srillig}; 741.9Srillig 751.9Srilligint 761.9Srilligenum_constant_from_unnamed_type(int x) 771.9Srillig{ 781.11Srillig /* using an enum constant as constant-expression */ 791.9Srillig switch (x) { 801.11Srillig case sizeof_int: 811.9Srillig return 1; 821.14Srillig case sizeof_short: 831.9Srillig return 2; 841.9Srillig default: 851.9Srillig break; 861.9Srillig } 871.9Srillig 881.9Srillig if (x == sizeof_int) 891.9Srillig return 4; 901.9Srillig if (x > sizeof_int) 911.9Srillig return 5; 921.9Srillig 931.15Srillig /* FIXME */ 941.15Srillig /* expect+1: warning: enum type mismatch: 'enum <unnamed>' '==' 'enum <unnamed>' [130] */ 951.15Srillig if (sizeof_int == sizeof_uint) 961.9Srillig return 6; 971.9Srillig 981.17Srillig /* expect+1: warning: 'return' statement not reached [193] */ 991.15Srillig return 0; 1001.9Srillig} 1011.10Srillig 1021.10Srillig/* 1031.10Srillig * A typical legitimate use case for an anonymous enum type that should not 1041.10Srillig * be mixed with other types is a state machine. 1051.10Srillig * 1061.10Srillig * This example demonstrates that the type of the 'switch' expression can be 1071.10Srillig * an anonymous enum. 1081.10Srillig */ 1091.10Srilligvoid 1101.10Srilligstate_machine(const char *str) 1111.10Srillig{ 1121.10Srillig enum { 1131.10Srillig begin, 1141.10Srillig seen_letter, 1151.10Srillig seen_letter_digit, 1161.10Srillig error 1171.10Srillig } state = begin; 1181.10Srillig 1191.10Srillig for (const char *p = str; *p != '\0'; p++) { 1201.10Srillig switch (state) { 1211.10Srillig case begin: 1221.10Srillig state = *p == 'A' ? seen_letter : error; 1231.10Srillig break; 1241.10Srillig case seen_letter: 1251.10Srillig state = *p == '1' ? seen_letter_digit : error; 1261.10Srillig break; 1271.10Srillig default: 1281.10Srillig state = error; 1291.10Srillig } 1301.10Srillig } 1311.10Srillig 1321.10Srillig if (state == 2) /* might be worth a warning */ 1331.10Srillig return; 1341.15Srillig /* expect+1: warning: enum type mismatch: 'enum <unnamed>' '==' 'enum <unnamed>' [130] */ 1351.15Srillig if (state == sizeof_int) 1361.10Srillig return; 1371.10Srillig} 1381.13Srillig 1391.13Srillig/* 1401.13Srillig * For check_case_label_enum, a warning only makes sense if the type of the 1411.13Srillig * enum can actually be specified somehow, either explicitly by using a tag 1421.13Srillig * name or a typedef name, or implicitly by using a variable in a switch 1431.13Srillig * expression. 1441.13Srillig */ 1451.13Srillig 1461.13Srilligtypedef enum { 1471.13Srillig has_typedef = 1001 1481.13Srillig} typedef_name; 1491.13Srillig 1501.13Srilligenum tag_name { 1511.13Srillig has_tag = 1002 1521.13Srillig}; 1531.13Srillig 1541.13Srilligenum { 1551.13Srillig has_variable = 1003 1561.13Srillig} variable; 1571.13Srillig 1581.13Srilligenum { 1591.13Srillig inaccessible = 1004 1601.13Srillig}; 1611.13Srillig 1621.13Srillig/* 1631.13Srillig * This check is already done by Clang, so it may not be necessary to add it 1641.13Srillig * to lint as well. Except if there are some cases that Clang didn't 1651.13Srillig * implement. 1661.13Srillig */ 1671.13Srilligvoid 1681.13Srilligtest_check_case_label_enum(enum color color) 1691.13Srillig{ 1701.13Srillig switch (color) 1711.13Srillig { 1721.13Srillig case has_typedef: 1731.13Srillig case has_tag: 1741.13Srillig case has_variable: 1751.13Srillig case inaccessible: 1761.13Srillig return; 1771.13Srillig } 1781.13Srillig} 179