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