Home | History | Annotate | Line # | Download | only in lint1
msg_247.c revision 1.6
      1 /*	$NetBSD: msg_247.c,v 1.6 2021/03/26 16:19:43 rillig Exp $	*/
      2 # 3 "msg_247.c"
      3 
      4 // Test for message: pointer cast from '%s' to '%s' may be troublesome [247]
      5 
      6 /* lint1-extra-flags: -c */
      7 
      8 /* example taken from Xlib.h */
      9 typedef struct {
     10 	int id;
     11 } *PDisplay;
     12 
     13 struct Other {
     14 	int id;
     15 };
     16 
     17 void
     18 example(struct Other *arg)
     19 {
     20 	PDisplay display;
     21 
     22 	/*
     23 	 * XXX: The target type is reported as 'struct <unnamed>'.  In cases
     24 	 *  like these, it would be helpful to print at least the type name
     25 	 *  of the pointer.  This type name though is discarded immediately
     26 	 *  when the parser reduces 'T_TYPENAME clrtyp' to 'clrtyp_typespec'.
     27 	 *  After that, the target type of the cast is just an unnamed struct,
     28 	 *  with no hint at all that there is a typedef for a pointer to the
     29 	 *  struct.
     30 	 */
     31 	display = (PDisplay)arg;	/* expect: 247 */
     32 }
     33 
     34 /*
     35  * C code with a long history that has existed in pre-C90 times already often
     36  * uses 'pointer to char' where modern code would use 'pointer to void'.
     37  * Since 'char' is the most general underlying type, there is nothing wrong
     38  * with casting to it.  An example for this type of code is X11.
     39  *
     40  * Casting to 'pointer to char' may also be used by programmers who don't know
     41  * about endianness, but that's not something lint can do anything about.  The
     42  * code for these two use cases looks exactly the same, so lint errs on the
     43  * side of fewer false positive warnings here. (after fixing the FIXME below)
     44  */
     45 char *
     46 cast_to_char_pointer(struct Other *arg)
     47 {
     48 	return (char *)arg;		/* expect: 247 *//* FIXME */
     49 }
     50 
     51 /*
     52  * In traditional C there was 'unsigned char' as well, so the same reasoning
     53  * as for plain 'char' applies here.
     54  */
     55 unsigned char *
     56 cast_to_unsigned_char_pointer(struct Other *arg)
     57 {
     58 	return (unsigned char *)arg;	/* expect: 247 *//* FIXME */
     59 }
     60 
     61 /*
     62  * Traditional C does not have the type specifier 'signed', which means that
     63  * this type cannot be used by old code.  Therefore warn about this.  All code
     64  * that triggers this warning should do the intermediate cast via 'void
     65  * pointer'.
     66  */
     67 signed char *
     68 cast_to_signed_char_pointer(struct Other *arg)
     69 {
     70 	return (signed char *)arg;	/* expect: 247 */
     71 }
     72 
     73 char *
     74 cast_to_void_pointer_then_to_char_pointer(struct Other *arg)
     75 {
     76 	return (char *)(void *)arg;
     77 }
     78