Home | History | Annotate | Line # | Download | only in lint1
      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