Home | History | Annotate | Line # | Download | only in lint1
      1  1.18  rillig /*	$NetBSD: c23.c,v 1.18 2025/09/18 18:22:18 rillig Exp $	*/
      2   1.1  rillig # 3 "c23.c"
      3   1.1  rillig 
      4   1.1  rillig // Tests for the option -Ac23, which allows features from C23 and all earlier
      5   1.1  rillig // ISO standards, but none of the GNU extensions.
      6   1.1  rillig //
      7   1.1  rillig // See also:
      8   1.7  rillig //	c11.c
      9   1.3  rillig //	msg_353.c		for empty initializer braces
     10   1.1  rillig 
     11  1.15  rillig /* lint1-flags: -Ac23 -hw -X 351 */
     12   1.1  rillig 
     13   1.9  rillig 
     14   1.9  rillig int
     15   1.9  rillig bool_is_predefined_in_c23(void)
     16   1.9  rillig {
     17   1.9  rillig 	bool t = true;
     18   1.9  rillig 	bool f = false;
     19   1.9  rillig 	return (t == true ? 20 : 0) + (f == false ? 3 : 0);
     20   1.9  rillig }
     21   1.9  rillig 
     22   1.9  rillig int
     23   1.9  rillig c99_bool_is_still_valid_in_c23(void)
     24   1.9  rillig {
     25   1.9  rillig 	_Bool t = 1;
     26   1.9  rillig 	_Bool f = 0;
     27   1.9  rillig 	return (t == 1 ? 20 : 0) + (f == 0 ? 3 : 0);
     28   1.9  rillig }
     29   1.9  rillig 
     30   1.9  rillig 
     31  1.11  rillig bool
     32  1.11  rillig null_pointer_constant(const char *p, double dbl)
     33  1.11  rillig {
     34  1.11  rillig 	/* expect+1: error: operands of '!=' have incompatible types 'double' and 'pointer to void' [107] */
     35  1.11  rillig 	if (dbl != nullptr)
     36  1.11  rillig 		p++;
     37  1.11  rillig 	if (dbl > 0.0)
     38  1.11  rillig 		p++;
     39  1.11  rillig 	if (*p == '\0')
     40  1.11  rillig 		p = nullptr;
     41  1.11  rillig 	return p == nullptr;
     42  1.11  rillig }
     43  1.11  rillig 
     44  1.11  rillig 
     45  1.12  rillig void *
     46  1.12  rillig storage_class_in_compound_literal(void)
     47  1.12  rillig {
     48  1.12  rillig 	typedef struct node node;
     49  1.12  rillig 	struct node {
     50  1.12  rillig 		node *left;
     51  1.12  rillig 		int value;
     52  1.12  rillig 		node *right;
     53  1.12  rillig 	};
     54  1.12  rillig 
     55  1.12  rillig 	node *tree;
     56  1.12  rillig 	tree = &(static node){
     57  1.12  rillig 	    &(static node){
     58  1.12  rillig 		nullptr,
     59  1.12  rillig 		3,
     60  1.12  rillig 		nullptr,
     61  1.12  rillig 	    },
     62  1.12  rillig 	    5,
     63  1.12  rillig 	    nullptr,
     64  1.12  rillig 	};
     65  1.12  rillig 	return tree->left;
     66  1.12  rillig }
     67  1.12  rillig 
     68   1.1  rillig int
     69   1.3  rillig empty_initializer_braces(void)
     70   1.1  rillig {
     71   1.1  rillig 	struct s {
     72   1.1  rillig 		int member;
     73   1.1  rillig 	} s;
     74   1.1  rillig 
     75   1.2  rillig 	// Empty initializer braces were introduced in C23.
     76   1.1  rillig 	s = (struct s){};
     77   1.1  rillig 	s = (struct s){s.member};
     78   1.1  rillig 	return s.member;
     79   1.1  rillig }
     80   1.2  rillig 
     81   1.7  rillig 
     82   1.7  rillig _Static_assert(1 > 0, "string");
     83   1.7  rillig _Static_assert(1 > 0);
     84   1.7  rillig 
     85   1.7  rillig 
     86   1.2  rillig // The keyword 'thread_local' was introduced in C23.
     87   1.2  rillig thread_local int globally_visible;
     88   1.2  rillig 
     89   1.3  rillig // Thread-local functions don't make sense; lint allows them, though.
     90   1.2  rillig thread_local void
     91   1.2  rillig thread_local_function(void)
     92   1.2  rillig {
     93   1.2  rillig }
     94   1.2  rillig 
     95   1.2  rillig void
     96   1.2  rillig function(void)
     97   1.2  rillig {
     98   1.2  rillig 	// Not sure whether it makes sense to have a function-scoped
     99   1.2  rillig 	// thread-local variable.  Don't warn for now, let the compilers handle
    100   1.2  rillig 	// this case.
    101   1.2  rillig 	thread_local int function_scoped_thread_local;
    102   1.2  rillig }
    103   1.4  rillig 
    104   1.6  rillig // 'thread_local' can be combined with 'extern' and 'static', but with no other
    105   1.6  rillig // storage classes.  The other storage classes cannot be combined.
    106   1.4  rillig extern thread_local int extern_thread_local_1;
    107   1.4  rillig thread_local extern int extern_thread_local_2;
    108   1.8  rillig /* expect+1: warning: static variable 'static_thread_local_1' unused [226] */
    109   1.6  rillig static thread_local int static_thread_local_1;
    110   1.8  rillig /* expect+1: warning: static variable 'static_thread_local_2' unused [226] */
    111   1.6  rillig thread_local static int static_thread_local_2;
    112  1.13  rillig 
    113  1.13  rillig 
    114  1.13  rillig int
    115  1.13  rillig attributes(int i)
    116  1.13  rillig {
    117  1.13  rillig 	// An attribute specifier list may be empty.
    118  1.13  rillig 	[[]]i++;
    119  1.13  rillig 
    120  1.13  rillig 	// There may be leading or trailing commas.
    121  1.13  rillig 	[[,]]i++;
    122  1.13  rillig 
    123  1.13  rillig 	// There may be arbitrary commas around or between the attributes.
    124  1.13  rillig 	[[,,,,,]]i++;
    125  1.13  rillig 
    126  1.13  rillig 	// An attribute may be a plain identifier without arguments.
    127  1.13  rillig 	[[identifier]]i++;
    128  1.13  rillig 
    129  1.13  rillig 	// The identifier may be prefixed with one additional identifier.
    130  1.13  rillig 	[[prefix::identifier]]i++;
    131  1.13  rillig 
    132  1.13  rillig 	// An attribute may have empty arguments.
    133  1.13  rillig 	[[identifier()]]i++;
    134  1.13  rillig 
    135  1.13  rillig 	// The arguments of an attribute may be arbitrary tokens.
    136  1.13  rillig 	[[identifier([])]]i++;
    137  1.13  rillig 
    138  1.13  rillig 	// The commas in this "argument list" are ordinary punctuator tokens,
    139  1.13  rillig 	// they do not separate any arguments.
    140  1.13  rillig 	// The structure of the attribute argument is:
    141  1.13  rillig 	//	1. empty balanced token sequence between '[' and ']'
    142  1.13  rillig 	//	2. token ','
    143  1.13  rillig 	//	3. empty balanced token sequence between '{' and '}'
    144  1.13  rillig 	//	4. token ','
    145  1.13  rillig 	//	5. empty balanced token sequence between '(' and ')'
    146  1.13  rillig 	[[identifier([], {}, ())]]i++;
    147  1.13  rillig 
    148  1.13  rillig 	// Inside an argument, parentheses may be nested.
    149  1.13  rillig 	[[identifier(((((())))))]]i++;
    150  1.13  rillig 	// Inside an argument, brackets may be nested.
    151  1.13  rillig 	[[identifier([[[[[]]]]])]]i++;
    152  1.13  rillig 	// Inside an argument, braces may be nested.
    153  1.13  rillig 	[[identifier({{{{{}}}}})]]i++;
    154  1.13  rillig 
    155  1.13  rillig 	// An attribute argument may contain arbitrary punctuation.
    156  1.13  rillig 	[[identifier(++++ ? ? ? : : :: )]]i++;
    157  1.13  rillig 
    158  1.13  rillig 	// An attribute argument may contain constants and string literals.
    159  1.13  rillig 	[[identifier(0, 0.0, "hello" " " "world")]]i++;
    160  1.13  rillig 
    161  1.13  rillig 	// There may be multiple attribute specifier sequences in a row.
    162  1.13  rillig 	[[]][[]][[]]i++;
    163  1.13  rillig 
    164  1.17  rillig 	// An attribute may occur more than once.
    165  1.17  rillig 	[[
    166  1.17  rillig 		maybe_unused, maybe_unused, maybe_unused, maybe_unused,
    167  1.17  rillig 		maybe_unused, maybe_unused, maybe_unused, maybe_unused,
    168  1.17  rillig 		maybe_unused, maybe_unused, maybe_unused, maybe_unused,
    169  1.17  rillig 		maybe_unused, maybe_unused, maybe_unused, maybe_unused,
    170  1.17  rillig 		maybe_unused, maybe_unused, maybe_unused, maybe_unused,
    171  1.17  rillig 	]]i++;
    172  1.17  rillig 
    173  1.13  rillig 	return i;
    174  1.13  rillig }
    175  1.14  rillig 
    176  1.14  rillig typedef int number;
    177  1.14  rillig 
    178  1.14  rillig void
    179  1.14  rillig attributes_in_parameter_declaration(
    180  1.14  rillig     [[maybe_unused]] int int_param,
    181  1.14  rillig     [[maybe_unused]] const int const_int_param,
    182  1.14  rillig     [[maybe_unused]] number typedef_param,
    183  1.14  rillig     [[maybe_unused]] const number const_typedef_param)
    184  1.14  rillig {
    185  1.14  rillig }
    186  1.15  rillig 
    187  1.15  rillig int
    188  1.15  rillig attribute_in_switch_statement(int n)
    189  1.15  rillig {
    190  1.15  rillig 	switch (n) {
    191  1.15  rillig 	case 1:
    192  1.15  rillig 		n++;
    193  1.15  rillig 	/* expect+1: warning: fallthrough on case statement [220] */
    194  1.15  rillig 	case 2:
    195  1.15  rillig 		n++;
    196  1.15  rillig 		[[fallthrough]];
    197  1.15  rillig 	case 3:
    198  1.15  rillig 		n++;
    199  1.15  rillig 		[[fallthrough]];
    200  1.15  rillig 	default:
    201  1.15  rillig 		n++;
    202  1.15  rillig 	}
    203  1.15  rillig 	return n;
    204  1.15  rillig }
    205  1.18  rillig 
    206  1.18  rillig // C23 6.7.7.4p13 says that "()" is equivalent to "(void)".
    207  1.18  rillig void function_without_parameters();
    208