xref: /netbsd-src/tests/usr.bin/xlint/lint1/msg_259.c (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
1 /*	$NetBSD: msg_259.c,v 1.23 2023/07/09 10:42:07 rillig Exp $	*/
2 # 3 "msg_259.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: -g -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 void signed_long_long(long long);
35 void unsigned_long_long(unsigned long long);
36 
37 void
38 change_in_type_width(char c, int i, long l)
39 {
40 	plain_char(c);
41 	signed_int(c);
42 	/* No warning 259 on LP64, only on ILP32 */
43 	signed_long(c);
44 
45 	plain_char(i);		/* XXX: why no warning? */
46 	signed_int(i);
47 	/* No warning 259 on LP64, only on ILP32 */
48 	signed_long(i);
49 
50 	plain_char(l);		/* XXX: why no warning? */
51 	/* expect+1: ... from 'long' to 'int' due to prototype [259] */
52 	signed_int(l);
53 	signed_long(l);
54 }
55 
56 /*
57  * Converting a signed integer type to its corresponding unsigned integer
58  * type (C99 6.2.5p6) is usually not a problem since the actual values of the
59  * expressions are usually not anywhere near the maximum signed value.  From
60  * a technical standpoint, it is correct to warn here since even small
61  * negative numbers may result in very large positive numbers.
62  *
63  * A common case where it occurs is when the difference of two pointers is
64  * converted to size_t.  The type ptrdiff_t is defined to be signed, but in
65  * many practical cases, the expression is '(end - start)', which makes the
66  * resulting value necessarily positive.
67  */
68 void
69 small_integer_types(char c, signed char sc, unsigned char uc,
70 		    signed short ss, unsigned short us,
71 		    signed int si, unsigned int ui,
72 		    signed long long sll, unsigned long long ull)
73 {
74 	plain_char(c);
75 	plain_char(sc);
76 	plain_char(uc);
77 	plain_char(ss);
78 	plain_char(us);
79 	plain_char(si);
80 	plain_char(ui);
81 	plain_char(sll);
82 	plain_char(ull);
83 
84 	signed_char(c);
85 	signed_char(sc);
86 	signed_char(uc);
87 	signed_char(ss);
88 	signed_char(us);
89 	signed_char(si);
90 	signed_char(ui);
91 	signed_char(sll);
92 	signed_char(ull);
93 
94 	unsigned_char(c);
95 	unsigned_char(sc);
96 	unsigned_char(uc);
97 	unsigned_char(ss);
98 	unsigned_char(us);
99 	unsigned_char(si);
100 	unsigned_char(ui);
101 	unsigned_char(sll);
102 	unsigned_char(ull);
103 
104 	signed_short(c);
105 	signed_short(sc);
106 	signed_short(uc);
107 	signed_short(ss);
108 	signed_short(us);
109 	signed_short(si);
110 	signed_short(ui);
111 	signed_short(sll);
112 	signed_short(ull);
113 
114 	unsigned_short(c);
115 	unsigned_short(sc);
116 	unsigned_short(uc);
117 	unsigned_short(ss);
118 	unsigned_short(us);
119 	unsigned_short(si);
120 	unsigned_short(ui);
121 	unsigned_short(sll);
122 	unsigned_short(ull);
123 }
124 
125 /*
126  * This function tests, among others, the conversion from a signed integer
127  * type to its corresponding unsigned integer type.  Warning 259 is not
128  * about lossy integer conversions but about ABI calling conventions.
129  *
130  * A common case where a conversion from a signed integer type to its
131  * corresponding unsigned integer type occurs is when the difference of two
132  * pointers is converted to size_t.  The type ptrdiff_t is defined to be
133  * signed, but in many practical cases, the expression is '(end - start)',
134  * which makes the resulting value necessarily positive.
135  */
136 void
137 signed_to_unsigned(int si, long sl, long long sll)
138 {
139 	/* expect+1: warning: argument 1 is converted from 'int' to 'unsigned int' due to prototype [259] */
140 	unsigned_int(si);
141 
142 	/* expect+1: warning: argument 1 is converted from 'long' to 'unsigned int' due to prototype [259] */
143 	unsigned_int(sl);
144 
145 	/* expect+1: warning: argument 1 is converted from 'long long' to 'unsigned int' due to prototype [259] */
146 	unsigned_int(sll);
147 
148 	/*
149 	 * No warning here.  Even though 'unsigned long' is 64 bits wide, it
150 	 * cannot represent negative 32-bit values.  This lossy conversion is
151 	 * covered by message 297 instead, which requires nonstandard flags.
152 	 */
153 	unsigned_long(si);
154 
155 	/* expect+1: warning: argument 1 is converted from 'long' to 'unsigned long' due to prototype [259] */
156 	unsigned_long(sl);
157 	/* expect+1: warning: argument 1 is converted from 'long long' to 'unsigned long' due to prototype [259] */
158 	unsigned_long(sll);
159 
160 	/*
161 	 * No warning here.  Even though 'unsigned long long' is 64 bits
162 	 * wide, it cannot represent negative 32-bit values.  This lossy
163 	 * conversion is covered by message 297 instead, which requires
164 	 * nonstandard flags.
165 	 */
166 	unsigned_long_long(si);
167 
168 	/* expect+1: warning: argument 1 is converted from 'long' to 'unsigned long long' due to prototype [259] */
169 	unsigned_long_long(sl);
170 
171 	/* expect+1: warning: argument 1 is converted from 'long long' to 'unsigned long long' due to prototype [259] */
172 	unsigned_long_long(sll);
173 }
174 
175 void
176 unsigned_to_signed(unsigned int ui, unsigned long ul, unsigned long long ull)
177 {
178 	/* expect+1: warning: argument 1 is converted from 'unsigned int' to 'int' due to prototype [259] */
179 	signed_int(ui);
180 	/* expect+1: warning: argument 1 is converted from 'unsigned long' to 'int' due to prototype [259] */
181 	signed_int(ul);
182 	/* expect+1: warning: argument 1 is converted from 'unsigned long long' to 'int' due to prototype [259] */
183 	signed_int(ull);
184 	signed_long(ui);
185 	/* expect+1: warning: argument 1 is converted from 'unsigned long' to 'long' due to prototype [259] */
186 	signed_long(ul);
187 	/* expect+1: warning: argument 1 is converted from 'unsigned long long' to 'long' due to prototype [259] */
188 	signed_long(ull);
189 	signed_long_long(ui);
190 	/* expect+1: warning: argument 1 is converted from 'unsigned long' to 'long long' due to prototype [259] */
191 	signed_long_long(ul);
192 	/* expect+1: warning: argument 1 is converted from 'unsigned long long' to 'long long' due to prototype [259] */
193 	signed_long_long(ull);
194 }
195 
196 void
197 signed_to_signed(signed int si, signed long sl, signed long long sll)
198 {
199 	signed_int(si);
200 	/* expect+1: warning: argument 1 is converted from 'long' to 'int' due to prototype [259] */
201 	signed_int(sl);
202 	/* expect+1: warning: argument 1 is converted from 'long long' to 'int' due to prototype [259] */
203 	signed_int(sll);
204 	signed_long(si);
205 	signed_long(sl);
206 	/* expect+1: warning: argument 1 is converted from 'long long' to 'long' due to prototype [259] */
207 	signed_long(sll);
208 	signed_long_long(si);
209 	/* expect+1: warning: argument 1 is converted from 'long' to 'long long' due to prototype [259] */
210 	signed_long_long(sl);
211 	signed_long_long(sll);
212 }
213 
214 void
215 unsigned_to_unsigned(unsigned int ui, unsigned long ul, unsigned long long ull)
216 {
217 	unsigned_int(ui);
218 	/* expect+1: warning: argument 1 is converted from 'unsigned long' to 'unsigned int' due to prototype [259] */
219 	unsigned_int(ul);
220 	/* expect+1: warning: argument 1 is converted from 'unsigned long long' to 'unsigned int' due to prototype [259] */
221 	unsigned_int(ull);
222 	unsigned_long(ui);
223 	unsigned_long(ul);
224 	/* expect+1: warning: argument 1 is converted from 'unsigned long long' to 'unsigned long' due to prototype [259] */
225 	unsigned_long(ull);
226 	unsigned_long_long(ui);
227 	/* expect+1: warning: argument 1 is converted from 'unsigned long' to 'unsigned long long' due to prototype [259] */
228 	unsigned_long_long(ul);
229 	unsigned_long_long(ull);
230 }
231 
232 void
233 pass_sizeof_as_smaller_type(void)
234 {
235 	/*
236 	 * Even though the expression has type size_t, it has a constant
237 	 * value that fits effortless into an 'unsigned int', it's so small
238 	 * that it would even fit into a 3-bit bit-field, so lint's warning
239 	 * may seem wrong here.
240 	 *
241 	 * This warning 259 is not about lossy integer conversion though but
242 	 * instead covers calling conventions that may differ between integer
243 	 * types of different sizes, and from that point of view, the
244 	 * constant, even though its value would fit in an unsigned int, is
245 	 * still passed as size_t.
246 	 */
247 	/* expect+1: warning: argument 1 is converted from 'unsigned long' to 'unsigned int' due to prototype [259] */
248 	unsigned_int(sizeof(int));
249 }
250