msg_130.c revision 1.14
1/* $NetBSD: msg_130.c,v 1.14 2021/05/25 19:04:07 rillig Exp $ */ 2# 3 "msg_130.c" 3 4// Test for message: enum type mismatch: '%s' '%s' '%s' [130] 5 6/* See also msg_241.c, which covers unusual operators on enums. */ 7 8enum color { 9 RED = 1 << 0, 10 GREEN = 1 << 1, 11 BLUE = 1 << 2 12}; 13 14enum size { 15 SMALL, 16 MEDIUM, 17 LARGE 18}; 19 20enum daytime { 21 NIGHT, MORNING, NOON, EVENING 22}; 23 24void sink(_Bool); 25 26void 27example(_Bool cond, enum color c, enum size s) 28{ 29 sink(cond ? GREEN : MORNING); /* expect: 130 */ 30 31 sink(c != s); /* expect: 130 */ 32 sink(c == s); /* expect: 130 */ 33 sink((c & MEDIUM) != 0); /* might be useful to warn about */ 34 sink((c | MEDIUM) != 0); /* might be useful to warn about */ 35 36 c |= MEDIUM; /* might be useful to warn about */ 37 c &= MEDIUM; /* might be useful to warn about */ 38 39 /* The cast to unsigned is required by GCC at WARNS=6. */ 40 c &= ~(unsigned)MEDIUM; /* might be useful to warn about */ 41} 42 43void 44switch_example(enum color c) 45{ 46 switch (c) { 47 case EVENING: /* maybe someday expect: 130 */ 48 case LARGE: /* maybe someday expect: 130 */ 49 case 0: /* maybe someday expect: 130 */ 50 sink(1 == 1); 51 break; 52 default: 53 break; 54 } 55} 56 57/* 58 * Unnamed enum types can be used as a container for constants, especially 59 * since in C90 and C99, even after the declaration 'static const int x = 3', 60 * 'x' is not a constant expression. 61 */ 62enum { 63 sizeof_int = sizeof(int), 64 sizeof_short = sizeof(short) 65}; 66 67enum { 68 sizeof_uint = sizeof(unsigned int) 69}; 70 71int 72enum_constant_from_unnamed_type(int x) 73{ 74 /* using an enum constant as constant-expression */ 75 switch (x) { 76 case sizeof_int: 77 return 1; 78 case sizeof_short: 79 return 2; 80 default: 81 break; 82 } 83 84 if (x == sizeof_int) 85 return 4; 86 if (x > sizeof_int) 87 return 5; 88 89 if (sizeof_int == sizeof_uint) /* expect: 130 *//* FIXME */ 90 return 6; 91 92 return 0; /* expect: statement not reached */ 93} 94 95/* 96 * A typical legitimate use case for an anonymous enum type that should not 97 * be mixed with other types is a state machine. 98 * 99 * This example demonstrates that the type of the 'switch' expression can be 100 * an anonymous enum. 101 */ 102void 103state_machine(const char *str) 104{ 105 enum { 106 begin, 107 seen_letter, 108 seen_letter_digit, 109 error 110 } state = begin; 111 112 for (const char *p = str; *p != '\0'; p++) { 113 switch (state) { 114 case begin: 115 state = *p == 'A' ? seen_letter : error; 116 break; 117 case seen_letter: 118 state = *p == '1' ? seen_letter_digit : error; 119 break; 120 default: 121 state = error; 122 } 123 } 124 125 if (state == 2) /* might be worth a warning */ 126 return; 127 if (state == sizeof_int) /* expect: 130 */ 128 return; 129} 130 131/* 132 * For check_case_label_enum, a warning only makes sense if the type of the 133 * enum can actually be specified somehow, either explicitly by using a tag 134 * name or a typedef name, or implicitly by using a variable in a switch 135 * expression. 136 */ 137 138typedef enum { 139 has_typedef = 1001 140} typedef_name; 141 142enum tag_name { 143 has_tag = 1002 144}; 145 146enum { 147 has_variable = 1003 148} variable; 149 150enum { 151 inaccessible = 1004 152}; 153 154/* 155 * This check is already done by Clang, so it may not be necessary to add it 156 * to lint as well. Except if there are some cases that Clang didn't 157 * implement. 158 */ 159void 160test_check_case_label_enum(enum color color) 161{ 162 switch (color) 163 { 164 case has_typedef: 165 case has_tag: 166 case has_variable: 167 case inaccessible: 168 return; 169 } 170} 171