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