msg_130.c revision 1.13
11.13Srillig/* $NetBSD: msg_130.c,v 1.13 2021/04/02 13:16:38 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.4Srillig sink(cond ? GREEN : MORNING); /* expect: 130 */ 301.4Srillig 311.4Srillig sink(c != s); /* expect: 130 */ 321.4Srillig sink(c == s); /* expect: 130 */ 331.4Srillig sink((c & MEDIUM) != 0); /* might be useful to warn about */ 341.4Srillig sink((c | MEDIUM) != 0); /* might be useful to warn about */ 351.4Srillig 361.4Srillig c |= MEDIUM; /* might be useful to warn about */ 371.4Srillig c &= MEDIUM; /* might be useful to warn about */ 381.4Srillig 391.4Srillig /* The cast to unsigned is required by GCC at WARNS=6. */ 401.4Srillig c &= ~(unsigned)MEDIUM; /* might be useful to warn about */ 411.2Srillig} 421.6Srillig 431.6Srilligvoid 441.6Srilligswitch_example(enum color c) 451.6Srillig{ 461.6Srillig switch (c) { 471.11Srillig case EVENING: /* maybe someday expect: 130 */ 481.11Srillig case LARGE: /* maybe someday expect: 130 */ 491.11Srillig case 0: /* maybe someday expect: 130 */ 501.6Srillig sink(1 == 1); 511.6Srillig break; 521.6Srillig default: 531.6Srillig break; 541.6Srillig } 551.6Srillig} 561.9Srillig 571.9Srillig/* 581.9Srillig * Unnamed enum types can be used as a container for constants, especially 591.9Srillig * since in C90 and C99, even after the declaration 'static const int x = 3', 601.9Srillig * 'x' is not a constant expression. 611.9Srillig */ 621.9Srilligenum { 631.9Srillig sizeof_int = sizeof(int), 641.9Srillig sizeof_long = sizeof(long) 651.9Srillig}; 661.9Srillig 671.9Srilligenum { 681.9Srillig sizeof_uint = sizeof(unsigned int) 691.9Srillig}; 701.9Srillig 711.9Srilligint 721.9Srilligenum_constant_from_unnamed_type(int x) 731.9Srillig{ 741.11Srillig /* using an enum constant as constant-expression */ 751.9Srillig switch (x) { 761.11Srillig case sizeof_int: 771.9Srillig return 1; 781.11Srillig case sizeof_long: 791.9Srillig return 2; 801.9Srillig default: 811.9Srillig break; 821.9Srillig } 831.9Srillig 841.9Srillig if (x == sizeof_int) 851.9Srillig return 4; 861.9Srillig if (x > sizeof_int) 871.9Srillig return 5; 881.9Srillig 891.9Srillig if (sizeof_int == sizeof_uint) /* expect: 130 *//* FIXME */ 901.9Srillig return 6; 911.9Srillig 921.12Srillig return 0; /* expect: statement not reached */ 931.9Srillig} 941.10Srillig 951.10Srillig/* 961.10Srillig * A typical legitimate use case for an anonymous enum type that should not 971.10Srillig * be mixed with other types is a state machine. 981.10Srillig * 991.10Srillig * This example demonstrates that the type of the 'switch' expression can be 1001.10Srillig * an anonymous enum. 1011.10Srillig */ 1021.10Srilligvoid 1031.10Srilligstate_machine(const char *str) 1041.10Srillig{ 1051.10Srillig enum { 1061.10Srillig begin, 1071.10Srillig seen_letter, 1081.10Srillig seen_letter_digit, 1091.10Srillig error 1101.10Srillig } state = begin; 1111.10Srillig 1121.10Srillig for (const char *p = str; *p != '\0'; p++) { 1131.10Srillig switch (state) { 1141.10Srillig case begin: 1151.10Srillig state = *p == 'A' ? seen_letter : error; 1161.10Srillig break; 1171.10Srillig case seen_letter: 1181.10Srillig state = *p == '1' ? seen_letter_digit : error; 1191.10Srillig break; 1201.10Srillig default: 1211.10Srillig state = error; 1221.10Srillig } 1231.10Srillig } 1241.10Srillig 1251.10Srillig if (state == 2) /* might be worth a warning */ 1261.10Srillig return; 1271.10Srillig if (state == sizeof_int) /* expect: 130 */ 1281.10Srillig return; 1291.10Srillig} 1301.13Srillig 1311.13Srillig/* 1321.13Srillig * For check_case_label_enum, a warning only makes sense if the type of the 1331.13Srillig * enum can actually be specified somehow, either explicitly by using a tag 1341.13Srillig * name or a typedef name, or implicitly by using a variable in a switch 1351.13Srillig * expression. 1361.13Srillig */ 1371.13Srillig 1381.13Srilligtypedef enum { 1391.13Srillig has_typedef = 1001 1401.13Srillig} typedef_name; 1411.13Srillig 1421.13Srilligenum tag_name { 1431.13Srillig has_tag = 1002 1441.13Srillig}; 1451.13Srillig 1461.13Srilligenum { 1471.13Srillig has_variable = 1003 1481.13Srillig} variable; 1491.13Srillig 1501.13Srilligenum { 1511.13Srillig inaccessible = 1004 1521.13Srillig}; 1531.13Srillig 1541.13Srillig/* 1551.13Srillig * This check is already done by Clang, so it may not be necessary to add it 1561.13Srillig * to lint as well. Except if there are some cases that Clang didn't 1571.13Srillig * implement. 1581.13Srillig */ 1591.13Srilligvoid 1601.13Srilligtest_check_case_label_enum(enum color color) 1611.13Srillig{ 1621.13Srillig switch (color) 1631.13Srillig { 1641.13Srillig case has_typedef: 1651.13Srillig case has_tag: 1661.13Srillig case has_variable: 1671.13Srillig case inaccessible: 1681.13Srillig return; 1691.13Srillig } 1701.13Srillig} 171