Home | History | Annotate | Line # | Download | only in lint1
expr_cast.c revision 1.6.2.1
      1  1.6.2.1  perseant /*	$NetBSD: expr_cast.c,v 1.6.2.1 2025/08/02 05:58:14 perseant 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.2.1  perseant 	/* expect+2: error: function returns invalid 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