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