1  /* Test for format extensions beyond the C standard and X/Open standard.
       2     Test for printf formats.
       3  */
       4  /* Origin: Joseph Myers <jsm28@cam.ac.uk> */
       5  /* { dg-do compile } */
       6  /* { dg-options "-std=gnu99 -Wformat" } */
       7  
       8  #include "format.h"
       9  
      10  void
      11  foo (quad_t q, u_quad_t uq, quad_t *qn, size_t z, size_t *zn, long long int ll,
      12       unsigned long long int ull, int i, unsigned int u, double d,
      13       char *s, void *p, wchar_t *ls, wint_t lc, int *n, long int l)
      14  {
      15    /* As an extension, GCC allows the BSD length "q" for integer formats.
      16       This is largely obsoleted in C99 by %j, %ll and PRId64.
      17    */
      18    printf ("%qd%qi%qo%qu%qx%qX%qn", q, q, uq, uq, uq, uq, qn);
      19    printf ("%qf", d); /* { dg-warning "length" "bad use of %q" } */
      20    printf ("%qF", d); /* { dg-warning "length" "bad use of %q" } */
      21    printf ("%qe", d); /* { dg-warning "length" "bad use of %q" } */
      22    printf ("%qE", d); /* { dg-warning "length" "bad use of %q" } */
      23    printf ("%qg", d); /* { dg-warning "length" "bad use of %q" } */
      24    printf ("%qG", d); /* { dg-warning "length" "bad use of %q" } */
      25    printf ("%qa", d); /* { dg-warning "length" "bad use of %q" } */
      26    printf ("%qA", d); /* { dg-warning "length" "bad use of %q" } */
      27    printf ("%qc", i); /* { dg-warning "length" "bad use of %q" } */
      28    printf ("%qs", s); /* { dg-warning "length" "bad use of %q" } */
      29    printf ("%qp", p); /* { dg-warning "length" "bad use of %q" } */
      30    printf ("%qC", lc); /* { dg-warning "length" "bad use of %q" } */
      31    printf ("%qS", ls); /* { dg-warning "length" "bad use of %q" } */
      32    /* With a bad length GCC wants some argument, any argument,
      33       to devour with the format conversion, as a synchronisation heuristic.
      34       This may get improved later.
      35    */
      36    printf ("%qm", i); /* { dg-warning "length" "bad use of %q" } */
      37    /* As an extension, GCC allows the length "Z" as a synonym for "z".
      38       This was an extension predating C99 which should now be considered
      39       deprecated; use the standard "z" instead.
      40    */
      41    printf ("%Zd%Zi%Zo%Zu%Zx%ZX", z, z, z, z, z, z);
      42    printf ("%Zn", zn);
      43    printf ("%Zf", d); /* { dg-warning "length" "bad use of %Z" } */
      44    printf ("%ZF", d); /* { dg-warning "length" "bad use of %Z" } */
      45    printf ("%Ze", d); /* { dg-warning "length" "bad use of %Z" } */
      46    printf ("%ZE", d); /* { dg-warning "length" "bad use of %Z" } */
      47    printf ("%Zg", d); /* { dg-warning "length" "bad use of %Z" } */
      48    printf ("%ZG", d); /* { dg-warning "length" "bad use of %Z" } */
      49    printf ("%Za", d); /* { dg-warning "length" "bad use of %Z" } */
      50    printf ("%ZA", d); /* { dg-warning "length" "bad use of %Z" } */
      51    printf ("%Zc", i); /* { dg-warning "length" "bad use of %Z" } */
      52    printf ("%Zs", s); /* { dg-warning "length" "bad use of %Z" } */
      53    printf ("%Zp", p); /* { dg-warning "length" "bad use of %Z" } */
      54    printf ("%ZC", lc); /* { dg-warning "length" "bad use of %Z" } */
      55    printf ("%ZS", ls); /* { dg-warning "length" "bad use of %Z" } */
      56    printf ("%Zm", i); /* { dg-warning "length" "bad use of %Z" } */
      57    /* As an extension, GCC allows the length "L" on integer formats
      58       (but not %n) as a synonym for "ll".
      59       This should be considered deprecated.
      60    */
      61    printf ("%Ld%Li%Lo%Lu%Lx%LX", ll, ll, ull, ull, ull, ull);
      62    /* As an extension, derived from syslog, GCC allows the conversion
      63       specifier "m" for formatting strerror(errno).  This may be used
      64       with width, precision and the "-" flag, the same as %s.
      65    */
      66    printf ("%m%3m%.4m%5.6m");
      67    printf ("%*m", i);
      68    printf ("%.*m", i);
      69    printf ("%*.*m", i, i);
      70    printf ("%3.*m", i);
      71    printf ("%*.4m", i);
      72    printf ("%-m");
      73    printf ("%+m"); /* { dg-warning "flag" "bad %+m" } */
      74    printf ("% m"); /* { dg-warning "flag" "bad % m" } */
      75    printf ("%#m"); /* { dg-warning "flag" "bad %#m" } */
      76    printf ("%0m"); /* { dg-warning "flag" "bad %0m" } */
      77    printf ("%'m"); /* { dg-warning "flag" "bad %'m" } */
      78    printf ("%hm", i); /* { dg-warning "length" "bad %hm" } */
      79    printf ("%hhm", i); /* { dg-warning "length" "bad %hhm" } */
      80    printf ("%lm", i); /* { dg-warning "length" "bad %lm" } */
      81    printf ("%llm", i); /* { dg-warning "length" "bad %llm" } */
      82    printf ("%jm", i); /* { dg-warning "length" "bad %jm" } */
      83    printf ("%zm", i); /* { dg-warning "length" "bad %zm" } */
      84    printf ("%tm", i); /* { dg-warning "length" "bad %tm" } */
      85    printf ("%Lm", i); /* { dg-warning "length" "bad %Lm" } */
      86    printf ("%qm", i); /* { dg-warning "length" "bad %qm" } */
      87    printf ("%Zm", i); /* { dg-warning "length" "bad %Zm" } */
      88    /* It should be OK to mix %m formats with $ operand number formats.  */
      89    printf ("%2$ld%m%1$d", i, l);
      90    /* Likewise, %m formats with width and precision should not have an
      91       operand number for the %m itself.
      92    */
      93    printf ("%*2$.*1$m", i, i);
      94    printf ("%1$*2$.*1$m", i, i); /* { dg-warning "no argument" "printf %1\$m" } */
      95    /* As an extension, glibc includes the "I" flag for decimal
      96       formats, to output using the locale's digits (e.g. in Arabic).
      97       In GCC, we require this to be in the standard place for flags, though
      98       glibc allows it also after width or precision.
      99    */
     100    printf ("%Id%Ii%Iu", i, i, u);
     101    printf ("%Io", u); /* { dg-warning "flag" "bad use of I flag" } */
     102    printf ("%Ix", u); /* { dg-warning "flag" "bad use of I flag" } */
     103    printf ("%IX", u); /* { dg-warning "flag" "bad use of I flag" } */
     104    printf ("%In", n); /* { dg-warning "flag" "bad use of I flag" } */
     105    printf ("%If", d);
     106    printf ("%IF", d);
     107    printf ("%Ie", d);
     108    printf ("%IE", d);
     109    printf ("%Ig", d);
     110    printf ("%IG", d);
     111    printf ("%Ia", d); /* { dg-warning "flag" "bad use of I flag" } */
     112    printf ("%IA", d); /* { dg-warning "flag" "bad use of I flag" } */
     113    printf ("%Ic", i); /* { dg-warning "flag" "bad use of I flag" } */
     114    printf ("%Is", s); /* { dg-warning "flag" "bad use of I flag" } */
     115    printf ("%Ip", p); /* { dg-warning "flag" "bad use of I flag" } */
     116    printf ("%IC", lc); /* { dg-warning "flag" "bad use of I flag" } */
     117    printf ("%IS", ls); /* { dg-warning "flag" "bad use of I flag" } */
     118    printf ("%Im"); /* { dg-warning "flag" "bad use of I flag" } */
     119  
     120    /* As an extension, GCC does format checking on "unlocked"
     121       i.e. thread unsafe versions of these functions.  */
     122    fprintf_unlocked (stdout, "%d", i);
     123    fprintf_unlocked (stdout, "%ld", i); /* { dg-warning "format" "fprintf_unlocked" } */
     124    printf_unlocked ("%d", i);
     125    printf_unlocked ("%ld", i); /* { dg-warning "format" "printf_unlocked" } */
     126  }