1/* $NetBSD: decl.c,v 1.30 2024/05/01 17:42:57 rillig Exp $ */ 2# 3 "decl.c" 3 4/* 5 * Tests for declarations, especially the distinction between the 6 * declaration-specifiers and the declarators. 7 */ 8 9/* lint1-extra-flags: -X 191,351 */ 10 11/* 12 * Even though 'const' comes after 'char' and is therefore quite close to the 13 * first identifier, it applies to both identifiers. 14 */ 15void 16specifier_qualifier(void) 17{ 18 char const a = 1, b = 2; 19 20 /* expect+1: warning: left operand of '=' must be modifiable lvalue [115] */ 21 a = 1; 22 /* expect+1: warning: left operand of '=' must be modifiable lvalue [115] */ 23 b = 2; 24} 25 26/* 27 * Since 'const' comes before 'char', there is no ambiguity whether the 28 * 'const' applies to all variables or just to the first. 29 */ 30void 31qualifier_specifier(void) 32{ 33 const char a = 1, b = 2; 34 35 /* expect+1: warning: left operand of '=' must be modifiable lvalue [115] */ 36 a = 3; 37 /* expect+1: warning: left operand of '=' must be modifiable lvalue [115] */ 38 b = 5; 39} 40 41void 42declarator_with_prefix_qualifier(void) 43{ 44 /* expect+1: error: syntax error 'const' [249] */ 45 char a = 1, const b = 2; 46 47 a = 1; 48 /* expect+1: error: 'b' undefined [99] */ 49 b = 2; 50} 51 52void 53declarator_with_postfix_qualifier(void) 54{ 55 /* expect+1: error: syntax error 'const' [249] */ 56 char a = 1, b const = 2; 57 58 a = 1; 59 b = 2; 60} 61 62void sink(double *); 63 64void 65declarators(void) 66{ 67 char *pc = 0, c = 0, **ppc = 0; 68 69 /* expect+1: warning: converting 'pointer to char' to incompatible 'pointer to double' for argument 1 [153] */ 70 sink(pc); 71 /* expect+1: warning: illegal combination of pointer 'pointer to double' and integer 'char', arg #1 [154] */ 72 sink(c); 73 /* expect+1: warning: converting 'pointer to pointer to char' to incompatible 'pointer to double' for argument 1 [153] */ 74 sink(ppc); 75} 76 77_Bool 78enum_error_handling(void) 79{ 80 enum { 81 /* expect+1: error: syntax error '"' [249] */ 82 "error 1" 83 : /* still the same error */ 84 , /* back on track */ 85 A, 86 B 87 } x = A; 88 89 return x == B; 90} 91 92/* 93 * An __attribute__ at the beginning of a declaration may become ambiguous 94 * since a GCC fallthrough statement starts with __attribute__ as well. 95 */ 96void 97unused_local_variable(void) 98{ 99 __attribute__((unused)) _Bool unused_var; 100 101 __attribute__((unused)) 102 __attribute__((unused)) _Bool unused_twice; 103} 104 105int 106declaration_without_type_specifier(void) 107{ 108 const i = 3; 109 /* expect-1: error: old-style declaration; add 'int' [1] */ 110 return i; 111} 112 113 114/* expect+2: warning: static function 'unused' unused [236] */ 115static void 116unused(void) 117{ 118} 119 120/* 121 * The attribute 'used' does not influence static functions, it only 122 * applies to function parameters. 123 */ 124/* LINTED */ 125static void 126unused_linted(void) 127{ 128} 129 130/* covers 'type_qualifier_list: type_qualifier_list type_qualifier' */ 131int *const volatile cover_type_qualifier_list; 132 133_Bool bool; 134char plain_char; 135signed char signed_char; 136unsigned char unsigned_char; 137short signed_short; 138unsigned short unsigned_short; 139int signed_int; 140unsigned int unsigned_int; 141long signed_long; 142unsigned long unsigned_long; 143struct { 144 int member; 145} unnamed_struct; 146 147/* 148 * Before decl.c 1.201 from 2021-07-15, lint crashed with an internal error 149 * in dcs_end_type (named end_type back then). 150 */ 151unsigned long sizes = 152 sizeof(const typeof(bool)) + 153 sizeof(const typeof(plain_char)) + 154 sizeof(const typeof(signed_char)) + 155 sizeof(const typeof(unsigned_char)) + 156 sizeof(const typeof(signed_short)) + 157 sizeof(const typeof(unsigned_short)) + 158 sizeof(const typeof(signed_int)) + 159 sizeof(const typeof(unsigned_int)) + 160 sizeof(const typeof(signed_long)) + 161 sizeof(const typeof(unsigned_long)) + 162 sizeof(const typeof(unnamed_struct)); 163 164/* expect+2: error: old-style declaration; add 'int' [1] */ 165/* expect+1: error: syntax error 'int' [249] */ 166thread int thread_int; 167__thread int thread_int; 168/* expect+2: error: old-style declaration; add 'int' [1] */ 169/* expect+1: error: syntax error 'int' [249] */ 170__thread__ int thread_int; 171 172static 173/* expect+1: warning: static function 'cover_func_declarator' unused [236] */ 174cover_func_declarator(void) 175/* expect+1: error: old-style declaration; add 'int' [1] */ 176{ 177} 178 179/* 180 * Before decl.c 1.268 from 2022-04-03, lint ran into an assertion failure for 181 * "elsz > 0" in 'length'. 182 */ 183/* expect+2: error: syntax error 'goto' [249] */ 184/* expect+1: warning: empty array declaration for 'void_array_error' [190] */ 185void void_array_error[] goto; 186 187const volatile int 188/* expect+1: warning: duplicate 'const' [10] */ 189 *const volatile const 190/* expect+1: warning: duplicate 'volatile' [10] */ 191 *volatile const volatile 192 *duplicate_ptr; 193 194 195/* 196 * Since tree.c 1.573 from 2023-07-15 and before decl.c 1.370 from 2023-07-31, 197 * lint crashed due to a failed assertion in find_member. The assertion states 198 * that every member of a struct or union must link back to its containing 199 * type, which had not been the case for unnamed bit-fields. 200 */ 201struct bit_and_data { 202 unsigned int :0; 203 unsigned int bit:1; 204 unsigned int :0; 205 206 void *data; 207}; 208 209static inline void * 210bit_and_data(struct bit_and_data *node) 211{ 212 return node->data; 213} 214 215 216// See cgram.y, rule 'notype_member_declarator'. 217void 218symbol_type_in_unnamed_bit_field_member(void) 219{ 220 enum { 221 bits = 4, 222 }; 223 224 struct s { 225 // Since there is no name in the declarator, the next symbol 226 // after the ':' must not be interpreted as a member name, but 227 // instead as a variable, type or function (SK_VCFT). 228 unsigned int :bits; 229 int named_member; 230 }; 231} 232 233// Symbols that are defined in the parameter list of a function definition can 234// be accessed in the body of the function, even if they are nested. 235int 236get_x(struct point3d { struct point3d_number { int v; } x, y, z; } arg) 237{ 238/* expect-1: warning: dubious tag declaration 'struct point3d' [85] */ 239/* expect-2: warning: dubious tag declaration 'struct point3d_number' [85] */ 240 static struct point3d local; 241 static struct point3d_number z; 242 return arg.x.v + local.x.v + z.v; 243} 244 245// Expressions of the form '(size_t)&null_ptr->member' are used by several 246// C implementations to implement the offsetof macro. 247void 248offsetof_on_array_member(void) 249{ 250 typedef struct { 251 int padding, plain, arr[2]; 252 } s1; 253 254 // Bit-fields must have a constant number of bits. 255 struct s2 { 256 unsigned int off_plain:(unsigned long)&((s1 *)0)->plain; 257 unsigned int off_arr:(unsigned long)&((s1 *)0)->arr; 258 unsigned int off_arr_0:(unsigned long)&((s1 *)0)->arr[0]; 259 unsigned int off_arr_3:(unsigned long)&((s1 *)0)->arr[3]; 260 }; 261 262 // Arrays may be variable-width, but the diagnostic reveals the size. 263 /* expect+1: error: negative array dimension (-4) [20] */ 264 typedef int off_plain[-(int)(unsigned long)&((s1 *)0)->plain]; 265 /* expect+1: error: negative array dimension (-8) [20] */ 266 typedef int off_arr[-(int)(unsigned long)&((s1 *)0)->arr]; 267 /* expect+1: error: negative array dimension (-8) [20] */ 268 typedef int off_arr_0[-(int)(unsigned long)&((s1 *)0)->arr[0]]; 269 /* expect+1: error: negative array dimension (-20) [20] */ 270 typedef int off_arr_3[-(int)(unsigned long)&((s1 *)0)->arr[3]]; 271} 272