Home | History | Annotate | Line # | Download | only in lint1
      1 /*	$NetBSD: expr_cast.c,v 1.7 2025/04/12 15:49:49 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 invalid 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