1 1.11 rillig /* $NetBSD: c23.c,v 1.11 2024/05/09 11:08:07 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.1 rillig int 46 1.3 rillig empty_initializer_braces(void) 47 1.1 rillig { 48 1.1 rillig struct s { 49 1.1 rillig int member; 50 1.1 rillig } s; 51 1.1 rillig 52 1.2 rillig // Empty initializer braces were introduced in C23. 53 1.1 rillig s = (struct s){}; 54 1.1 rillig s = (struct s){s.member}; 55 1.1 rillig return s.member; 56 1.1 rillig } 57 1.2 rillig 58 1.7 rillig 59 1.7 rillig _Static_assert(1 > 0, "string"); 60 1.7 rillig _Static_assert(1 > 0); 61 1.7 rillig 62 1.7 rillig 63 1.2 rillig // The keyword 'thread_local' was introduced in C23. 64 1.2 rillig thread_local int globally_visible; 65 1.2 rillig 66 1.3 rillig // Thread-local functions don't make sense; lint allows them, though. 67 1.2 rillig thread_local void 68 1.2 rillig thread_local_function(void) 69 1.2 rillig { 70 1.2 rillig } 71 1.2 rillig 72 1.2 rillig void 73 1.2 rillig function(void) 74 1.2 rillig { 75 1.2 rillig // Not sure whether it makes sense to have a function-scoped 76 1.2 rillig // thread-local variable. Don't warn for now, let the compilers handle 77 1.2 rillig // this case. 78 1.2 rillig thread_local int function_scoped_thread_local; 79 1.2 rillig } 80 1.4 rillig 81 1.6 rillig // 'thread_local' can be combined with 'extern' and 'static', but with no other 82 1.6 rillig // storage classes. The other storage classes cannot be combined. 83 1.4 rillig extern thread_local int extern_thread_local_1; 84 1.4 rillig thread_local extern int extern_thread_local_2; 85 1.8 rillig /* expect+1: warning: static variable 'static_thread_local_1' unused [226] */ 86 1.6 rillig static thread_local int static_thread_local_1; 87 1.8 rillig /* expect+1: warning: static variable 'static_thread_local_2' unused [226] */ 88 1.6 rillig thread_local static int static_thread_local_2; 89