xref: /netbsd-src/tests/usr.bin/xlint/lint1/expr_cast.c (revision 360641f995d7499cd0671fd1b81a69e4a9f1f07a)
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
cast(void)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
cast_from_error(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 *
lvalue_cast(void * p)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