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