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