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