Commit 5804a754 by Joseph Myers Committed by Joseph Myers

c-common.c (init_dollar_format_checking, [...]): New functions.

	* c-common.c (init_dollar_format_checking,
	maybe_read_dollar_number, finish_dollar_format_checking): New
	functions.
	(dollar_arguments_used, dollar_arguments_count,
	dollar_first_arg_num, dollar_max_arg_used, dollar_format_warned):
	New variables.
	(check_format_info): Support $ formats for scanf and printf width
	and precision.  Always increment format_chars to advance past the
	'*' of precision, not just when the format parameters are
	available to check.

testsuite:
	* gcc.dg/c90-printf-3.c, gcc.dg/c90-scanf-2.c,
	gcc.dg/c90-scanf-3.c, gcc.dg/c90-scanf-4.c,
	gcc.dg/c90-strftime-1.c, gcc.dg/c99-printf-3.c,
	gcc.dg/c99-scanf-1.c, gcc.dg/c99-scanf-2.c, gcc.dg/c99-scanf-3.c,
	gcc.dg/format-xopen-1.c: New tests.

From-SVN: r35856
parent 95adab8e
2000-08-21 Joseph S. Myers <jsm28@cam.ac.uk>
* c-common.c (init_dollar_format_checking,
maybe_read_dollar_number, finish_dollar_format_checking): New
functions.
(dollar_arguments_used, dollar_arguments_count,
dollar_first_arg_num, dollar_max_arg_used, dollar_format_warned):
New variables.
(check_format_info): Support $ formats for scanf and printf width
and precision. Always increment format_chars to advance past the
'*' of precision, not just when the format parameters are
available to check.
2000-08-21 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* mips.c (block_move_loop, expand_block_move,
......
2000-08-21 Joseph S. Myers <jsm28@cam.ac.uk>
* gcc.dg/c90-printf-3.c, gcc.dg/c90-scanf-2.c,
gcc.dg/c90-scanf-3.c, gcc.dg/c90-scanf-4.c,
gcc.dg/c90-strftime-1.c, gcc.dg/c99-printf-3.c,
gcc.dg/c99-scanf-1.c, gcc.dg/c99-scanf-2.c, gcc.dg/c99-scanf-3.c,
gcc.dg/format-xopen-1.c: New tests.
2000-08-21 Joseph S. Myers <jsm28@cam.ac.uk>
* gcc.dg/c90-scanf-1.c, gcc.dg/c94-scanf-1.c: New tests.
2000-08-21 Jakub Jelinek <jakub@redhat.com>
......
/* Test for printf formats. Test that the C90 functions get their default
attributes in strict C90 mode, but the C99 and gettext functions
do not.
*/
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic -Wformat" } */
/* This may not be correct in the particular case, but allows the
prototypes to be declared, and we don't try to link.
*/
typedef struct _FILE FILE;
extern FILE *stdout;
typedef __SIZE_TYPE__ size_t;
typedef __builtin_va_list va_list;
extern int fprintf (FILE *, const char *, ...);
extern int printf (const char *, ...);
extern int sprintf (char *, const char *, ...);
extern int vfprintf (FILE *, const char *, va_list);
extern int vprintf (const char *, va_list);
extern int vsprintf (char *, const char *, va_list);
extern int snprintf (char *, size_t, const char *, ...);
extern int vsnprintf (char *, size_t, const char *, va_list);
extern char *gettext (const char *);
extern char *dgettext (const char *, const char *);
extern char *dcgettext (const char *, const char *, int);
void
foo (int i, char *s, size_t n, va_list v0, va_list v1, va_list v2, va_list v3,
va_list v4, va_list v5, va_list v6, va_list v7, va_list v8)
{
fprintf (stdout, "%d", i);
fprintf (stdout, "%ld", i); /* { dg-warning "format" "fprintf" } */
printf ("%d", i);
printf ("%ld", i); /* { dg-warning "format" "printf" } */
sprintf (s, "%d", i);
sprintf (s, "%ld", i); /* { dg-warning "format" "sprintf" } */
vfprintf (stdout, "%d", v0);
vfprintf (stdout, "%Y", v1); /* { dg-warning "format" "vfprintf" } */
vprintf ("%d", v2);
vprintf ("%Y", v3); /* { dg-warning "format" "vprintf" } */
/* The following used to give a bogus warning. */
vprintf ("%*.*d", v8);
vsprintf (s, "%d", v4);
vsprintf (s, "%Y", v5); /* { dg-warning "format" "vsprintf" } */
snprintf (s, n, "%d", i);
snprintf (s, n, "%ld", i);
vsnprintf (s, n, "%d", v6);
vsnprintf (s, n, "%Y", v7);
printf (gettext ("%d"), i);
printf (gettext ("%ld"), i);
printf (dgettext ("", "%d"), i);
printf (dgettext ("", "%ld"), i);
printf (dcgettext ("", "%d", 0), i);
printf (dcgettext ("", "%ld", 0), i);
}
/* Test for scanf formats. Formats using C99 features should be rejected
outside of C99 mode.
*/
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic -Wformat" } */
typedef __SIZE_TYPE__ size_t;
typedef __PTRDIFF_TYPE__ ptrdiff_t;
__extension__ typedef long long int llong;
/* This next definition is broken. When GCC has a <stdint.h> and
an internal understanding of intmax_t, it should be
replaced by an include of <stdint.h> or by a definition for internal
macros or typedefs.
*/
__extension__ typedef long long int intmax_t;
extern int scanf (const char *, ...);
void
foo (signed char *hhp, float *fp, llong *llp, intmax_t *jp,
size_t *zp, ptrdiff_t *tp)
{
/* Some tests already in c90-scanf-1.c. */
/* The widths hh, ll, j, z, t are new. */
scanf ("%hhd", hhp); /* { dg-warning "length character|C" "%hh in C90" } */
scanf ("%lld", llp); /* { dg-warning "length character|C" "%ll in C90" } */
scanf ("%jd", jp); /* { dg-warning "length character|C" "%j in C90" } */
scanf ("%zu", zp); /* { dg-warning "length character|C" "%z in C90" } */
scanf ("%td", tp); /* { dg-warning "length character|C" "%t in C90" } */
/* The formats F, a, A are new. */
scanf ("%F", fp); /* { dg-warning "C" "%F in C90" } */
scanf ("%a", fp); /* { dg-warning "C" "%a in C90" } */
scanf ("%A", fp); /* { dg-warning "C" "%A in C90" } */
}
/* Test for scanf formats. Formats using extensions to the standard
should be rejected in strict pedantic mode.
*/
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic -Wformat" } */
typedef __WCHAR_TYPE__ wchar_t;
extern int scanf (const char *, ...);
void
foo (char **sp, wchar_t **lsp)
{
/* %a formats for allocation, only recognised in C90 mode, are a
GNU extension.
*/
scanf ("%as", sp); /* { dg-warning "C" "%as" } */
scanf ("%aS", lsp); /* { dg-warning "C" "%aS" } */
scanf ("%a[bcd]", sp); /* { dg-warning "C" "%a[]" } */
}
/* Test for scanf formats. Test that the C90 functions get their default
attributes in strict C90 mode, but the C99 and gettext functions
do not.
*/
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic -Wformat" } */
/* This may not be correct in the particular case, but allows the
prototypes to be declared, and we don't try to link.
*/
typedef struct _FILE FILE;
extern FILE *stdin;
typedef __builtin_va_list va_list;
extern int fscanf (FILE *, const char *, ...);
extern int scanf (const char *, ...);
extern int sscanf (const char *, const char *, ...);
extern int vfscanf (FILE *, const char *, va_list);
extern int vscanf (const char *, va_list);
extern int vsscanf (const char *, const char *, va_list);
extern char *gettext (const char *);
extern char *dgettext (const char *, const char *);
extern char *dcgettext (const char *, const char *, int);
void
foo (int *ip, char *s, va_list v0, va_list v1, va_list v2, va_list v3,
va_list v4, va_list v5)
{
fscanf (stdin, "%d", ip);
fscanf (stdin, "%ld", ip); /* { dg-warning "format" "fscanf" } */
scanf ("%d", ip);
scanf ("%ld", ip); /* { dg-warning "format" "scanf" } */
sscanf (s, "%d", ip);
sscanf (s, "%ld", ip); /* { dg-warning "format" "sscanf" } */
vfscanf (stdin, "%d", v0);
vfscanf (stdin, "%Y", v1);
vscanf ("%d", v2);
vscanf ("%Y", v3);
vsscanf (s, "%d", v4);
vsscanf (s, "%Y", v5);
scanf (gettext ("%d"), ip);
scanf (gettext ("%ld"), ip);
scanf (dgettext ("", "%d"), ip);
scanf (dgettext ("", "%ld"), ip);
scanf (dcgettext ("", "%d", 0), ip);
scanf (dcgettext ("", "%ld", 0), ip);
}
/* Test for strftime formats. Formats using C90 features. */
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic -Wformat" } */
typedef __SIZE_TYPE__ size_t;
struct tm;
extern size_t strftime (char *, size_t, const char *, const struct tm *);
void
foo (char *s, size_t m, const struct tm *tp)
{
/* See ISO/IEC 9899:1990 (E) subclause 7.12.3.5 (pages 174-175). */
/* Formats which are Y2K-compliant (no 2-digit years). */
strftime (s, m, "%a%A%b%B%d%H%I%j%m%M%p%S%U%w%W%X%Y%Z%%", tp);
/* Formats with 2-digit years. */
strftime (s, m, "%y", tp); /* { dg-warning "only last 2" "2-digit year" } */
/* Formats with 2-digit years in some locales. */
strftime (s, m, "%c", tp); /* { dg-warning "some locales" "2-digit year" } */
strftime (s, m, "%x", tp); /* { dg-warning "some locales" "2-digit year" } */
}
/* Test for printf formats. Test that the C99 functions get their default
attributes in strict C99 mode, but the gettext functions do not.
*/
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic -Wformat" } */
/* This may not be correct in the particular case, but allows the
prototypes to be declared, and we don't try to link.
*/
typedef struct _FILE FILE;
extern FILE *stdout;
typedef __SIZE_TYPE__ size_t;
typedef __builtin_va_list va_list;
extern int fprintf (FILE *restrict, const char *restrict, ...);
extern int printf (const char *restrict, ...);
extern int sprintf (char *restrict, const char *restrict, ...);
extern int vfprintf (FILE *restrict, const char *restrict, va_list);
extern int vprintf (const char *restrict, va_list);
extern int vsprintf (char *restrict, const char *restrict, va_list);
extern int snprintf (char *restrict, size_t, const char *restrict, ...);
extern int vsnprintf (char *restrict, size_t, const char *restrict, va_list);
extern char *gettext (const char *);
extern char *dgettext (const char *, const char *);
extern char *dcgettext (const char *, const char *, int);
void
foo (int i, char *s, size_t n, va_list v0, va_list v1, va_list v2, va_list v3,
va_list v4, va_list v5, va_list v6, va_list v7)
{
fprintf (stdout, "%d", i);
fprintf (stdout, "%ld", i); /* { dg-warning "format" "fprintf" } */
printf ("%d", i);
printf ("%ld", i); /* { dg-warning "format" "printf" } */
sprintf (s, "%d", i);
sprintf (s, "%ld", i); /* { dg-warning "format" "sprintf" } */
snprintf (s, n, "%d", i);
snprintf (s, n, "%ld", i); /* { dg-warning "format" "snprintf" } */
vfprintf (stdout, "%d", v0);
vfprintf (stdout, "%Y", v1); /* { dg-warning "format" "vfprintf" } */
vprintf ("%d", v0);
vprintf ("%Y", v1); /* { dg-warning "format" "vprintf" } */
vsprintf (s, "%d", v0);
vsprintf (s, "%Y", v1); /* { dg-warning "format" "vsprintf" } */
vsnprintf (s, n, "%d", v0);
vsnprintf (s, n, "%Y", v1); /* { dg-warning "format" "vsnprintf" } */
printf (gettext ("%d"), i);
printf (gettext ("%ld"), i);
printf (dgettext ("", "%d"), i);
printf (dgettext ("", "%ld"), i);
printf (dcgettext ("", "%d", 0), i);
printf (dcgettext ("", "%ld", 0), i);
}
/* Test for scanf formats. Formats using extensions to the standard
should be rejected in strict pedantic mode.
*/
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic -Wformat" } */
typedef __SIZE_TYPE__ size_t;
typedef __WCHAR_TYPE__ wchar_t;
extern int scanf (const char *, ...);
void
foo (int *ip, long long int *llp, size_t *zp, wchar_t *ls)
{
/* The length modifiers q, Z and L as applied to integer formats are
extensions.
*/
scanf ("%qd", llp); /* { dg-warning "C" "%q length" } */
scanf ("%Ld", llp); /* { dg-warning "C" "%L length" } */
scanf ("%Zu", zp); /* { dg-warning "C" "%Z length" } */
/* The conversion specifiers C and S are X/Open extensions. */
scanf ("%C", ls); /* { dg-warning "C" "scanf %C" } */
scanf ("%S", ls); /* { dg-warning "C" "scanf %S" } */
/* The use of operand number $ formats is an X/Open extension. */
scanf ("%1$d", ip); /* { dg-warning "C" "scanf $ format" } */
}
/* Test for scanf formats. Test that the C99 functions get their default
attributes in strict C99 mode, but the gettext functions do not.
*/
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic -Wformat" } */
/* This may not be correct in the particular case, but allows the
prototypes to be declared, and we don't try to link.
*/
typedef struct _FILE FILE;
extern FILE *stdin;
typedef __builtin_va_list va_list;
extern int fscanf (FILE *restrict, const char *restrict, ...);
extern int scanf (const char *restrict, ...);
extern int sscanf (const char *restrict, const char *restrict, ...);
extern int vfscanf (FILE *restrict, const char *restrict, va_list);
extern int vscanf (const char *restrict, va_list);
extern int vsscanf (const char *restrict, const char *restrict, va_list);
extern char *gettext (const char *);
extern char *dgettext (const char *, const char *);
extern char *dcgettext (const char *, const char *, int);
void
foo (int *ip, char *s, va_list v0, va_list v1, va_list v2, va_list v3,
va_list v4, va_list v5)
{
fscanf (stdin, "%d", ip);
fscanf (stdin, "%ld", ip); /* { dg-warning "format" "fscanf" } */
scanf ("%d", ip);
scanf ("%ld", ip); /* { dg-warning "format" "scanf" } */
sscanf (s, "%d", ip);
sscanf (s, "%ld", ip); /* { dg-warning "format" "sscanf" } */
vfscanf (stdin, "%d", v0);
vfscanf (stdin, "%Y", v1); /* { dg-warning "format" "vfscanf" } */
vscanf ("%d", v2);
vscanf ("%Y", v3); /* { dg-warning "format" "vscanf" } */
vsscanf (s, "%d", v4);
vsscanf (s, "%Y", v5); /* { dg-warning "format" "vsscanf" } */
scanf (gettext ("%d"), ip);
scanf (gettext ("%ld"), ip);
scanf (dgettext ("", "%d"), ip);
scanf (dgettext ("", "%ld"), ip);
scanf (dcgettext ("", "%d", 0), ip);
scanf (dcgettext ("", "%ld", 0), ip);
}
/* Test for X/Open format extensions, as found in the
Single Unix Specification and in Austin Group draft 4, subject to some
Aardvark problem reports submitted.
*/
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */
/* { dg-options "-std=gnu99 -Wformat" } */
typedef __WCHAR_TYPE__ wchar_t;
typedef __WINT_TYPE__ wint_t;
typedef __builtin_va_list va_list;
extern int printf (const char *, ...);
extern int vprintf (const char *, va_list);
extern int scanf (const char *, ...);
void
foo (int i, unsigned int u, wint_t lc, wchar_t *ls, int *ip, double d,
char *s, void *p, int *n, long int l, int i2, float *fp, long int *lp,
va_list va)
{
/* The conversion specifiers C and S, for both printf and scanf,
are X/Open extensions.
*/
printf ("%C", lc);
printf ("%3C", lc);
printf ("%.3C", lc); /* { dg-warning "precision" "precision with %C" } */
printf ("%hC", lc); /* { dg-warning "length character" "bad %hC" } */
printf ("%hhC", lc); /* { dg-warning "length character" "bad %hhC" } */
printf ("%lC", lc); /* { dg-warning "length character" "bad %lC" } */
printf ("%llC", lc); /* { dg-warning "length character" "bad %llC" } */
printf ("%jC", lc); /* { dg-warning "length character" "bad %jC" } */
printf ("%zC", lc); /* { dg-warning "length character" "bad %zC" } */
printf ("%tC", lc); /* { dg-warning "length character" "bad %tC" } */
printf ("%LC", lc); /* { dg-warning "length character" "bad %LC" } */
printf ("%-C", lc);
printf ("%+C", lc); /* { dg-warning "flag" "bad %+C" } */
printf ("% C", lc); /* { dg-warning "flag" "bad % C" } */
printf ("%#C", lc); /* { dg-warning "flag" "bad %#C" } */
printf ("%0C", lc); /* { dg-warning "flag" "bad %0C" } */
printf ("%S", ls);
printf ("%3S", ls);
printf ("%.3S", ls);
printf ("%hS", ls); /* { dg-warning "length character" "bad %hS" } */
printf ("%hhS", ls); /* { dg-warning "length character" "bad %hhS" } */
printf ("%lS", ls); /* { dg-warning "length character" "bad %lS" } */
printf ("%llS", ls); /* { dg-warning "length character" "bad %llS" } */
printf ("%jS", ls); /* { dg-warning "length character" "bad %jS" } */
printf ("%zS", ls); /* { dg-warning "length character" "bad %zS" } */
printf ("%tS", ls); /* { dg-warning "length character" "bad %tS" } */
printf ("%LS", ls); /* { dg-warning "length character" "bad %LS" } */
printf ("%-S", ls);
printf ("%+S", ls); /* { dg-warning "flag" "bad %+S" } */
printf ("% S", ls); /* { dg-warning "flag" "bad % S" } */
printf ("%#S", ls); /* { dg-warning "flag" "bad %#S" } */
printf ("%0S", ls); /* { dg-warning "flag" "bad %0S" } */
scanf ("%C", ls);
scanf ("%S", ls);
scanf ("%*C%*S");
scanf ("%2C%3S", ls, ls);
scanf ("%hC", ls); /* { dg-warning "length character" "bad %hC" } */
scanf ("%hhC", ls); /* { dg-warning "length character" "bad %hhC" } */
scanf ("%lC", ls); /* { dg-warning "length character" "bad %lC" } */
scanf ("%llC", ls); /* { dg-warning "length character" "bad %llC" } */
scanf ("%jC", ls); /* { dg-warning "length character" "bad %jC" } */
scanf ("%zC", ls); /* { dg-warning "length character" "bad %zC" } */
scanf ("%tC", ls); /* { dg-warning "length character" "bad %tC" } */
scanf ("%LC", ls); /* { dg-warning "length character" "bad %LC" } */
scanf ("%hS", ls); /* { dg-warning "length character" "bad %hS" } */
scanf ("%hhS", ls); /* { dg-warning "length character" "bad %hhS" } */
scanf ("%lS", ls); /* { dg-warning "length character" "bad %lS" } */
scanf ("%llS", ls); /* { dg-warning "length character" "bad %llS" } */
scanf ("%jS", ls); /* { dg-warning "length character" "bad %jS" } */
scanf ("%zS", ls); /* { dg-warning "length character" "bad %zS" } */
scanf ("%tS", ls); /* { dg-warning "length character" "bad %tS" } */
scanf ("%LS", ls); /* { dg-warning "length character" "bad %LS" } */
/* In C99 mode (even with extensions), %aS is a floating point
format followed by an S.
*/
scanf ("%aS", fp);
/* The printf flag character ' is an X/Open extension. */
/* Allowing %'F here presumes acceptance of the corresponding Aardvark
report.
*/
printf ("%'d%'i%'u%'f%'F%'g%'G", i, i, u, d, d, d, d);
printf ("%'o", u); /* { dg-warning "flag" "bad use of ' flag" } */
printf ("%'x", u); /* { dg-warning "flag" "bad use of ' flag" } */
printf ("%'X", u); /* { dg-warning "flag" "bad use of ' flag" } */
printf ("%'e", d); /* { dg-warning "flag" "bad use of ' flag" } */
printf ("%'E", d); /* { dg-warning "flag" "bad use of ' flag" } */
printf ("%'a", d); /* { dg-warning "flag" "bad use of ' flag" } */
printf ("%'A", d); /* { dg-warning "flag" "bad use of ' flag" } */
printf ("%'c", i); /* { dg-warning "flag" "bad use of ' flag" } */
printf ("%'s", s); /* { dg-warning "flag" "bad use of ' flag" } */
printf ("%'p", p); /* { dg-warning "flag" "bad use of ' flag" } */
printf ("%'n", n); /* { dg-warning "flag" "bad use of ' flag" } */
/* The use of operand number $ formats is an X/Open extension. */
/* Banning gaps in the arguments used with scanf, and not objecting to
multiple use of an argument with scanf, presumes acceptance of the
corresponding Aardvark reports.
*/
scanf ("%1$d", ip);
printf ("%1$d", i);
printf ("%3$*2$.*1$d", i2, i, l);
printf ("%4$ld%7$ld%5$d%6$d%3$d%1$d%2$d", i, i, i, l, i, i, l);
scanf ("%4$ld%7$ld%5$d%6$d%3$d%1$d%2$d", ip, ip, ip, lp, ip, ip, lp);
printf ("%1$d%d", i, i); /* { dg-warning "missing" "mixing $ and non-$ formats" } */
printf ("%%%1$d%%%2$d", i, i);
printf ("%d%2$d", i); /* { dg-warning "type character" "mixing $ and non-$ formats" } */
printf ("%1$*d", i, i); /* { dg-warning "missing" "mixing $ and non-$ formats" } */
scanf ("%1$d%d", ip, ip); /* { dg-warning "missing" "mixing $ and non-$ formats" } */
scanf ("%*f%%%1$d%%%2$d", ip, ip);
printf ("%2$d", i); /* { dg-warning "operand" "$ number too large" } */
printf ("%0$d", i); /* { dg-warning "operand" "$ number too small" } */
printf ("%3$d%1$d", i, i, i); /* { dg-warning "before used" "unused $ operand" } */
printf ("%2$d%1$d", i, i, i); /* { dg-warning "unused" "unused $ operand" } */
vprintf ("%3$d%1$d", va); /* { dg-warning "before used" "unused $ operand" } */
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment