1 /* { dg-options "-Wformat -fdiagnostics-show-caret" } */
2
3 #include "format.h"
4
5 /* Various format tests, some containing type mismatches. Verify that for
6 the type mismatch cases that we offer "good" suggestions. Specifically,
7 any suggestions should preserve flags characters, field width and precision,
8 and, if possible, the conversion specifier character, whilst giving a
9 corrected length modifier appropriate to the argument type. */
10
11 /* Tests of "x" without a length modifier, with various param types.
12 Suggestions should preserve the "x" for integer arguments. */
13
14 void
test_x(char * d,int iexpr,unsigned int uiexpr,long lexpr,unsigned long ulexpr,long long llexpr,unsigned long long ullexpr,float fexpr,double dexpr,long double ldexpr,void * ptr)15 test_x (char *d,
16 int iexpr, unsigned int uiexpr,
17 long lexpr, unsigned long ulexpr,
18 long long llexpr, unsigned long long ullexpr,
19 float fexpr, double dexpr, long double ldexpr,
20 void *ptr)
21 {
22 /* Integer arguments. */
23
24 sprintf (d, " %-8x ", iexpr);
25 sprintf (d, " %-8x ", uiexpr);
26
27 sprintf (d, " %-8x ", lexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long int'" } */
28 /* { dg-begin-multiline-output "" }
29 sprintf (d, " %-8x ", lexpr);
30 ~~~^ ~~~~~
31 | |
32 | long int
33 unsigned int
34 %-8lx
35 { dg-end-multiline-output "" } */
36 sprintf (d, " %-8x ", ulexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long unsigned int'" } */
37 /* { dg-begin-multiline-output "" }
38 sprintf (d, " %-8x ", ulexpr);
39 ~~~^ ~~~~~~
40 | |
41 | long unsigned int
42 unsigned int
43 %-8lx
44 { dg-end-multiline-output "" } */
45
46 sprintf (d, " %-8x ", llexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long long int'" } */
47 /* { dg-begin-multiline-output "" }
48 sprintf (d, " %-8x ", llexpr);
49 ~~~^ ~~~~~~
50 | |
51 | long long int
52 unsigned int
53 %-8llx
54 { dg-end-multiline-output "" } */
55 sprintf (d, " %-8x ", ullexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long long unsigned int'" } */
56 /* { dg-begin-multiline-output "" }
57 sprintf (d, " %-8x ", ullexpr);
58 ~~~^ ~~~~~~~
59 | |
60 | long long unsigned int
61 unsigned int
62 %-8llx
63 { dg-end-multiline-output "" } */
64
65 /* Floating-point arguments. */
66
67 sprintf (d, " %-8x ", fexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'double'" } */
68 /* { dg-begin-multiline-output "" }
69 sprintf (d, " %-8x ", fexpr);
70 ~~~^ ~~~~~
71 | |
72 | double
73 unsigned int
74 %-8f
75 { dg-end-multiline-output "" } */
76 sprintf (d, " %-8x ", dexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'double'" } */
77 /* { dg-begin-multiline-output "" }
78 sprintf (d, " %-8x ", dexpr);
79 ~~~^ ~~~~~
80 | |
81 | double
82 unsigned int
83 %-8f
84 { dg-end-multiline-output "" } */
85 sprintf (d, " %-8x ", ldexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long double'" } */
86 /* { dg-begin-multiline-output "" }
87 sprintf (d, " %-8x ", ldexpr);
88 ~~~^ ~~~~~~
89 | |
90 | long double
91 unsigned int
92 %-8Lf
93 { dg-end-multiline-output "" } */
94
95 /* Pointer. */
96 sprintf (d, " %-8x ", ptr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'void \\*'" } */
97 /* { dg-begin-multiline-output "" }
98 sprintf (d, " %-8x ", ptr);
99 ~~~^ ~~~
100 | |
101 | void *
102 unsigned int
103 %-8p
104 { dg-end-multiline-output "" } */
105
106 /* Something unrecognized. */
107 struct s { int i; };
108 struct s s;
109 sprintf (d, " %-8x ", s); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'struct s'" } */
110 /* { dg-begin-multiline-output "" }
111 sprintf (d, " %-8x ", s);
112 ~~~^ ~
113 | |
114 | struct s
115 unsigned int
116 { dg-end-multiline-output "" } */
117 }
118
119 /* Tests of "x" with "l", with various param types.
120 Suggestions should preserve the "x" for integer arguments. */
121
122 void
test_lx(char * d,int iexpr,unsigned int uiexpr,long lexpr,unsigned long ulexpr,long long llexpr,unsigned long long ullexpr,float fexpr,double dexpr,long double ldexpr)123 test_lx (char *d,
124 int iexpr, unsigned int uiexpr,
125 long lexpr, unsigned long ulexpr,
126 long long llexpr, unsigned long long ullexpr,
127 float fexpr, double dexpr, long double ldexpr)
128 {
129 /* Integer arguments. */
130
131 sprintf (d, " %-8lx ", iexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'int'" } */
132 /* { dg-begin-multiline-output "" }
133 sprintf (d, " %-8lx ", iexpr);
134 ~~~~^ ~~~~~
135 | |
136 | int
137 long unsigned int
138 %-8x
139 { dg-end-multiline-output "" } */
140 sprintf (d, " %-8lx ", uiexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int'" } */
141 /* { dg-begin-multiline-output "" }
142 sprintf (d, " %-8lx ", uiexpr);
143 ~~~~^ ~~~~~~
144 | |
145 | unsigned int
146 long unsigned int
147 %-8x
148 { dg-end-multiline-output "" } */
149
150 sprintf (d, " %-8lx ", lexpr);
151 sprintf (d, " %-8lx ", ulexpr);
152
153 sprintf (d, " %-8lx ", llexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long long int'" } */
154 /* { dg-begin-multiline-output "" }
155 sprintf (d, " %-8lx ", llexpr);
156 ~~~~^ ~~~~~~
157 | |
158 | long long int
159 long unsigned int
160 %-8llx
161 { dg-end-multiline-output "" } */
162 sprintf (d, " %-8lx ", ullexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long long unsigned int'" } */
163 /* { dg-begin-multiline-output "" }
164 sprintf (d, " %-8lx ", ullexpr);
165 ~~~~^ ~~~~~~~
166 | |
167 | long long unsigned int
168 long unsigned int
169 %-8llx
170 { dg-end-multiline-output "" } */
171
172 /* Floating-point arguments. */
173
174 sprintf (d, " %-8lx ", fexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'double'" } */
175 /* { dg-begin-multiline-output "" }
176 sprintf (d, " %-8lx ", fexpr);
177 ~~~~^ ~~~~~
178 | |
179 | double
180 long unsigned int
181 %-8f
182 { dg-end-multiline-output "" } */
183 sprintf (d, " %-8lx ", dexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'double'" } */
184 /* { dg-begin-multiline-output "" }
185 sprintf (d, " %-8lx ", dexpr);
186 ~~~~^ ~~~~~
187 | |
188 | double
189 long unsigned int
190 %-8f
191 { dg-end-multiline-output "" } */
192 sprintf (d, " %-8lx ", ldexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long double'" } */
193 /* { dg-begin-multiline-output "" }
194 sprintf (d, " %-8lx ", ldexpr);
195 ~~~~^ ~~~~~~
196 | |
197 | long double
198 long unsigned int
199 %-8Lf
200 { dg-end-multiline-output "" } */
201 }
202
203 /* Tests of "o" without a length modifier, with various param types.
204 Suggestions should preserve the "o" for integer arguments. */
205
206 void
test_o(char * d,int iexpr,unsigned int uiexpr,long lexpr,unsigned long ulexpr,long long llexpr,unsigned long long ullexpr)207 test_o (char *d,
208 int iexpr, unsigned int uiexpr,
209 long lexpr, unsigned long ulexpr,
210 long long llexpr, unsigned long long ullexpr)
211 {
212 /* Integer arguments. */
213
214 sprintf (d, " %-8o ", iexpr);
215 sprintf (d, " %-8o ", uiexpr);
216
217 sprintf (d, " %-8o ", lexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long int'" } */
218 /* { dg-begin-multiline-output "" }
219 sprintf (d, " %-8o ", lexpr);
220 ~~~^ ~~~~~
221 | |
222 | long int
223 unsigned int
224 %-8lo
225 { dg-end-multiline-output "" } */
226 sprintf (d, " %-8o ", ulexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long unsigned int'" } */
227 /* { dg-begin-multiline-output "" }
228 sprintf (d, " %-8o ", ulexpr);
229 ~~~^ ~~~~~~
230 | |
231 | long unsigned int
232 unsigned int
233 %-8lo
234 { dg-end-multiline-output "" } */
235
236 sprintf (d, " %-8o ", llexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long long int'" } */
237 /* { dg-begin-multiline-output "" }
238 sprintf (d, " %-8o ", llexpr);
239 ~~~^ ~~~~~~
240 | |
241 | long long int
242 unsigned int
243 %-8llo
244 { dg-end-multiline-output "" } */
245 sprintf (d, " %-8o ", ullexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long long unsigned int'" } */
246 /* { dg-begin-multiline-output "" }
247 sprintf (d, " %-8o ", ullexpr);
248 ~~~^ ~~~~~~~
249 | |
250 | long long unsigned int
251 unsigned int
252 %-8llo
253 { dg-end-multiline-output "" } */
254 }
255
256 /* Tests of "o" with "l", with various param types.
257 Suggestions should preserve the "o" for integer arguments. */
258
259 void
test_lo(char * d,int iexpr,unsigned int uiexpr,long lexpr,unsigned long ulexpr,long long llexpr,unsigned long long ullexpr)260 test_lo (char *d,
261 int iexpr, unsigned int uiexpr,
262 long lexpr, unsigned long ulexpr,
263 long long llexpr, unsigned long long ullexpr)
264 {
265 /* Integer arguments. */
266
267 sprintf (d, " %-8lo ", iexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'int'" } */
268 /* { dg-begin-multiline-output "" }
269 sprintf (d, " %-8lo ", iexpr);
270 ~~~~^ ~~~~~
271 | |
272 | int
273 long unsigned int
274 %-8o
275 { dg-end-multiline-output "" } */
276 sprintf (d, " %-8lo ", uiexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int'" } */
277 /* { dg-begin-multiline-output "" }
278 sprintf (d, " %-8lo ", uiexpr);
279 ~~~~^ ~~~~~~
280 | |
281 | unsigned int
282 long unsigned int
283 %-8o
284 { dg-end-multiline-output "" } */
285
286 sprintf (d, " %-8lo ", lexpr);
287 sprintf (d, " %-8lo ", ulexpr);
288
289 sprintf (d, " %-8lo ", llexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'long long int'" } */
290 /* { dg-begin-multiline-output "" }
291 sprintf (d, " %-8lo ", llexpr);
292 ~~~~^ ~~~~~~
293 | |
294 | long long int
295 long unsigned int
296 %-8llo
297 { dg-end-multiline-output "" } */
298 sprintf (d, " %-8lo ", ullexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'long long unsigned int'" } */
299 /* { dg-begin-multiline-output "" }
300 sprintf (d, " %-8lo ", ullexpr);
301 ~~~~^ ~~~~~~~
302 | |
303 | long long unsigned int
304 long unsigned int
305 %-8llo
306 { dg-end-multiline-output "" } */
307 }
308
309 /* Tests of "e" without a length modifier, with various param types.
310 Suggestions should preserve the "e" for float arguments. */
311
312 void
test_e(char * d,int iexpr,float fexpr,double dexpr,long double ldexpr)313 test_e (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
314 {
315 /* Integer arguments. */
316
317 sprintf (d, " %-8e ", iexpr); /* { dg-warning "20: format '%e' expects argument of type 'double', but argument 3 has type 'int'" } */
318 /* { dg-begin-multiline-output "" }
319 sprintf (d, " %-8e ", iexpr);
320 ~~~^ ~~~~~
321 | |
322 | int
323 double
324 %-8d
325 { dg-end-multiline-output "" } */
326
327 /* Floating-point arguments. */
328
329 sprintf (d, " %-8e ", fexpr);
330 sprintf (d, " %-8e ", dexpr);
331 sprintf (d, " %-8e ", ldexpr); /* { dg-warning "20: format '%e' expects argument of type 'double', but argument 3 has type 'long double'" } */
332 /* { dg-begin-multiline-output "" }
333 sprintf (d, " %-8e ", ldexpr);
334 ~~~^ ~~~~~~
335 | |
336 | long double
337 double
338 %-8Le
339 { dg-end-multiline-output "" } */
340 }
341
342 /* Tests of "e" with "L", with various param types.
343 Suggestions should preserve the "e" for float arguments. */
344
345 void
test_Le(char * d,int iexpr,float fexpr,double dexpr,long double ldexpr)346 test_Le (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
347 {
348 /* Integer arguments. */
349
350 sprintf (d, " %-8Le ", iexpr); /* { dg-warning "21: format '%Le' expects argument of type 'long double', but argument 3 has type 'int'" } */
351 /* { dg-begin-multiline-output "" }
352 sprintf (d, " %-8Le ", iexpr);
353 ~~~~^ ~~~~~
354 | |
355 | int
356 long double
357 %-8d
358 { dg-end-multiline-output "" } */
359
360 /* Floating-point arguments. */
361
362 sprintf (d, " %-8Le ", fexpr); /* { dg-warning "21: format '%Le' expects argument of type 'long double', but argument 3 has type 'double'" } */
363 /* { dg-begin-multiline-output "" }
364 sprintf (d, " %-8Le ", fexpr);
365 ~~~~^ ~~~~~
366 | |
367 | double
368 long double
369 %-8e
370 { dg-end-multiline-output "" } */
371
372 sprintf (d, " %-8Le ", dexpr); /* { dg-warning "21: format '%Le' expects argument of type 'long double', but argument 3 has type 'double'" } */
373 /* { dg-begin-multiline-output "" }
374 sprintf (d, " %-8Le ", dexpr);
375 ~~~~^ ~~~~~
376 | |
377 | double
378 long double
379 %-8e
380 { dg-end-multiline-output "" } */
381
382 sprintf (d, " %-8Le ", ldexpr);
383 }
384
385 /* Tests of "E" without a length modifier, with various param types.
386 Suggestions should preserve the "E" for floating-point arguments. */
387
388 void
test_E(char * d,int iexpr,float fexpr,double dexpr,long double ldexpr)389 test_E (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
390 {
391 /* Integer arguments. */
392
393 sprintf (d, " %-8E ", iexpr); /* { dg-warning "20: format '%E' expects argument of type 'double', but argument 3 has type 'int'" } */
394 /* { dg-begin-multiline-output "" }
395 sprintf (d, " %-8E ", iexpr);
396 ~~~^ ~~~~~
397 | |
398 | int
399 double
400 %-8d
401 { dg-end-multiline-output "" } */
402
403 /* Floating-point arguments. */
404
405 sprintf (d, " %-8E ", fexpr);
406 sprintf (d, " %-8E ", dexpr);
407 sprintf (d, " %-8E ", ldexpr); /* { dg-warning "20: format '%E' expects argument of type 'double', but argument 3 has type 'long double'" } */
408 /* { dg-begin-multiline-output "" }
409 sprintf (d, " %-8E ", ldexpr);
410 ~~~^ ~~~~~~
411 | |
412 | long double
413 double
414 %-8LE
415 { dg-end-multiline-output "" } */
416 }
417
418 /* Tests of "E" with "L", with various param types.
419 Suggestions should preserve the "E" for floating-point arguments. */
420
421 void
test_LE(char * d,int iexpr,float fexpr,double dexpr,long double ldexpr)422 test_LE (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
423 {
424 /* Integer arguments. */
425
426 sprintf (d, " %-8LE ", iexpr); /* { dg-warning "21: format '%LE' expects argument of type 'long double', but argument 3 has type 'int'" } */
427 /* { dg-begin-multiline-output "" }
428 sprintf (d, " %-8LE ", iexpr);
429 ~~~~^ ~~~~~
430 | |
431 | int
432 long double
433 %-8d
434 { dg-end-multiline-output "" } */
435
436 sprintf (d, " %-8LE ", fexpr); /* { dg-warning "21: format '%LE' expects argument of type 'long double', but argument 3 has type 'double'" } */
437 /* { dg-begin-multiline-output "" }
438 sprintf (d, " %-8LE ", fexpr);
439 ~~~~^ ~~~~~
440 | |
441 | double
442 long double
443 %-8E
444 { dg-end-multiline-output "" } */
445
446 sprintf (d, " %-8LE ", dexpr); /* { dg-warning "21: format '%LE' expects argument of type 'long double', but argument 3 has type 'double'" } */
447 /* { dg-begin-multiline-output "" }
448 sprintf (d, " %-8LE ", dexpr);
449 ~~~~^ ~~~~~
450 | |
451 | double
452 long double
453 %-8E
454 { dg-end-multiline-output "" } */
455
456 sprintf (d, " %-8LE ", ldexpr);
457 }
458
459 /* Test of a suggestion for a conversion specification containing
460 all features (flags, width, precision, length modifier), where
461 all the other arguments have mismatching types. */
462
463 void
test_everything(char * d,long lexpr)464 test_everything (char *d, long lexpr)
465 {
466 sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr); /* { dg-line test_everything_sprintf } */
467
468 /* { dg-warning "26: field width specifier '\\*' expects argument of type 'int', but argument 3 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */
469 /* { dg-begin-multiline-output "" }
470 sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr);
471 ~~~^~~~~~ ~~~~~
472 | |
473 int long int
474 { dg-end-multiline-output "" } */
475
476 /* { dg-warning "28: field precision specifier '\\.\\*' expects argument of type 'int', but argument 4 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */
477 /* { dg-begin-multiline-output "" }
478 sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr);
479 ~~~~~^~~~ ~~~~~
480 | |
481 int long int
482 { dg-end-multiline-output "" } */
483
484 /* { dg-warning "31: format '%lld' expects argument of type 'long long int', but argument 5 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */
485 /* { dg-begin-multiline-output "" }
486 sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr);
487 ~~~~~~~~^ ~~~~~
488 | |
489 long long int long int
490 %-+*.*ld
491 { dg-end-multiline-output "" } */
492 }
493