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