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