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