xref: /netbsd-src/tests/usr.bin/xlint/lint1/msg_259_c90.c (revision 4a29af3e7e781de02b66d044b90aebd888ee3694)
1 /*	$NetBSD: msg_259_c90.c,v 1.6 2023/07/09 10:42:07 rillig Exp $	*/
2 # 3 "msg_259_c90.c"
3 
4 /* Test for message: argument %d is converted from '%s' to '%s' due to prototype [259] */
5 
6 /*
7  * This warning detects function calls that are translated in very different
8  * translation environments, one where prototypes are omitted, and one where
9  * prototypes are active.  It is possible to make such code interoperable,
10  * but that requires that each argument is converted to its proper type by
11  * the caller of the function.
12  *
13  * When lint is run with the '-s' flag, it no longer warns about code with
14  * incompatibilities between traditional C and C90, therefore this test omits
15  * all of the options '-t', '-s', '-S' and '-Ac11'.
16  *
17  * See also msg_297, which is about lossy integer conversions, but that
18  * requires the flags -a -p -P, which are not enabled in the default NetBSD
19  * build.
20  */
21 
22 /* lint1-only-if: lp64 */
23 /* lint1-flags: -h -w -X 351 */
24 
25 void plain_char(char);
26 void signed_char(signed char);
27 void unsigned_char(unsigned char);
28 void signed_short(signed short);
29 void unsigned_short(unsigned short);
30 void signed_int(int);
31 void unsigned_int(unsigned int);
32 void signed_long(long);
33 void unsigned_long(unsigned long);
34 /* No 'long long' since it requires C99. */
35 
36 void
change_in_type_width(char c,int i,long l)37 change_in_type_width(char c, int i, long l)
38 {
39 	plain_char(c);
40 	signed_int(c);
41 	/* No warning 259 on LP64, only on ILP32 */
42 	signed_long(c);
43 
44 	plain_char(i);		/* XXX: why no warning? */
45 	signed_int(i);
46 	/* No warning 259 on LP64, only on ILP32 */
47 	signed_long(i);
48 
49 	plain_char(l);		/* XXX: why no warning? */
50 	/* expect+1: ... from 'long' to 'int' due to prototype [259] */
51 	signed_int(l);
52 	signed_long(l);
53 }
54 
55 /*
56  * Converting a signed integer type to its corresponding unsigned integer
57  * type (C99 6.2.5p6) is usually not a problem since the actual values of the
58  * expressions are usually not anywhere near the maximum signed value.  From
59  * a technical standpoint, it is correct to warn here since even small
60  * negative numbers may result in very large positive numbers.
61  *
62  * A common case where it occurs is when the difference of two pointers is
63  * converted to size_t.  The type ptrdiff_t is defined to be signed, but in
64  * many practical cases, the expression is '(end - start)', which makes the
65  * resulting value necessarily positive.
66  */
67 void
small_integer_types(char c,signed char sc,unsigned char uc,signed short ss,unsigned short us,signed int si,unsigned int ui,signed long sl,unsigned long ul)68 small_integer_types(char c, signed char sc, unsigned char uc,
69 		    signed short ss, unsigned short us,
70 		    signed int si, unsigned int ui,
71 		    signed long sl, unsigned long ul)
72 {
73 	plain_char(c);
74 	plain_char(sc);
75 	plain_char(uc);
76 	plain_char(ss);
77 	plain_char(us);
78 	plain_char(si);
79 	plain_char(ui);
80 	plain_char(sl);
81 	plain_char(ul);
82 
83 	signed_char(c);
84 	signed_char(sc);
85 	signed_char(uc);
86 	signed_char(ss);
87 	signed_char(us);
88 	signed_char(si);
89 	signed_char(ui);
90 	signed_char(sl);
91 	signed_char(ul);
92 
93 	unsigned_char(c);
94 	unsigned_char(sc);
95 	unsigned_char(uc);
96 	unsigned_char(ss);
97 	unsigned_char(us);
98 	unsigned_char(si);
99 	unsigned_char(ui);
100 	unsigned_char(sl);
101 	unsigned_char(ul);
102 
103 	signed_short(c);
104 	signed_short(sc);
105 	signed_short(uc);
106 	signed_short(ss);
107 	signed_short(us);
108 	signed_short(si);
109 	signed_short(ui);
110 	signed_short(sl);
111 	signed_short(ul);
112 
113 	unsigned_short(c);
114 	unsigned_short(sc);
115 	unsigned_short(uc);
116 	unsigned_short(ss);
117 	unsigned_short(us);
118 	unsigned_short(si);
119 	unsigned_short(ui);
120 	unsigned_short(sl);
121 	unsigned_short(ul);
122 }
123 
124 /*
125  * This function tests, among others, the conversion from a signed integer
126  * type to its corresponding unsigned integer type.  Warning 259 is not
127  * about lossy integer conversions but about ABI calling conventions.
128  *
129  * A common case where a conversion from a signed integer type to its
130  * corresponding unsigned integer type occurs is when the difference of two
131  * pointers is converted to size_t.  The type ptrdiff_t is defined to be
132  * signed, but in many practical cases, the expression is '(end - start)',
133  * which makes the resulting value necessarily positive.
134  */
135 void
signed_to_unsigned(int si,long sl)136 signed_to_unsigned(int si, long sl)
137 {
138 	/* expect+1: warning: argument 1 is converted from 'int' to 'unsigned int' due to prototype [259] */
139 	unsigned_int(si);
140 
141 	/* expect+1: warning: argument 1 is converted from 'long' to 'unsigned int' due to prototype [259] */
142 	unsigned_int(sl);
143 
144 	/*
145 	 * No warning here.  Even though 'unsigned long' is 64 bits wide, it
146 	 * cannot represent negative 32-bit values.  This lossy conversion is
147 	 * covered by message 297 instead, which requires nonstandard flags.
148 	 */
149 	unsigned_long(si);
150 
151 	/* expect+1: warning: argument 1 is converted from 'long' to 'unsigned long' due to prototype [259] */
152 	unsigned_long(sl);
153 }
154 
155 void
unsigned_to_signed(unsigned int ui,unsigned long ul)156 unsigned_to_signed(unsigned int ui, unsigned long ul)
157 {
158 	/* expect+1: warning: argument 1 is converted from 'unsigned int' to 'int' due to prototype [259] */
159 	signed_int(ui);
160 	/* expect+1: warning: argument 1 is converted from 'unsigned long' to 'int' due to prototype [259] */
161 	signed_int(ul);
162 	signed_long(ui);
163 	/* expect+1: warning: argument 1 is converted from 'unsigned long' to 'long' due to prototype [259] */
164 	signed_long(ul);
165 }
166 
167 void
signed_to_signed(signed int si,signed long sl)168 signed_to_signed(signed int si, signed long sl)
169 {
170 	signed_int(si);
171 	/* expect+1: warning: argument 1 is converted from 'long' to 'int' due to prototype [259] */
172 	signed_int(sl);
173 	signed_long(si);
174 	signed_long(sl);
175 }
176 
177 void
unsigned_to_unsigned(unsigned int ui,unsigned long ul)178 unsigned_to_unsigned(unsigned int ui, unsigned long ul)
179 {
180 	unsigned_int(ui);
181 	/* expect+1: warning: argument 1 is converted from 'unsigned long' to 'unsigned int' due to prototype [259] */
182 	unsigned_int(ul);
183 	unsigned_long(ui);
184 	unsigned_long(ul);
185 }
186 
187 void
pass_sizeof_as_smaller_type(void)188 pass_sizeof_as_smaller_type(void)
189 {
190 	/*
191 	 * Even though the expression has type size_t, it has a constant
192 	 * value that fits effortless into an 'unsigned int', it's so small
193 	 * that it would even fit into a 3-bit bit-field, so lint's warning
194 	 * may seem wrong here.
195 	 *
196 	 * This warning 259 is not about lossy integer conversion though but
197 	 * instead covers calling conventions that may differ between integer
198 	 * types of different sizes, and from that point of view, the
199 	 * constant, even though its value would fit in an unsigned int, is
200 	 * still passed as size_t.
201 	 */
202 	/* expect+1: warning: argument 1 is converted from 'unsigned long' to 'unsigned int' due to prototype [259] */
203 	unsigned_int(sizeof(int));
204 }
205