1/* Test for printf formats.  Formats using C90 features, including cases
2   where C90 specifies some aspect of the format to be ignored or where
3   the behavior is undefined.
4*/
5/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
6/* { dg-do compile } */
7/* { dg-options "-std=iso9899:1990 -pedantic -Wformat" } */
8
9#include "format.h"
10
11void
12foo (int i, int i1, int i2, unsigned int u, double d, char *s, void *p,
13     int *n, short int *hn, long int l, unsigned long int ul,
14     long int *ln, long double ld, wint_t lc, wchar_t *ls, llong ll,
15     ullong ull, unsigned int *un, const int *cn, signed char *ss,
16     unsigned char *us, const signed char *css, unsigned int u1,
17     unsigned int u2)
18{
19  /* See ISO/IEC 9899:1990 (E) subclause 7.9.6.1 (pages 131-134).  */
20  /* Basic sanity checks for the different components of a format.  */
21  printf ("%d\n", i);
22  printf ("%+d\n", i);
23  printf ("%3d\n", i);
24  printf ("%-3d\n", i);
25  printf ("%.7d\n", i);
26  printf ("%+9.4d\n", i);
27  printf ("%.3ld\n", l);
28  printf ("%*d\n", i1, i);
29  printf ("%.*d\n", i2, i);
30  printf ("%*.*ld\n", i1, i2, l);
31  printf ("%d %lu\n", i, ul);
32  /* GCC has objected to the next one in the past, but it is a valid way
33     of specifying zero precision.
34  */
35  printf ("%.e\n", d); /* { dg-bogus "precision" "bogus precision warning" } */
36  /* Bogus use of width.  */
37  printf ("%5n\n", n); /* { dg-warning "width" "width with %n" } */
38  /* Erroneous, ignored or pointless constructs with precision.  */
39  /* Whether negative values for precision may be included in the format
40     string is not entirely clear; presume not, following Clive Feather's
41     proposed resolution to DR#220 against C99.  In any case, such a
42     construct should be warned about.
43  */
44  printf ("%.-5d\n", i); /* { dg-warning "format|precision" "negative precision warning" } */
45  printf ("%.-*d\n", i); /* { dg-warning "format" "broken %.-*d format" } */
46  printf ("%.3c\n", i); /* { dg-warning "precision" "precision with %c" } */
47  printf ("%.3p\n", p); /* { dg-warning "precision" "precision with %p" } */
48  printf ("%.3n\n", n); /* { dg-warning "precision" "precision with %n" } */
49  /* Valid and invalid %% constructions.  Some of the warning messages
50     are non-optimal, but they do detect the errorneous nature of the
51     format string.
52  */
53  printf ("%%");
54  printf ("%.3%"); /* { dg-warning "format" "bogus %%" } */
55  printf ("%-%"); /* { dg-warning "format" "bogus %%" } */
56  printf ("%-%\n"); /* { dg-warning "format" "bogus %%" } */
57  printf ("%5%\n"); /* { dg-warning "format" "bogus %%" } */
58  printf ("%h%\n"); /* { dg-warning "format" "bogus %%" } */
59  /* Valid and invalid %h, %l, %L constructions.  */
60  printf ("%hd", i);
61  printf ("%hi", i);
62  /* Strictly, these parameters should be int or unsigned int according to
63     what unsigned short promotes to.  However, GCC ignores sign
64     differences in format checking here, and this is relied on to get the
65     correct checking without print_char_table needing to know whether
66     int and short are the same size.
67  */
68  printf ("%ho%hu%hx%hX", u, u, u, u);
69  printf ("%hn", hn);
70  printf ("%hf", d); /* { dg-warning "length" "bad use of %h" } */
71  printf ("%he", d); /* { dg-warning "length" "bad use of %h" } */
72  printf ("%hE", d); /* { dg-warning "length" "bad use of %h" } */
73  printf ("%hg", d); /* { dg-warning "length" "bad use of %h" } */
74  printf ("%hG", d); /* { dg-warning "length" "bad use of %h" } */
75  printf ("%hc", i); /* { dg-warning "length" "bad use of %h" } */
76  printf ("%hs", s); /* { dg-warning "length" "bad use of %h" } */
77  printf ("%hp", p); /* { dg-warning "length" "bad use of %h" } */
78  printf ("%h"); /* { dg-warning "conversion lacks type" "bare %h" } */
79  printf ("%h."); /* { dg-warning "conversion" "bogus %h." } */
80  printf ("%ld%li%lo%lu%lx%lX", l, l, ul, ul, ul, ul);
81  printf ("%ln", ln);
82  printf ("%lf", d); /* { dg-warning "length|C" "bad use of %l" } */
83  printf ("%le", d); /* { dg-warning "length|C" "bad use of %l" } */
84  printf ("%lE", d); /* { dg-warning "length|C" "bad use of %l" } */
85  printf ("%lg", d); /* { dg-warning "length|C" "bad use of %l" } */
86  printf ("%lG", d); /* { dg-warning "length|C" "bad use of %l" } */
87  printf ("%lp", p); /* { dg-warning "length|C" "bad use of %l" } */
88  /* These next two were added in C94, but should be objected to in C90.
89     For the first one, GCC has wanted wchar_t instead of the correct C94
90     and C99 wint_t.
91  */
92  printf ("%lc", lc); /* { dg-warning "length|C" "C90 bad use of %l" } */
93  printf ("%ls", ls); /* { dg-warning "length|C" "C90 bad use of %l" } */
94  /* These uses of %L are legitimate, though GCC has wrongly warned for
95     them in the past.
96  */
97  printf ("%Le%LE%Lf%Lg%LG", ld, ld, ld, ld, ld);
98  /* These next six are accepted by GCC as referring to long long,
99     but -pedantic correctly warns.
100  */
101  printf ("%Ld", ll); /* { dg-warning "does not support" "bad use of %L" } */
102  printf ("%Li", ll); /* { dg-warning "does not support" "bad use of %L" } */
103  printf ("%Lo", ull); /* { dg-warning "does not support" "bad use of %L" } */
104  printf ("%Lu", ull); /* { dg-warning "does not support" "bad use of %L" } */
105  printf ("%Lx", ull); /* { dg-warning "does not support" "bad use of %L" } */
106  printf ("%LX", ull); /* { dg-warning "does not support" "bad use of %L" } */
107  printf ("%Lc", i); /* { dg-warning "length" "bad use of %L" } */
108  printf ("%Ls", s); /* { dg-warning "length" "bad use of %L" } */
109  printf ("%Lp", p); /* { dg-warning "length" "bad use of %L" } */
110  printf ("%Ln", n); /* { dg-warning "length" "bad use of %L" } */
111  /* Valid uses of each bare conversion.  */
112  printf ("%d%i%o%u%x%X%f%e%E%g%G%c%s%p%n%%", i, i, u, u, u, u, d, d, d, d, d,
113	  i, s, p, n);
114  /* Uses of the - flag (valid on all non-%, non-n conversions).  */
115  printf ("%-d%-i%-o%-u%-x%-X%-f%-e%-E%-g%-G%-c%-s%-p", i, i, u, u, u, u,
116	  d, d, d, d, d, i, s, p);
117  printf ("%-n", n); /* { dg-warning "flag" "bad use of %-n" } */
118  /* Uses of the + flag (valid on signed conversions only).  */
119  printf ("%+d%+i%+f%+e%+E%+g%+G\n", i, i, d, d, d, d, d);
120  printf ("%+o", u); /* { dg-warning "flag" "bad use of + flag" } */
121  printf ("%+u", u); /* { dg-warning "flag" "bad use of + flag" } */
122  printf ("%+x", u); /* { dg-warning "flag" "bad use of + flag" } */
123  printf ("%+X", u); /* { dg-warning "flag" "bad use of + flag" } */
124  printf ("%+c", i); /* { dg-warning "flag" "bad use of + flag" } */
125  printf ("%+s", s); /* { dg-warning "flag" "bad use of + flag" } */
126  printf ("%+p", p); /* { dg-warning "flag" "bad use of + flag" } */
127  printf ("%+n", n); /* { dg-warning "flag" "bad use of + flag" } */
128  /* Uses of the space flag (valid on signed conversions only, and ignored
129     with +).
130  */
131  printf ("% +d", i); /* { dg-warning "use of both|ignored" "use of space and + flags" } */
132  printf ("%+ d", i); /* { dg-warning "use of both|ignored" "use of space and + flags" } */
133  printf ("% d% i% f% e% E% g% G\n", i, i, d, d, d, d, d);
134  printf ("% o", u); /* { dg-warning "flag" "bad use of space flag" } */
135  printf ("% u", u); /* { dg-warning "flag" "bad use of space flag" } */
136  printf ("% x", u); /* { dg-warning "flag" "bad use of space flag" } */
137  printf ("% X", u); /* { dg-warning "flag" "bad use of space flag" } */
138  printf ("% c", i); /* { dg-warning "flag" "bad use of space flag" } */
139  printf ("% s", s); /* { dg-warning "flag" "bad use of space flag" } */
140  printf ("% p", p); /* { dg-warning "flag" "bad use of space flag" } */
141  printf ("% n", n); /* { dg-warning "flag" "bad use of space flag" } */
142  /* Uses of the # flag.  */
143  printf ("%#o%#x%#X%#e%#E%#f%#g%#G", u, u, u, d, d, d, d, d);
144  printf ("%#d", i); /* { dg-warning "flag" "bad use of # flag" } */
145  printf ("%#i", i); /* { dg-warning "flag" "bad use of # flag" } */
146  printf ("%#u", u); /* { dg-warning "flag" "bad use of # flag" } */
147  printf ("%#c", i); /* { dg-warning "flag" "bad use of # flag" } */
148  printf ("%#s", s); /* { dg-warning "flag" "bad use of # flag" } */
149  printf ("%#p", p); /* { dg-warning "flag" "bad use of # flag" } */
150  printf ("%#n", n); /* { dg-warning "flag" "bad use of # flag" } */
151  /* Uses of the 0 flag.  */
152  printf ("%08d%08i%08o%08u%08x%08X%08e%08E%08f%08g%08G", i, i, u, u, u, u,
153	  d, d, d, d, d);
154  printf ("%0c", i); /* { dg-warning "flag" "bad use of 0 flag" } */
155  printf ("%0s", s); /* { dg-warning "flag" "bad use of 0 flag" } */
156  printf ("%0p", p); /* { dg-warning "flag" "bad use of 0 flag" } */
157  printf ("%0n", n); /* { dg-warning "flag" "bad use of 0 flag" } */
158  /* 0 flag ignored with precision for certain types, not others.  */
159  printf ("%08.5d", i); /* { dg-warning "ignored" "0 flag ignored with precision" } */
160  printf ("%08.5i", i); /* { dg-warning "ignored" "0 flag ignored with precision" } */
161  printf ("%08.5o", u); /* { dg-warning "ignored" "0 flag ignored with precision" } */
162  printf ("%08.5u", u); /* { dg-warning "ignored" "0 flag ignored with precision" } */
163  printf ("%08.5x", u); /* { dg-warning "ignored" "0 flag ignored with precision" } */
164  printf ("%08.5X", u); /* { dg-warning "ignored" "0 flag ignored with precision" } */
165  printf ("%08.5f%08.5e%08.5E%08.5g%08.5G", d, d, d, d, d);
166  /* 0 flag ignored with - flag.  */
167  printf ("%-08d", i); /* { dg-warning "flags|ignored" "0 flag ignored with - flag" } */
168  printf ("%-08i", i); /* { dg-warning "flags|ignored" "0 flag ignored with - flag" } */
169  printf ("%-08o", u); /* { dg-warning "flags|ignored" "0 flag ignored with - flag" } */
170  printf ("%-08u", u); /* { dg-warning "flags|ignored" "0 flag ignored with - flag" } */
171  printf ("%-08x", u); /* { dg-warning "flags|ignored" "0 flag ignored with - flag" } */
172  printf ("%-08X", u); /* { dg-warning "flags|ignored" "0 flag ignored with - flag" } */
173  printf ("%-08e", d); /* { dg-warning "flags|ignored" "0 flag ignored with - flag" } */
174  printf ("%-08E", d); /* { dg-warning "flags|ignored" "0 flag ignored with - flag" } */
175  printf ("%-08f", d); /* { dg-warning "flags|ignored" "0 flag ignored with - flag" } */
176  printf ("%-08g", d); /* { dg-warning "flags|ignored" "0 flag ignored with - flag" } */
177  printf ("%-08G", d); /* { dg-warning "flags|ignored" "0 flag ignored with - flag" } */
178  /* Various tests of bad argument types.  */
179  printf ("%d", l); /* { dg-warning "format" "bad argument types" } */
180  printf ("%*.*d", l, i2, i); /* { dg-warning "field" "bad * argument types" } */
181  printf ("%*.*d", i1, l, i); /* { dg-warning "field" "bad * argument types" } */
182  printf ("%ld", i); /* { dg-warning "format" "bad argument types" } */
183  printf ("%s", n); /* { dg-warning "format" "bad argument types" } */
184  printf ("%p", i); /* { dg-warning "format" "bad argument types" } */
185  printf ("%n", p); /* { dg-warning "format" "bad argument types" } */
186  /* With -pedantic, we want some further checks for pointer targets:
187     %p should allow only pointers to void (possibly qualified) and
188     to character types (possibly qualified), but not function pointers
189     or pointers to other types.  (Whether, in fact, character types are
190     allowed here is unclear; see thread on comp.std.c, July 2000 for
191     discussion of the requirements of rules on identical representation,
192     and of the application of the as if rule with the new va_arg
193     allowances in C99 to printf.)  Likewise, we should warn if
194     pointer targets differ in signedness, except in some circumstances
195     for character pointers.  (In C99 we should consider warning for
196     char * or unsigned char * being passed to %hhn, even if strictly
197     legitimate by the standard.)
198  */
199  printf ("%p", foo); /* { dg-warning "format" "bad argument types" } */
200  printf ("%n", un); /* { dg-warning "format" "bad argument types" } */
201  printf ("%p", n); /* { dg-warning "format" "bad argument types" } */
202  /* Allow character pointers with %p.  */
203  printf ("%p%p%p%p", s, ss, us, css);
204  /* %s allows any character type.  */
205  printf ("%s%s%s%s", s, ss, us, css);
206  /* Warning for void * arguments for %s is GCC's historical behavior,
207     and seems useful to keep, even if some standard versions might be
208     read to permit it.
209  */
210  printf ("%s", p); /* { dg-warning "format" "bad argument types" } */
211  /* The historical behavior is to allow signed / unsigned types
212     interchangably as arguments.  For values representable in both types,
213     such usage may be correct.  For now preserve the behavior of GCC
214     in such cases.
215  */
216  printf ("%d", u);
217  /* Also allow the same for width and precision arguments.  In the past,
218     GCC has been inconsistent and allowed unsigned for width but not
219     precision.
220  */
221  printf ("%*.*d", u1, u2, i);
222  /* Wrong number of arguments.  */
223  printf ("%d%d", i); /* { dg-warning "arguments" "wrong number of args" } */
224  printf ("%d", i, i); /* { dg-warning "arguments" "wrong number of args" } */
225  /* Miscellaneous bogus constructions.  */
226  printf (""); /* { dg-warning "zero-length" "warning for empty format" } */
227  printf ("\0"); /* { dg-warning "embedded" "warning for embedded NUL" } */
228  printf ("%d\0", i); /* { dg-warning "embedded" "warning for embedded NUL" } */
229  printf ("%d\0%d", i, i); /* { dg-warning "embedded|too many" "warning for embedded NUL" } */
230  printf (NULL); /* { dg-warning "null" "null format string warning" } */
231  printf ("%"); /* { dg-warning "trailing" "trailing % warning" } */
232  printf ("%++d", i); /* { dg-warning "repeated" "repeated flag warning" } */
233  printf ("%n", cn); /* { dg-warning "constant" "%n with const" } */
234  printf ((const char *)L"foo"); /* { dg-warning "wide" "wide string" } */
235  printf ("%n", (int *)0); /* { dg-warning "null" "%n with NULL" } */
236  printf ("%s", (char *)0); /* { dg-warning "null" "%s with NULL" } */
237}
238