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