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