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