1 /* { dg-options "-Wformat -fdiagnostics-show-caret" } */
2
3 /* This is a copy of gcc.dg/format/diagnostic-ranges.c
4 with the following changes:
5 - removal of "format.h"
6 - "char \\*" -> "char\\*" (space removal)
7 - move of test_u8 to Wformat-ranges-c++11.C. */
8
9 #define printf __builtin_printf
10 typedef __SIZE_TYPE__ size_t;
11 typedef __SIZE_TYPE__ ssize_t;
12
13 extern ssize_t strfmon (char *__restrict __s, size_t __maxsize,
14 const char *__restrict, ...)
15 __attribute__ ((__format__ (__strfmon__, 3, 4)));
16
17 /* See PR 52952. */
18
test_mismatching_types(const char * msg)19 void test_mismatching_types (const char *msg)
20 {
21 printf("hello %i", msg); /* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'const char\\*' " } */
22
23 /* { dg-begin-multiline-output "" }
24 printf("hello %i", msg);
25 ~^ ~~~
26 | |
27 int const char*
28 %s
29 { dg-end-multiline-output "" } */
30
31
32 printf("hello %s", 42); /* { dg-warning "format '%s' expects argument of type 'char\\*', but argument 2 has type 'int'" } */
33 /* { dg-begin-multiline-output "" }
34 printf("hello %s", 42);
35 ~^ ~~
36 | |
37 | int
38 char*
39 %d
40 { dg-end-multiline-output "" } */
41
42 printf("hello %i", (long)0); /* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'long int' " } */
43 /* { dg-begin-multiline-output "" }
44 printf("hello %i", (long)0);
45 ~^ ~~~~~~~
46 | |
47 int long int
48 %li
49 { dg-end-multiline-output "" } */
50 }
51
test_multiple_arguments(void)52 void test_multiple_arguments (void)
53 {
54 printf ("arg0: %i arg1: %s arg 2: %i", /* { dg-warning "29: format '%s'" } */
55 100, 101, 102);
56 /* { dg-begin-multiline-output "" }
57 printf ("arg0: %i arg1: %s arg 2: %i",
58 ~^
59 |
60 char*
61 %d
62 100, 101, 102);
63 ~~~
64 |
65 int
66 { dg-end-multiline-output "" } */
67 }
68
test_multiple_arguments_2(int i,int j)69 void test_multiple_arguments_2 (int i, int j)
70 {
71 printf ("arg0: %i arg1: %s arg 2: %i", /* { dg-warning "29: format '%s'" } */
72 100, i + j, 102);
73 /* { dg-begin-multiline-output "" }
74 printf ("arg0: %i arg1: %s arg 2: %i",
75 ~^
76 |
77 char*
78 %d
79 100, i + j, 102);
80 ~~~~~
81 |
82 int
83 { dg-end-multiline-output "" } */
84 }
85
multiline_format_string(void)86 void multiline_format_string (void) {
87 printf ("before the fmt specifier"
88 "%"
89 "d" /* { dg-warning "12: format '%d' expects a matching 'int' argument" } */
90 "after the fmt specifier");
91 /* { dg-begin-multiline-output "" }
92 "%"
93 ~~
94 "d"
95 ~^
96 |
97 int
98 { dg-end-multiline-output "" } */
99 }
100
test_hex(const char * msg)101 void test_hex (const char *msg)
102 {
103 /* "%" is \x25
104 "i" is \x69 */
105 printf("hello \x25\x69", msg); /* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'const char\\*' " } */
106
107 /* { dg-begin-multiline-output "" }
108 printf("hello \x25\x69", msg);
109 ~~~~^~~~ ~~~
110 | |
111 int const char*
112 \x25s
113 { dg-end-multiline-output "" } */
114 }
115
test_oct(const char * msg)116 void test_oct (const char *msg)
117 {
118 /* "%" is octal 045
119 "i" is octal 151. */
120 printf("hello \045\151", msg); /* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'const char\\*' " } */
121
122 /* { dg-begin-multiline-output "" }
123 printf("hello \045\151", msg);
124 ~~~~^~~~ ~~~
125 | |
126 int const char*
127 \045s
128 { dg-end-multiline-output "" } */
129 }
130
test_multiple(const char * msg)131 void test_multiple (const char *msg)
132 {
133 /* "%" is \x25 in hex
134 "i" is \151 in octal. */
135 printf("prefix" "\x25" "\151" "suffix", /* { dg-warning "format '%i'" } */
136 msg);
137 /* { dg-begin-multiline-output "" }
138 printf("prefix" "\x25" "\151" "suffix",
139 ~~~~~~~~^~~~
140 |
141 int
142 \x25" "s
143 msg);
144 ~~~
145 |
146 const char*
147 { dg-end-multiline-output "" } */
148 }
149
test_param(long long_i,long long_j)150 void test_param (long long_i, long long_j)
151 {
152 printf ("foo %s bar", long_i + long_j); /* { dg-warning "17: format '%s' expects argument of type 'char\\*', but argument 2 has type 'long int'" } */
153 /* { dg-begin-multiline-output "" }
154 printf ("foo %s bar", long_i + long_j);
155 ~^ ~~~~~~~~~~~~~~~
156 | |
157 char* long int
158 %ld
159 { dg-end-multiline-output "" } */
160 }
161
test_field_width_specifier(long l,int i1,int i2)162 void test_field_width_specifier (long l, int i1, int i2)
163 {
164 printf (" %*.*d ", l, i1, i2); /* { dg-warning "14: field width specifier '\\*' expects argument of type 'int', but argument 2 has type 'long int'" } */
165 /* { dg-begin-multiline-output "" }
166 printf (" %*.*d ", l, i1, i2);
167 ~^~~~ ~
168 | |
169 int long int
170 { dg-end-multiline-output "" } */
171 }
172
173 /* PR c/72857. */
174
test_field_width_specifier_2(char * d,long foo,long bar)175 void test_field_width_specifier_2 (char *d, long foo, long bar)
176 {
177 __builtin_sprintf (d, " %*ld ", foo, foo); /* { dg-warning "28: field width specifier '\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */
178 /* { dg-begin-multiline-output "" }
179 __builtin_sprintf (d, " %*ld ", foo, foo);
180 ~^~~ ~~~
181 | |
182 int long int
183 { dg-end-multiline-output "" } */
184
185 __builtin_sprintf (d, " %*ld ", foo + bar, foo); /* { dg-warning "28: field width specifier '\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */
186 /* { dg-begin-multiline-output "" }
187 __builtin_sprintf (d, " %*ld ", foo + bar, foo);
188 ~^~~ ~~~~~~~~~
189 | |
190 int long int
191 { dg-end-multiline-output "" } */
192 }
193
test_field_precision_specifier(char * d,long foo,long bar)194 void test_field_precision_specifier (char *d, long foo, long bar)
195 {
196 __builtin_sprintf (d, " %.*ld ", foo, foo); /* { dg-warning "29: field precision specifier '\\.\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */
197 /* { dg-begin-multiline-output "" }
198 __builtin_sprintf (d, " %.*ld ", foo, foo);
199 ~~^~~ ~~~
200 | |
201 int long int
202 { dg-end-multiline-output "" } */
203
204 __builtin_sprintf (d, " %.*ld ", foo + bar, foo); /* { dg-warning "29: field precision specifier '\\.\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */
205 /* { dg-begin-multiline-output "" }
206 __builtin_sprintf (d, " %.*ld ", foo + bar, foo);
207 ~~^~~ ~~~~~~~~~
208 | |
209 int long int
210 { dg-end-multiline-output "" } */
211 }
212
test_spurious_percent(void)213 void test_spurious_percent (void)
214 {
215 printf("hello world %"); /* { dg-warning "23: spurious trailing" } */
216
217 /* { dg-begin-multiline-output "" }
218 printf("hello world %");
219 ^
220 { dg-end-multiline-output "" } */
221 }
222
test_empty_precision(char * s,size_t m,double d)223 void test_empty_precision (char *s, size_t m, double d)
224 {
225 strfmon (s, m, "%#.5n", d); /* { dg-warning "20: empty left precision in gnu_strfmon format" } */
226 /* { dg-begin-multiline-output "" }
227 strfmon (s, m, "%#.5n", d);
228 ^
229 { dg-end-multiline-output "" } */
230
231 strfmon (s, m, "%#5.n", d); /* { dg-warning "22: empty precision in gnu_strfmon format" } */
232 /* { dg-begin-multiline-output "" }
233 strfmon (s, m, "%#5.n", d);
234 ^
235 { dg-end-multiline-output "" } */
236 }
237
test_repeated(int i)238 void test_repeated (int i)
239 {
240 printf ("%++d", i); /* { dg-warning "14: repeated '\\+' flag in format" } */
241 /* { dg-begin-multiline-output "" }
242 printf ("%++d", i);
243 ^
244 { dg-end-multiline-output "" } */
245 }
246
test_conversion_lacks_type(void)247 void test_conversion_lacks_type (void)
248 {
249 printf (" %h"); /* { dg-warning "14:conversion lacks type at end of format" } */
250 /* { dg-begin-multiline-output "" }
251 printf (" %h");
252 ^
253 { dg-end-multiline-output "" } */
254 }
255
test_embedded_nul(void)256 void test_embedded_nul (void)
257 {
258 printf (" \0 "); /* { dg-warning "13:embedded" "warning for embedded NUL" } */
259 /* { dg-begin-multiline-output "" }
260 printf (" \0 ");
261 ^~
262 { dg-end-multiline-output "" } */
263 }
264
test_macro(const char * msg)265 void test_macro (const char *msg)
266 {
267 #define INT_FMT "%i" /* { dg-message "19: format string is defined here" } */
268 printf("hello " INT_FMT " world", msg); /* { dg-warning "10: format '%i' expects argument of type 'int', but argument 2 has type 'const char\\*' " } */
269 /* { dg-begin-multiline-output "" }
270 printf("hello " INT_FMT " world", msg);
271 ^~~~~~~~~~~~~~~~~~~~~~~~~ ~~~
272 |
273 const char*
274 { dg-end-multiline-output "" } */
275 /* { dg-begin-multiline-output "" }
276 #define INT_FMT "%i"
277 ~^
278 |
279 int
280 %s
281 { dg-end-multiline-output "" } */
282 #undef INT_FMT
283 }
284
test_macro_2(const char * msg)285 void test_macro_2 (const char *msg)
286 {
287 #define PRIu32 "u" /* { dg-message "17: format string is defined here" } */
288 printf("hello %" PRIu32 " world", msg); /* { dg-warning "10: format '%u' expects argument of type 'unsigned int', but argument 2 has type 'const char\\*' " } */
289 /* { dg-begin-multiline-output "" }
290 printf("hello %" PRIu32 " world", msg);
291 ^~~~~~~~~~~~~~~~~~~~~~~~~ ~~~
292 |
293 const char*
294 { dg-end-multiline-output "" } */
295 /* { dg-begin-multiline-output "" }
296 #define PRIu32 "u"
297 ^
298 |
299 unsigned int
300 { dg-end-multiline-output "" } */
301 #undef PRIu32
302 }
303
test_macro_3(const char * msg)304 void test_macro_3 (const char *msg)
305 {
306 #define FMT_STRING "hello %i world" // { dg-line test_macro_3_macro_line }
307 /* { dg-warning "20: format '%i' expects argument of type 'int', but argument 2 has type 'const char\\*'" "" { target *-*-* } .-1 } */
308 printf(FMT_STRING, msg); /* { dg-message "10: in expansion of macro 'FMT_STRING" } */
309 /* { dg-begin-multiline-output "" }
310 #define FMT_STRING "hello %i world"
311 ^~~~~~~~~~~~~~~~
312 { dg-end-multiline-output "" } */
313 /* { dg-begin-multiline-output "" }
314 printf(FMT_STRING, msg);
315 ^~~~~~~~~~
316 { dg-end-multiline-output "" } */
317 /* { dg-message "28: format string is defined here" "" { target *-*-* } test_macro_3_macro_line } */
318 /* { dg-begin-multiline-output "" }
319 #define FMT_STRING "hello %i world"
320 ~^
321 |
322 int
323 %s
324 { dg-end-multiline-output "" } */
325 #undef FMT_STRING
326 }
327
test_macro_4(const char * msg)328 void test_macro_4 (const char *msg)
329 {
330 #define FMT_STRING "hello %i world" /* { dg-warning "20: format '%i' expects argument of type 'int', but argument 2 has type 'const char\\*' " } */
331 printf(FMT_STRING "\n", msg); /* { dg-message "10: in expansion of macro 'FMT_STRING" } */
332 /* { dg-begin-multiline-output "" }
333 #define FMT_STRING "hello %i world"
334 ^
335 { dg-end-multiline-output "" } */
336 /* { dg-begin-multiline-output "" }
337 printf(FMT_STRING "\n", msg);
338 ^~~~~~~~~~
339 { dg-end-multiline-output "" } */
340 /* { dg-begin-multiline-output "" }
341 #define FMT_STRING "hello %i world"
342 ~^
343 |
344 int
345 %s
346 { dg-end-multiline-output "" } */
347 #undef FMT_STRING
348 }
349
test_non_contiguous_strings(void)350 void test_non_contiguous_strings (void)
351 {
352 __builtin_printf(" %" "d ", 0.5); /* { dg-warning "26: format .%d. expects argument of type .int., but argument 2 has type .double." } */
353 /* { dg-begin-multiline-output "" }
354 __builtin_printf(" %" "d ", 0.5);
355 ~~~~^ ~~~
356 | |
357 int double
358 %" "f
359 { dg-end-multiline-output "" } */
360 }
361
test_const_arrays(void)362 void test_const_arrays (void)
363 {
364 /* TODO: ideally we'd highlight both the format string *and* the use of
365 it here. For now, just verify that we gracefully handle this case. */
366 const char a[] = " %d ";
367 __builtin_printf(a, 0.5); /* { dg-warning "20: format .%d. expects argument of type .int., but argument 2 has type .double." } */
368 /* { dg-begin-multiline-output "" }
369 __builtin_printf(a, 0.5);
370 ^ ~~~
371 |
372 double
373 { dg-end-multiline-output "" } */
374 }
375