1 /* $NetBSD: c23.c,v 1.17 2024/11/30 11:27:20 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 -hw -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 // An attribute may occur more than once. 165 [[ 166 maybe_unused, maybe_unused, maybe_unused, maybe_unused, 167 maybe_unused, maybe_unused, maybe_unused, maybe_unused, 168 maybe_unused, maybe_unused, maybe_unused, maybe_unused, 169 maybe_unused, maybe_unused, maybe_unused, maybe_unused, 170 maybe_unused, maybe_unused, maybe_unused, maybe_unused, 171 ]]i++; 172 173 return i; 174 } 175 176 typedef int number; 177 178 void 179 attributes_in_parameter_declaration( 180 [[maybe_unused]] int int_param, 181 [[maybe_unused]] const int const_int_param, 182 [[maybe_unused]] number typedef_param, 183 [[maybe_unused]] const number const_typedef_param) 184 { 185 } 186 187 int 188 attribute_in_switch_statement(int n) 189 { 190 switch (n) { 191 case 1: 192 n++; 193 /* expect+1: warning: fallthrough on case statement [220] */ 194 case 2: 195 n++; 196 [[fallthrough]]; 197 case 3: 198 n++; 199 [[fallthrough]]; 200 default: 201 n++; 202 } 203 return n; 204 } 205