xref: /netbsd-src/tests/usr.bin/xlint/lint1/lang_level_c99.c (revision 656ffdf2e3864b68d292b6310a83df69189a876a)
1 /*	$NetBSD: lang_level_c99.c,v 1.6 2024/11/05 04:53:28 rillig Exp $	*/
2 # 3 "lang_level_c99.c"
3 
4 /*
5  * Tests that are specific to the C99 language level, in particular:
6  *
7  *	* syntax elements that were added in C99
8  *	* lint diagnostics that differ between the C90 and C99 language levels
9  *	* lint diagnostics that differ between the C99 and C11 language levels
10  */
11 
12 /* lint1-flags: -S -w -X 351 */
13 
14 /*
15  * Features that were added in the C99 standard, as listed in the C99 foreword.
16  *
17  * In the below comments, [-] means unsupported and [x] means supported.
18  */
19 
20 // [-] restricted character set support via digraphs and <iso646.h>
21 //
22 // Lint neither parses digraphs nor trigraphs.
23 
24 // [x] wide character library support in <wchar.h> and <wctype.h>
25 //
26 // On all supported platforms, 'wchar_t' == 'int'.
27 
28 const int wide_string[] = L"wide";
29 
30 // [x] more precise aliasing rules via effective type
31 //
32 // Irrelevant, as lint does not check the runtime behavior.
33 
34 // [x] restricted pointers
35 //
36 // Can be parsed, are otherwise ignored.
37 
38 // [-] variable length arrays
39 //
40 // Variable length arrays are handled as if the number of elements in the array
41 // were always 1.
42 
43 /* FIXME: Parameter 'n' _is_ actually used. */
44 /* expect+2: warning: parameter 'n' unused in function 'variable_length_arrays' [231] */
45 unsigned long long
46 variable_length_arrays(int n)
47 {
48 	int vla[n];
49 	/* FIXME: The array dimension is not constant, but still negative. */
50 	/* expect+1: error: negative array dimension (-4) [20] */
51 	typedef int sizeof_vla[-(int)sizeof(vla)];
52 	return sizeof(vla);
53 }
54 
55 // [x] flexible array members
56 //
57 // Flexible array members are parsed but not validated thoroughly.
58 
59 void
60 flexible_array_members(void)
61 {
62 	struct {
63 		int regular;
64 		int flexible[];
65 	} s = {
66 		0,
67 		// Flexible array member must not be initialized.  Lint does
68 		// not detect this, leaving the job to the C99 compiler.
69 		{ 1, 3, 4, }
70 	};
71 	/* expect+1: error: negative array dimension (-4) [20] */
72 	typedef int sizeof_s[-(int)sizeof(s)];
73 }
74 
75 // [x] static and type qualifiers in parameter array declarators
76 //
77 // Can be parsed, are otherwise ignored.
78 
79 // [-] complex (and imaginary) support in <complex.h>
80 //
81 // Lint does not keep track of which parts of a complex object are initialized.
82 //
83 // Lint does not support '_Imaginary'.
84 
85 // [x] type-generic math macros in <tgmath.h>
86 //
87 // Irrelevant, as lint only sees the preprocessed source code.
88 
89 // [x] the long long int type and library functions
90 //
91 // On all platforms supported by lint, 'long long' is 64 bits wide.  The other
92 // fixed-width types are 'char', 'short', 'int' and (only on 64-bit platforms)
93 // '__int128_t'.
94 //
95 // The lint standard libraries -lstdc and -lposix do not contain the
96 // functions added in C99.
97 
98 /* expect+1: error: negative array dimension (-1) [20] */
99 typedef int sizeof_char[-(int)sizeof(char)];
100 /* expect+1: error: negative array dimension (-2) [20] */
101 typedef int sizeof_short[-(int)sizeof(short)];
102 /* expect+1: error: negative array dimension (-4) [20] */
103 typedef int sizeof_int[-(int)sizeof(int)];
104 /* expect+1: error: negative array dimension (-8) [20] */
105 typedef int sizeof_long_long[-(int)sizeof(long long)];
106 
107 // [x] increased minimum translation limits
108 //
109 // Irrelevant, as lint does not have any hard-coded limits.
110 
111 // [x] additional floating-point characteristics in <float.h>
112 //
113 // Lint has very limited support for floating point numbers, as it fully relies
114 // on the host platform.  This is noticeable when cross-compiling between
115 // platforms with different size or representation of 'long double'.
116 
117 // [x] remove implicit int
118 //
119 // Lint parses old-style declarations and marks them as errors.
120 
121 // [x] reliable integer division
122 //
123 // The lint source code requires a C99 compiler, so when mapping the integer
124 // operations to those from the host platform, lint uses these.
125 
126 // [-] universal character names (\u and \U)
127 //
128 // No, as nothing in the NetBSD source tree uses this feature.
129 
130 // [-] extended identifiers
131 //
132 // No, as nothing in the NetBSD source tree uses this feature.
133 
134 // [x] hexadecimal floating-point constants and %a and %A printf/scanf
135 // conversion specifiers
136 
137 void pf();			/* no prototype parameters */
138 
139 void
140 hexadecimal_floating_point_constants(void)
141 {
142 	double hex = 0x1.0p34;
143 	pf("%s %a\n", "hex", hex);
144 }
145 
146 // [x] compound literals
147 //
148 // See d_c99_compound_literal_comma.c.
149 struct short_rect {
150 	short top, left, bottom, right;
151 };
152 
153 struct short_rect *rect_location(void);
154 
155 void
156 compound_literal(void)
157 {
158 	struct short_rect me = (struct short_rect){ 1, 2, 3, 4 };
159 	me.left = me.left;
160 	*rect_location() = (struct short_rect){ 1, 2, 3, 4 };
161 }
162 
163 // [x] designated initializers
164 //
165 // See init_c99.c.
166 
167 // [x] // comments
168 //
169 // Also supported in GCC mode.
170 
171 // [?] extended integer types and library functions in <inttypes.h> and
172 // <stdint.h>
173 //
174 // TODO
175 
176 // [x] remove implicit function declaration
177 
178 void
179 call_implicitly_declared_function(void)
180 {
181 	/* expect+1: error: function 'implicitly_declared_function' implicitly declared to return int [215] */
182 	implicitly_declared_function(0);
183 }
184 
185 // [x] preprocessor arithmetic done in intmax_t/uintmax_t
186 //
187 // Irrelevant, as lint only sees the preprocessed source code.
188 
189 // [x] mixed declarations and code
190 
191 // [x] new block scopes for selection and iteration statements
192 void
193 for_scope(void)
194 {
195 	// A for loop may have a declaration in its first part.
196 	for (int i = 0; i < 10; i++)
197 		continue;
198 
199 	// Test that the scope of the previous i has ended.
200 	for (int i = 0; i < 10; i++)
201 		continue;
202 }
203 
204 
205 // [?] integer constant type rules
206 //
207 // TODO
208 
209 // [?] integer promotion rules
210 //
211 // TODO
212 
213 // [x] macros with a variable number of arguments
214 //
215 // Irrelevant, as lint only sees the preprocessed source code.
216 
217 // [x] the vscanf family of functions in <stdio.h> and <wchar.h>
218 //
219 // Irrelevant, as typical C99 compilers already check these.
220 
221 // [x] additional math library functions in <math.h>
222 //
223 // Irrelevant, as lint does not check arithmetic expressions.
224 //
225 // Lint also does not generate its own standard library definition for libm.
226 
227 // [x] treatment of error conditions by math library functions
228 // (math_errhandling)
229 //
230 // Irrelevant, as lint does not check for error handling.
231 
232 // [x] floating-point environment access in <fenv.h>
233 //
234 // TODO
235 
236 // [x] IEC 60559 (also known as IEC 559 or IEEE arithmetic) support
237 //
238 // On platforms that conform to IEC 60559, lint performs the arithmetic
239 // operations accordingly.  When cross-compiling on a vax host for other target
240 // platforms, no such support is available.
241 
242 // [x] trailing comma allowed in enum declaration
243 //
244 // Yes, see the grammar rule 'enums_with_opt_comma'.
245 
246 // [-] %lf conversion specifier allowed in printf
247 //
248 // TODO: see tests/lint2/msg_013.exp.
249 
250 // [x] inline functions
251 //
252 // Yes, also allowed in GCC mode.
253 
254 // [x] the snprintf family of functions in <stdio.h>
255 //
256 // The snprintf functions are treated like all other functions.  The checks for
257 // matching format strings targets traditional C only and thus does not apply
258 // to these functions, as they have a prototype definition.
259 
260 // [x] boolean type in <stdbool.h>
261 //
262 // Yes.  Conversion to and from boolean follows 6.3.1.2.  See also the -T flag,
263 // which enables 'strict bool mode'.
264 
265 // [x] idempotent type qualifiers
266 //
267 // Lint warns about duplicate type qualifiers but accepts them otherwise.
268 
269 /* expect+1: warning: duplicate 'const' [10] */
270 const const int duplicate_type_qualifier = 2;
271 
272 // [x] empty macro arguments
273 //
274 // Irrelevant, as lint only sees the preprocessed source code.
275 
276 // [?] new structure type compatibility rules (tag compatibility)
277 //
278 // TODO
279 
280 // [x] additional predefined macro names
281 //
282 // Irrelevant, as lint only sees the preprocessed source code.
283 
284 // [-] _Pragma preprocessing operator
285 //
286 // No, not yet asked for.
287 
288 // [-] standard pragmas
289 //
290 // No, not yet asked for.
291 
292 // [x] __func__ predefined identifier
293 //
294 // Yes, see 'fallback_symbol'.
295 const char *
296 function_name(void)
297 {
298 	/* expect+1: error: negative array dimension (-14) [20] */
299 	typedef int reveal_size[-(int)sizeof(__func__)];
300 	return __func__;
301 }
302 
303 
304 // Since tree.c 1.504 from 2023-01-29 and before tree.c 1.591 from 2024-01-07,
305 // lint crashed because there was no "current function", even though the
306 // "block level" was not 0.
307 /* expect+1: error: '__func__' undefined [99] */
308 typedef int func_outside_function(int[sizeof(__func__)]);
309 
310 
311 // [x] va_copy macro
312 //
313 // Irrelevant, as lint only sees the preprocessed source code.
314 
315 // [x] additional strftime conversion specifiers
316 //
317 // Irrelevant, as lint does not check strftime in depth.
318 
319 // [?] LIA compatibility annex
320 //
321 // TODO
322 
323 // [x] deprecate ungetc at the beginning of a binary file
324 //
325 // Irrelevant, as lint's analysis is not that deep into the runtime behavior.
326 
327 // [x] remove deprecation of aliased array parameters
328 //
329 // Irrelevant, as lint does not check for aliasing.
330 
331 // [?] conversion of array to pointer not limited to lvalues
332 //
333 // TODO
334 
335 // [x] relaxed constraints on aggregate and union initialization
336 //
337 // Yes, struct and union members can be initialized with non-constant
338 // expressions.  Members that have struct or union type can be initialized with
339 // an expression of the same type.
340 
341 // [x] relaxed restrictions on portable header names
342 //
343 // Irrelevant, as lint only sees the preprocessed source code.
344 
345 // [x] return without expression not permitted in function that returns a value
346 // (and vice versa)
347 
348 void
349 return_no_expr(int x)
350 {
351 	x++;
352 	/* expect+1: error: void function 'return_no_expr' cannot return value [213] */
353 	return x;
354 }
355 
356 int
357 return_expr(void)
358 {
359 	/* expect+1: error: function 'return_expr' expects to return value [214] */
360 	return;
361 }
362