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