c23.c revision 1.14 1 1.14 rillig /* $NetBSD: c23.c,v 1.14 2024/06/17 04:14:02 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.1 rillig /* lint1-flags: -Ac23 -w -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.13 rillig return i;
165 1.13 rillig }
166 1.14 rillig
167 1.14 rillig typedef int number;
168 1.14 rillig
169 1.14 rillig void
170 1.14 rillig attributes_in_parameter_declaration(
171 1.14 rillig /* expect+1: warning: parameter 'int_param' unused in function 'attributes_in_parameter_declaration' [231] */
172 1.14 rillig [[maybe_unused]] int int_param,
173 1.14 rillig /* expect+1: warning: parameter 'const_int_param' unused in function 'attributes_in_parameter_declaration' [231] */
174 1.14 rillig [[maybe_unused]] const int const_int_param,
175 1.14 rillig /* expect+1: warning: parameter 'typedef_param' unused in function 'attributes_in_parameter_declaration' [231] */
176 1.14 rillig [[maybe_unused]] number typedef_param,
177 1.14 rillig /* expect+1: warning: parameter 'const_typedef_param' unused in function 'attributes_in_parameter_declaration' [231] */
178 1.14 rillig [[maybe_unused]] const number const_typedef_param)
179 1.14 rillig {
180 1.14 rillig }
181