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