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