Home | History | Annotate | Line # | Download | only in lint1
lang_level_c99.c revision 1.5.2.1
      1  1.5.2.1  perseant /*	$NetBSD: lang_level_c99.c,v 1.5.2.1 2025/08/02 05:58:15 perseant 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.5.2.1  perseant // 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