1 /* $NetBSD: expr_cast.c,v 1.6 2024/06/08 13:50:47 rillig Exp $ */ 2 # 3 "expr_cast.c" 3 4 /* 5 * Tests for value conversion using a cast-expression. 6 * 7 * K&R C does not mention any restrictions on the target type. 8 * C90 requires both the source type and the target type to be scalar. 9 * 10 * GCC allows casting to a struct type but there is no documentation about 11 * it at https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html. See 12 * c-typeck.c, function build_c_cast, RECORD_OR_UNION_TYPE_P. 13 */ 14 15 /* lint1-flags: -Sw -X 351 */ 16 17 struct S { 18 int member; 19 }; 20 21 struct S 22 cast(void) 23 { 24 struct S { 25 double incompatible; 26 } local = { 27 0.0 28 }; 29 30 /* expect+2: error: invalid cast from 'struct S' to 'struct S' [147] */ 31 /* expect+1: error: function 'cast' expects to return value [214] */ 32 return (struct S)local; 33 } 34 35 /* 36 * https://gnats.netbsd.org/22119 37 * 38 * Before 2021-02-28, lint crashed in cast() since the target type of the 39 * cast is NULL. 40 */ 41 void 42 cast_from_error(void) 43 { 44 void (*f1)(void); 45 46 /* expect+1: error: 'p' undefined [99] */ 47 f1 = (void (*)(void))p; 48 /* expect+2: error: function returns illegal type 'function(void) returning pointer to void' [15] */ 49 /* expect+1: error: invalid cast from 'int' to 'function() returning pointer to function(void) returning pointer to void' [147] */ 50 f1 = (void *()(void))p; /* crash before 2021-02-28 */ 51 } 52 53 /* 54 * Pointer casts had been valid lvalues in GCC before 4.0. 55 * 56 * https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues 57 * 58 * C99 6.5.4 "Cast operators" footnote 85 says "A cast does not yield an 59 * lvalue". 60 */ 61 62 void take_ptr(const void *); 63 64 void * 65 lvalue_cast(void *p) 66 { 67 struct str { 68 int member; 69 }; 70 71 /* expect+2: error: a cast does not yield an lvalue [163] */ 72 /* expect+1: error: left operand of '=' must be lvalue [114] */ 73 ((struct str *)p) = 0; 74 75 /* expect+2: error: a cast does not yield an lvalue [163] */ 76 /* expect+1: error: operand of '&' must be lvalue [114] */ 77 take_ptr(&(const void *)p); 78 79 return p; 80 } 81