1  /* Test for X/Open format extensions, as found in the
       2     Single Unix Specification and in Austin Group draft 7.
       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 (int i, unsigned int u, wint_t lc, wchar_t *ls, int *ip, double d,
      12       char *s, void *p, int *n, long int l, int i2, float *fp, long int *lp,
      13       va_list va)
      14  {
      15    /* The conversion specifiers C and S, for both printf and scanf,
      16       are X/Open extensions.
      17    */
      18    printf ("%C", lc);
      19    printf ("%3C", lc);
      20    printf ("%.3C", lc); /* { dg-warning "precision" "precision with %C" } */
      21    printf ("%hC", lc); /* { dg-warning "length" "bad %hC" } */
      22    printf ("%hhC", lc); /* { dg-warning "length" "bad %hhC" } */
      23    printf ("%lC", lc); /* { dg-warning "length" "bad %lC" } */
      24    printf ("%llC", lc); /* { dg-warning "length" "bad %llC" } */
      25    printf ("%jC", lc); /* { dg-warning "length" "bad %jC" } */
      26    printf ("%zC", lc); /* { dg-warning "length" "bad %zC" } */
      27    printf ("%tC", lc); /* { dg-warning "length" "bad %tC" } */
      28    printf ("%LC", lc); /* { dg-warning "length" "bad %LC" } */
      29    printf ("%-C", lc);
      30    printf ("%+C", lc); /* { dg-warning "flag" "bad %+C" } */
      31    printf ("% C", lc); /* { dg-warning "flag" "bad % C" } */
      32    printf ("%#C", lc); /* { dg-warning "flag" "bad %#C" } */
      33    printf ("%0C", lc); /* { dg-warning "flag" "bad %0C" } */
      34    printf ("%'C", lc); /* { dg-warning "flag" "bad %'C" } */
      35    printf ("%S", ls);
      36    printf ("%3S", ls);
      37    printf ("%.3S", ls);
      38    printf ("%hS", ls); /* { dg-warning "length" "bad %hS" } */
      39    printf ("%hhS", ls); /* { dg-warning "length" "bad %hhS" } */
      40    printf ("%lS", ls); /* { dg-warning "length" "bad %lS" } */
      41    printf ("%llS", ls); /* { dg-warning "length" "bad %llS" } */
      42    printf ("%jS", ls); /* { dg-warning "length" "bad %jS" } */
      43    printf ("%zS", ls); /* { dg-warning "length" "bad %zS" } */
      44    printf ("%tS", ls); /* { dg-warning "length" "bad %tS" } */
      45    printf ("%LS", ls); /* { dg-warning "length" "bad %LS" } */
      46    printf ("%-S", ls);
      47    printf ("%+S", ls); /* { dg-warning "flag" "bad %+S" } */
      48    printf ("% S", ls); /* { dg-warning "flag" "bad % S" } */
      49    printf ("%#S", ls); /* { dg-warning "flag" "bad %#S" } */
      50    printf ("%0S", ls); /* { dg-warning "flag" "bad %0S" } */
      51    printf ("%'S", ls); /* { dg-warning "flag" "bad %'S" } */
      52    scanf ("%C", ls);
      53    scanf ("%S", ls);
      54    scanf ("%*C%*S");
      55    scanf ("%2C%3S", ls, ls);
      56    scanf ("%hC", ls); /* { dg-warning "length" "bad %hC" } */
      57    scanf ("%hhC", ls); /* { dg-warning "length" "bad %hhC" } */
      58    scanf ("%lC", ls); /* { dg-warning "length" "bad %lC" } */
      59    scanf ("%llC", ls); /* { dg-warning "length" "bad %llC" } */
      60    scanf ("%jC", ls); /* { dg-warning "length" "bad %jC" } */
      61    scanf ("%zC", ls); /* { dg-warning "length" "bad %zC" } */
      62    scanf ("%tC", ls); /* { dg-warning "length" "bad %tC" } */
      63    scanf ("%LC", ls); /* { dg-warning "length" "bad %LC" } */
      64    scanf ("%hS", ls); /* { dg-warning "length" "bad %hS" } */
      65    scanf ("%hhS", ls); /* { dg-warning "length" "bad %hhS" } */
      66    scanf ("%lS", ls); /* { dg-warning "length" "bad %lS" } */
      67    scanf ("%llS", ls); /* { dg-warning "length" "bad %llS" } */
      68    scanf ("%jS", ls); /* { dg-warning "length" "bad %jS" } */
      69    scanf ("%zS", ls); /* { dg-warning "length" "bad %zS" } */
      70    scanf ("%tS", ls); /* { dg-warning "length" "bad %tS" } */
      71    scanf ("%LS", ls); /* { dg-warning "length" "bad %LS" } */
      72    /* In C99 mode (even with extensions), %aS is a floating point
      73       format followed by an S.
      74    */
      75    scanf ("%aS", fp);
      76    /* The printf flag character ' is an X/Open extension.  */
      77    printf ("%'d%'i%'u%'f%'F%'g%'G", i, i, u, d, d, d, d);
      78    printf ("%'o", u); /* { dg-warning "flag" "bad use of ' flag" } */
      79    printf ("%'x", u); /* { dg-warning "flag" "bad use of ' flag" } */
      80    printf ("%'X", u); /* { dg-warning "flag" "bad use of ' flag" } */
      81    printf ("%'e", d); /* { dg-warning "flag" "bad use of ' flag" } */
      82    printf ("%'E", d); /* { dg-warning "flag" "bad use of ' flag" } */
      83    printf ("%'a", d); /* { dg-warning "flag" "bad use of ' flag" } */
      84    printf ("%'A", d); /* { dg-warning "flag" "bad use of ' flag" } */
      85    printf ("%'c", i); /* { dg-warning "flag" "bad use of ' flag" } */
      86    printf ("%'s", s); /* { dg-warning "flag" "bad use of ' flag" } */
      87    printf ("%'p", p); /* { dg-warning "flag" "bad use of ' flag" } */
      88    printf ("%'n", n); /* { dg-warning "flag" "bad use of ' flag" } */
      89    /* The use of operand number $ formats is an X/Open extension.  */
      90    scanf ("%1$d", ip);
      91    printf ("%1$d", i);
      92    printf ("%1$d", l); /* { dg-warning "arg 2|argument 2" "mismatched args with $ format" } */
      93    printf ("%3$*2$.*1$ld", i2, i, l);
      94    printf ("%4$ld%7$ld%5$d%6$d%3$d%1$d%2$d", i, i, i, l, i, i, l);
      95    scanf ("%4$ld%7$ld%5$d%6$d%3$d%1$d%2$d", ip, ip, ip, lp, ip, ip, lp);
      96    printf ("%1$d%d", i, i); /* { dg-warning "missing" "mixing $ and non-$ formats" } */
      97    printf ("%%%1$d%%%2$d", i, i);
      98    printf ("%d%2$d", i); /* { dg-warning "used after format" "mixing $ and non-$ formats" } */
      99    printf ("%1$*d", i, i); /* { dg-warning "missing" "mixing $ and non-$ formats" } */
     100    printf ("%*1$d", i); /* { dg-warning "missing" "mixing $ and non-$ formats" } */
     101    scanf ("%1$d%d", ip, ip); /* { dg-warning "missing" "mixing $ and non-$ formats" } */
     102    scanf ("%*f%%%1$d%%%2$d", ip, ip);
     103    printf ("%2$d", i); /* { dg-warning "operand" "$ number too large" } */
     104    printf ("%0$d", i); /* { dg-warning "operand" "$ number too small" } */
     105    printf ("%3$d%1$d", i, i, i); /* { dg-warning "before used" "unused $ operand" } */
     106    printf ("%2$d%1$d", i, i, i); /* { dg-warning "unused" "unused $ operand" } */
     107    vprintf ("%3$d%1$d", va); /* { dg-warning "before used" "unused $ operand" } */
     108    /* With scanf formats, gaps in the used arguments are allowed only if the
     109       arguments are all pointers.  In such a case, should only give the lesser
     110       warning about unused arguments rather than the more serious one about
     111       argument gaps.  */
     112    scanf ("%3$d%1$d", ip, ip, ip); /* { dg-bogus "before used" "unused $ scanf pointer operand" } */
     113    /* { dg-warning "unused" "unused $ scanf pointer operand" { target *-*-* } .-1 } */
     114    /* If there are non-pointer arguments unused at the end, this is also OK.  */
     115    scanf ("%3$d%1$d", ip, ip, ip, i); /* { dg-bogus "before used" "unused $ scanf pointer operand" } */
     116    /* { dg-warning "unused" "unused $ scanf pointer operand" { target *-*-* } .-1 } */
     117    scanf ("%3$d%1$d", ip, i, ip); /* { dg-warning "before used" "unused $ scanf non-pointer operand" } */
     118    /* Can't check the arguments in the vscanf case, so should suppose the
     119       lesser problem.  */
     120    vscanf ("%3$d%1$d", va); /* { dg-bogus "before used" "unused $ scanf pointer operand" } */
     121    /* { dg-warning "unused" "unused $ scanf pointer operand" { target *-*-* } .-1 } */
     122    scanf ("%2$*d%1$d", ip, ip); /* { dg-warning "operand" "operand number with suppression" } */
     123    printf ("%1$d%1$d", i);
     124    scanf ("%1$d%1$d", ip); /* { dg-warning "more than once" "multiple use of scanf argument" } */
     125  }