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