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
This commit is contained in:
parent
95adab8e11
commit
5804a754e5
13 changed files with 864 additions and 32 deletions
|
@ -1,3 +1,16 @@
|
|||
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,
|
||||
|
|
268
gcc/c-common.c
268
gcc/c-common.c
|
@ -1324,6 +1324,11 @@ static international_format_info *international_format_list = NULL;
|
|||
|
||||
static void check_format_info PARAMS ((function_format_info *, tree));
|
||||
|
||||
static void init_dollar_format_checking PARAMS ((int, tree));
|
||||
static int maybe_read_dollar_number PARAMS ((const char **, int,
|
||||
tree, tree *));
|
||||
static void finish_dollar_format_checking PARAMS ((void));
|
||||
|
||||
/* Initialize the table of functions to perform format checking on.
|
||||
The ISO C functions are always checked (whether <stdio.h> is
|
||||
included or not), since it is common to call printf without
|
||||
|
@ -1501,6 +1506,169 @@ check_function_format (name, assembler_name, params)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Variables used by the checking of $ operand number formats. */
|
||||
static char *dollar_arguments_used = NULL;
|
||||
static int dollar_arguments_alloc = 0;
|
||||
static int dollar_arguments_count;
|
||||
static int dollar_first_arg_num;
|
||||
static int dollar_max_arg_used;
|
||||
static int dollar_format_warned;
|
||||
|
||||
/* Initialize the checking for a format string that may contain $
|
||||
parameter number specifications; we will need to keep track of whether
|
||||
each parameter has been used. FIRST_ARG_NUM is the number of the first
|
||||
argument that is a parameter to the format, or 0 for a vprintf-style
|
||||
function; PARAMS is the list of arguments starting at this argument. */
|
||||
|
||||
static void
|
||||
init_dollar_format_checking (first_arg_num, params)
|
||||
int first_arg_num;
|
||||
tree params;
|
||||
{
|
||||
dollar_first_arg_num = first_arg_num;
|
||||
dollar_arguments_count = 0;
|
||||
dollar_max_arg_used = 0;
|
||||
dollar_format_warned = 0;
|
||||
if (first_arg_num > 0)
|
||||
{
|
||||
while (params)
|
||||
{
|
||||
dollar_arguments_count++;
|
||||
params = TREE_CHAIN (params);
|
||||
}
|
||||
}
|
||||
if (dollar_arguments_alloc < dollar_arguments_count)
|
||||
{
|
||||
if (dollar_arguments_used)
|
||||
free (dollar_arguments_used);
|
||||
dollar_arguments_alloc = dollar_arguments_count;
|
||||
dollar_arguments_used = xmalloc (dollar_arguments_alloc);
|
||||
}
|
||||
if (dollar_arguments_alloc)
|
||||
memset (dollar_arguments_used, 0, dollar_arguments_alloc);
|
||||
}
|
||||
|
||||
|
||||
/* Look for a decimal number followed by a $ in *FORMAT. If DOLLAR_NEEDED
|
||||
is set, it is an error if one is not found; otherwise, it is OK. If
|
||||
such a number is found, check whether it is within range and mark that
|
||||
numbered operand as being used for later checking. Returns the operand
|
||||
number if found and within range, zero if no such number was found and
|
||||
this is OK, or -1 on error. PARAMS points to the first operand of the
|
||||
format; PARAM_PTR is made to point to the parameter referred to. If
|
||||
a $ format is found, *FORMAT is updated to point just after it. */
|
||||
|
||||
static int
|
||||
maybe_read_dollar_number (format, dollar_needed, params, param_ptr)
|
||||
const char **format;
|
||||
int dollar_needed;
|
||||
tree params;
|
||||
tree *param_ptr;
|
||||
{
|
||||
int argnum;
|
||||
int overflow_flag;
|
||||
const char *fcp = *format;
|
||||
if (*fcp < '0' || *fcp > '9')
|
||||
{
|
||||
if (dollar_needed)
|
||||
{
|
||||
warning ("missing $ operand number in format");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
argnum = 0;
|
||||
overflow_flag = 0;
|
||||
while (*fcp >= '0' && *fcp <= '9')
|
||||
{
|
||||
int nargnum;
|
||||
nargnum = 10 * argnum + (*fcp - '0');
|
||||
if (nargnum < 0 || nargnum / 10 != argnum)
|
||||
overflow_flag = 1;
|
||||
argnum = nargnum;
|
||||
fcp++;
|
||||
}
|
||||
if (*fcp != '$')
|
||||
{
|
||||
if (dollar_needed)
|
||||
{
|
||||
warning ("missing $ operand number in format");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
*format = fcp + 1;
|
||||
if (pedantic && !dollar_format_warned)
|
||||
{
|
||||
warning ("ISO C does not support %%n$ operand number formats");
|
||||
dollar_format_warned = 1;
|
||||
}
|
||||
if (overflow_flag || argnum == 0
|
||||
|| (dollar_first_arg_num && argnum > dollar_arguments_count))
|
||||
{
|
||||
warning ("operand number out of range in format");
|
||||
return -1;
|
||||
}
|
||||
if (argnum > dollar_max_arg_used)
|
||||
dollar_max_arg_used = argnum;
|
||||
/* For vprintf-style functions we may need to allocate more memory to
|
||||
track which arguments are used. */
|
||||
while (dollar_arguments_alloc < dollar_max_arg_used)
|
||||
{
|
||||
int nalloc;
|
||||
nalloc = 2 * dollar_arguments_alloc + 16;
|
||||
dollar_arguments_used = xrealloc (dollar_arguments_used, nalloc);
|
||||
memset (dollar_arguments_used + dollar_arguments_alloc, 0,
|
||||
nalloc - dollar_arguments_alloc);
|
||||
dollar_arguments_alloc = nalloc;
|
||||
}
|
||||
dollar_arguments_used[argnum - 1] = 1;
|
||||
if (dollar_first_arg_num)
|
||||
{
|
||||
int i;
|
||||
*param_ptr = params;
|
||||
for (i = 1; i < argnum && *param_ptr != 0; i++)
|
||||
*param_ptr = TREE_CHAIN (*param_ptr);
|
||||
|
||||
if (*param_ptr == 0)
|
||||
{
|
||||
/* This case shouldn't be caught here. */
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
else
|
||||
*param_ptr = 0;
|
||||
return argnum;
|
||||
}
|
||||
|
||||
|
||||
/* Finish the checking for a format string that used $ operand number formats
|
||||
instead of non-$ formats. We check for unused operands before used ones
|
||||
(a serious error, since the implementation of the format function
|
||||
can't know what types to pass to va_arg to find the later arguments).
|
||||
and for unused operands at the end of the format (if we know how many
|
||||
arguments the format had, so not for vprintf). If there were operand
|
||||
numbers out of range on a non-vprintf-style format, we won't have reached
|
||||
here. */
|
||||
|
||||
static void
|
||||
finish_dollar_format_checking ()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < dollar_max_arg_used; i++)
|
||||
{
|
||||
if (!dollar_arguments_used[i])
|
||||
warning ("format argument %d unused before used argument %d in $-style format",
|
||||
i + 1, dollar_max_arg_used);
|
||||
}
|
||||
if (dollar_first_arg_num && dollar_max_arg_used < dollar_arguments_count)
|
||||
warning ("unused arguments in $-style format");
|
||||
}
|
||||
|
||||
|
||||
/* Check the argument list of a call to printf, scanf, etc.
|
||||
INFO points to the function_format_info structure.
|
||||
PARAMS is the list of argument values. */
|
||||
|
@ -1524,7 +1692,9 @@ check_format_info (info, params)
|
|||
const char *format_chars;
|
||||
format_char_info *fci = NULL;
|
||||
char flag_chars[8];
|
||||
int has_operand_number = 0;
|
||||
/* -1 if no conversions taking an operand have been found; 0 if one has
|
||||
and it didn't use $; 1 if $ formats are in use. */
|
||||
int has_operand_number = -1;
|
||||
|
||||
/* Skip to format argument. If the argument isn't available, there's
|
||||
no work for us to do; prototype checking will catch the problem. */
|
||||
|
@ -1624,6 +1794,7 @@ check_format_info (info, params)
|
|||
}
|
||||
|
||||
first_fillin_param = params;
|
||||
init_dollar_format_checking (info->first_arg_num, first_fillin_param);
|
||||
while (1)
|
||||
{
|
||||
int aflag;
|
||||
|
@ -1633,8 +1804,11 @@ check_format_info (info, params)
|
|||
{
|
||||
if (format_chars - TREE_STRING_POINTER (format_tree) != format_length)
|
||||
warning ("embedded `\\0' in format");
|
||||
if (info->first_arg_num != 0 && params != 0 && ! has_operand_number)
|
||||
if (info->first_arg_num != 0 && params != 0
|
||||
&& has_operand_number <= 0)
|
||||
warning ("too many arguments for format");
|
||||
if (has_operand_number > 0)
|
||||
finish_dollar_format_checking ();
|
||||
return;
|
||||
}
|
||||
if (*format_chars++ != '%')
|
||||
|
@ -1657,6 +1831,22 @@ check_format_info (info, params)
|
|||
suppressed = *format_chars == '*';
|
||||
if (suppressed)
|
||||
++format_chars;
|
||||
else if (has_operand_number != 0)
|
||||
{
|
||||
int opnum;
|
||||
opnum = maybe_read_dollar_number (&format_chars,
|
||||
has_operand_number == 1,
|
||||
first_fillin_param, ¶ms);
|
||||
if (opnum == -1)
|
||||
return;
|
||||
else if (opnum > 0)
|
||||
{
|
||||
has_operand_number = 1;
|
||||
arg_num = opnum + info->first_arg_num - 1;
|
||||
}
|
||||
else
|
||||
has_operand_number = 0;
|
||||
}
|
||||
while (ISDIGIT (*format_chars))
|
||||
{
|
||||
wide = TRUE;
|
||||
|
@ -1709,35 +1899,21 @@ check_format_info (info, params)
|
|||
}
|
||||
else if (info->format_type == printf_format_type)
|
||||
{
|
||||
/* See if we have a number followed by a dollar sign. If we do,
|
||||
it is an operand number, so set PARAMS to that operand. */
|
||||
if (*format_chars >= '0' && *format_chars <= '9')
|
||||
if (has_operand_number != 0)
|
||||
{
|
||||
const char *p = format_chars;
|
||||
|
||||
while (*p >= '0' && *p++ <= '9')
|
||||
;
|
||||
|
||||
if (*p == '$')
|
||||
int opnum;
|
||||
opnum = maybe_read_dollar_number (&format_chars,
|
||||
has_operand_number == 1,
|
||||
first_fillin_param, ¶ms);
|
||||
if (opnum == -1)
|
||||
return;
|
||||
else if (opnum > 0)
|
||||
{
|
||||
int opnum = atoi (format_chars);
|
||||
|
||||
if (pedantic)
|
||||
warning ("ISO C does not support printf %%n$");
|
||||
|
||||
params = first_fillin_param;
|
||||
format_chars = p + 1;
|
||||
has_operand_number = 1;
|
||||
|
||||
for (i = 1; i < opnum && params != 0; i++)
|
||||
params = TREE_CHAIN (params);
|
||||
|
||||
if (opnum == 0 || params == 0)
|
||||
{
|
||||
warning ("operand number out of range in format");
|
||||
return;
|
||||
}
|
||||
arg_num = opnum + info->first_arg_num - 1;
|
||||
}
|
||||
else
|
||||
has_operand_number = 0;
|
||||
}
|
||||
|
||||
while (*format_chars != 0 && index (" +#0-'", *format_chars) != 0)
|
||||
|
@ -1774,11 +1950,25 @@ check_format_info (info, params)
|
|||
tfaff ();
|
||||
return;
|
||||
}
|
||||
if (has_operand_number > 0)
|
||||
{
|
||||
int opnum;
|
||||
opnum = maybe_read_dollar_number (&format_chars, 1,
|
||||
first_fillin_param,
|
||||
¶ms);
|
||||
if (opnum <= 0)
|
||||
return;
|
||||
else
|
||||
arg_num = opnum + info->first_arg_num - 1;
|
||||
}
|
||||
if (info->first_arg_num != 0)
|
||||
{
|
||||
cur_param = TREE_VALUE (params);
|
||||
params = TREE_CHAIN (params);
|
||||
++arg_num;
|
||||
if (has_operand_number <= 0)
|
||||
{
|
||||
params = TREE_CHAIN (params);
|
||||
++arg_num;
|
||||
}
|
||||
/* size_t is generally not valid here.
|
||||
It will work on most machines, because size_t and int
|
||||
have the same mode. But might as well warn anyway,
|
||||
|
@ -1807,17 +1997,31 @@ check_format_info (info, params)
|
|||
In this case, an int argument supplies the...precision." */
|
||||
if (*format_chars == '*')
|
||||
{
|
||||
++format_chars;
|
||||
if (has_operand_number > 0)
|
||||
{
|
||||
int opnum;
|
||||
opnum = maybe_read_dollar_number (&format_chars, 1,
|
||||
first_fillin_param,
|
||||
¶ms);
|
||||
if (opnum <= 0)
|
||||
return;
|
||||
else
|
||||
arg_num = opnum + info->first_arg_num - 1;
|
||||
}
|
||||
if (info->first_arg_num != 0)
|
||||
{
|
||||
++format_chars;
|
||||
if (params == 0)
|
||||
{
|
||||
tfaff ();
|
||||
return;
|
||||
}
|
||||
cur_param = TREE_VALUE (params);
|
||||
params = TREE_CHAIN (params);
|
||||
++arg_num;
|
||||
if (has_operand_number <= 0)
|
||||
{
|
||||
params = TREE_CHAIN (params);
|
||||
++arg_num;
|
||||
}
|
||||
if ((TYPE_MAIN_VARIANT (TREE_TYPE (cur_param))
|
||||
!= integer_type_node)
|
||||
&&
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
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.
|
||||
|
|
60
gcc/testsuite/gcc.dg/c90-printf-3.c
Normal file
60
gcc/testsuite/gcc.dg/c90-printf-3.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/* 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);
|
||||
}
|
37
gcc/testsuite/gcc.dg/c90-scanf-2.c
Normal file
37
gcc/testsuite/gcc.dg/c90-scanf-2.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/* 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" } */
|
||||
}
|
21
gcc/testsuite/gcc.dg/c90-scanf-3.c
Normal file
21
gcc/testsuite/gcc.dg/c90-scanf-3.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
/* 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[]" } */
|
||||
}
|
51
gcc/testsuite/gcc.dg/c90-scanf-4.c
Normal file
51
gcc/testsuite/gcc.dg/c90-scanf-4.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/* 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);
|
||||
}
|
23
gcc/testsuite/gcc.dg/c90-strftime-1.c
Normal file
23
gcc/testsuite/gcc.dg/c90-strftime-1.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* 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" } */
|
||||
}
|
56
gcc/testsuite/gcc.dg/c99-printf-3.c
Normal file
56
gcc/testsuite/gcc.dg/c99-printf-3.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/* 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);
|
||||
}
|
165
gcc/testsuite/gcc.dg/c99-scanf-1.c
Normal file
165
gcc/testsuite/gcc.dg/c99-scanf-1.c
Normal file
|
@ -0,0 +1,165 @@
|
|||
/* Test for scanf formats. Formats using C99 features, including cases
|
||||
where C99 specifies some aspect of the format to be ignored or where
|
||||
the behaviour is undefined.
|
||||
*/
|
||||
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-std=iso9899:1999 -pedantic -Wformat" } */
|
||||
|
||||
typedef __WCHAR_TYPE__ wchar_t;
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||
|
||||
/* Kludges to get types corresponding to size_t and ptrdiff_t. */
|
||||
#define unsigned signed
|
||||
typedef __SIZE_TYPE__ signed_size_t;
|
||||
#undef unsigned
|
||||
#define signed /* Type might or might not have explicit 'signed'. */
|
||||
typedef unsigned __PTRDIFF_TYPE__ unsigned_ptrdiff_t;
|
||||
#undef signed
|
||||
|
||||
/* These next definitions are broken. When GCC has a <stdint.h> and
|
||||
an internal understanding of intmax_t and uintmax_t, they should be
|
||||
replaced by an include of <stdint.h> or by definitions for internal
|
||||
macros or typedefs, and the corresponding xfails removed.
|
||||
*/
|
||||
typedef long long int intmax_t;
|
||||
typedef unsigned long long int uintmax_t;
|
||||
|
||||
extern int scanf (const char *, ...);
|
||||
|
||||
void
|
||||
foo (int *ip, unsigned int *uip, short int *hp, unsigned short int *uhp,
|
||||
signed char *hhp, unsigned char *uhhp, long int *lp,
|
||||
unsigned long int *ulp, float *fp, double *dp, long double *ldp, char *s,
|
||||
void **pp, int *n, long long *llp, unsigned long long *ullp, wchar_t *ls,
|
||||
short int *hn, signed char *hhn, long int *ln, long long int *lln,
|
||||
intmax_t *jp, uintmax_t *ujp, intmax_t *jn, size_t *zp,
|
||||
signed_size_t *szp, signed_size_t *zn, ptrdiff_t *tp,
|
||||
unsigned_ptrdiff_t *utp, ptrdiff_t *tn)
|
||||
{
|
||||
/* See ISO/IEC 9899:1999 (E) subclause 7.19.6.2 (pages 281-288).
|
||||
We do not repeat here most of the checks for correct C90 formats
|
||||
or completely broken formats.
|
||||
*/
|
||||
/* Valid, invalid and silly assignment-suppression
|
||||
and width constructions.
|
||||
*/
|
||||
scanf ("%*d%*i%*o%*u%*x%*X%*a%*A%*e%*E%*f%*F%*g%*G%*s%*[abc]%*c%*p");
|
||||
scanf ("%*2d%*8s%*3c");
|
||||
scanf ("%*n"); /* { dg-warning "suppress" "suppression of %n" } */
|
||||
scanf ("%*hd"); /* { dg-warning "together" "suppression with length" } */
|
||||
scanf ("%2d%3i%4o%5u%6x%7X%8a%9A%10e%11E%12f%13F%14g%15G%16s%3[abc]%4c%5p",
|
||||
ip, ip, uip, uip, uip, uip, fp, fp, fp, fp, fp, fp, fp, fp,
|
||||
s, s, s, pp);
|
||||
scanf ("%0d", ip); /* { dg-warning "width" "warning for zero width" } */
|
||||
scanf ("%3n", n); /* { dg-warning "width" "width with %n" } */
|
||||
/* Valid and invalid %h, %hh, %l, %ll, %j, %z, %t, %L constructions. */
|
||||
scanf ("%hd%hi%ho%hu%hx%hX%hn", hp, hp, uhp, uhp, uhp, uhp, hn);
|
||||
scanf ("%ha", fp); /* { dg-warning "length character" "bad use of %h" } */
|
||||
scanf ("%hA", fp); /* { dg-warning "length character" "bad use of %h" } */
|
||||
scanf ("%he", fp); /* { dg-warning "length character" "bad use of %h" } */
|
||||
scanf ("%hE", fp); /* { dg-warning "length character" "bad use of %h" } */
|
||||
scanf ("%hf", fp); /* { dg-warning "length character" "bad use of %h" } */
|
||||
scanf ("%hF", fp); /* { dg-warning "length character" "bad use of %h" } */
|
||||
scanf ("%hg", fp); /* { dg-warning "length character" "bad use of %h" } */
|
||||
scanf ("%hG", fp); /* { dg-warning "length character" "bad use of %h" } */
|
||||
scanf ("%hs", s); /* { dg-warning "length character" "bad use of %h" } */
|
||||
scanf ("%h[ac]", s); /* { dg-warning "length character" "bad use of %h" } */
|
||||
scanf ("%hc", s); /* { dg-warning "length character" "bad use of %h" } */
|
||||
scanf ("%hp", pp); /* { dg-warning "length character" "bad use of %h" } */
|
||||
scanf ("%hhd%hhi%hho%hhu%hhx%hhX%hhn", hhp, hhp, uhhp, uhhp, uhhp, uhhp,
|
||||
hhn);
|
||||
scanf ("%hha", fp); /* { dg-warning "length character" "bad use of %hh" } */
|
||||
scanf ("%hhA", fp); /* { dg-warning "length character" "bad use of %hh" } */
|
||||
scanf ("%hhe", fp); /* { dg-warning "length character" "bad use of %hh" } */
|
||||
scanf ("%hhE", fp); /* { dg-warning "length character" "bad use of %hh" } */
|
||||
scanf ("%hhf", fp); /* { dg-warning "length character" "bad use of %hh" } */
|
||||
scanf ("%hhF", fp); /* { dg-warning "length character" "bad use of %hh" } */
|
||||
scanf ("%hhg", fp); /* { dg-warning "length character" "bad use of %hh" } */
|
||||
scanf ("%hhG", fp); /* { dg-warning "length character" "bad use of %hh" } */
|
||||
scanf ("%hhs", s); /* { dg-warning "length character" "bad use of %hh" } */
|
||||
scanf ("%hh[ac]", s); /* { dg-warning "length character" "bad use of %hh" } */
|
||||
scanf ("%hhc", s); /* { dg-warning "length character" "bad use of %hh" } */
|
||||
scanf ("%hhp", pp); /* { dg-warning "length character" "bad use of %hh" } */
|
||||
scanf ("%ld%li%lo%lu%lx%lX%ln", lp, lp, ulp, ulp, ulp, ulp, ln);
|
||||
scanf ("%la%lA%le%lE%lf%lF%lg%lG", dp, dp, dp, dp, dp, dp, dp, dp);
|
||||
scanf ("%lp", pp); /* { dg-warning "length character" "bad use of %l" } */
|
||||
scanf ("%ls", ls);
|
||||
scanf ("%l[ac]", ls);
|
||||
scanf ("%lc", ls);
|
||||
scanf ("%lld%lli%llo%llu%llx%llX%lln", llp, llp, ullp, ullp, ullp, ullp,
|
||||
lln);
|
||||
scanf ("%lla", fp); /* { dg-warning "length character" "bad use of %ll" } */
|
||||
scanf ("%llA", fp); /* { dg-warning "length character" "bad use of %ll" } */
|
||||
scanf ("%lle", fp); /* { dg-warning "length character" "bad use of %ll" } */
|
||||
scanf ("%llE", fp); /* { dg-warning "length character" "bad use of %ll" } */
|
||||
scanf ("%llf", fp); /* { dg-warning "length character" "bad use of %ll" } */
|
||||
scanf ("%llF", fp); /* { dg-warning "length character" "bad use of %ll" } */
|
||||
scanf ("%llg", fp); /* { dg-warning "length character" "bad use of %ll" } */
|
||||
scanf ("%llG", fp); /* { dg-warning "length character" "bad use of %ll" } */
|
||||
scanf ("%lls", s); /* { dg-warning "length character" "bad use of %ll" } */
|
||||
scanf ("%ll[ac]", s); /* { dg-warning "length character" "bad use of %ll" } */
|
||||
scanf ("%llc", s); /* { dg-warning "length character" "bad use of %ll" } */
|
||||
scanf ("%llp", pp); /* { dg-warning "length character" "bad use of %ll" } */
|
||||
scanf ("%jd%ji%jo%ju%jx%jX%jn", jp, jp, ujp, ujp, ujp, ujp, jn); /* { dg-bogus "length character" "bogus %j warning" { xfail *-*-* } } */
|
||||
scanf ("%ja", fp); /* { dg-warning "length character" "bad use of %j" } */
|
||||
scanf ("%jA", fp); /* { dg-warning "length character" "bad use of %j" } */
|
||||
scanf ("%je", fp); /* { dg-warning "length character" "bad use of %j" } */
|
||||
scanf ("%jE", fp); /* { dg-warning "length character" "bad use of %j" } */
|
||||
scanf ("%jf", fp); /* { dg-warning "length character" "bad use of %j" } */
|
||||
scanf ("%jF", fp); /* { dg-warning "length character" "bad use of %j" } */
|
||||
scanf ("%jg", fp); /* { dg-warning "length character" "bad use of %j" } */
|
||||
scanf ("%jG", fp); /* { dg-warning "length character" "bad use of %j" } */
|
||||
scanf ("%js", s); /* { dg-warning "length character" "bad use of %j" } */
|
||||
scanf ("%j[ac]", s); /* { dg-warning "length character" "bad use of %j" } */
|
||||
scanf ("%jc", s); /* { dg-warning "length character" "bad use of %j" } */
|
||||
scanf ("%jp", pp); /* { dg-warning "length character" "bad use of %j" } */
|
||||
scanf ("%zd%zi%zo%zu%zx%zX%zn", szp, szp, zp, zp, zp, zp, zn);
|
||||
scanf ("%za", fp); /* { dg-warning "length character" "bad use of %z" } */
|
||||
scanf ("%zA", fp); /* { dg-warning "length character" "bad use of %z" } */
|
||||
scanf ("%ze", fp); /* { dg-warning "length character" "bad use of %z" } */
|
||||
scanf ("%zE", fp); /* { dg-warning "length character" "bad use of %z" } */
|
||||
scanf ("%zf", fp); /* { dg-warning "length character" "bad use of %z" } */
|
||||
scanf ("%zF", fp); /* { dg-warning "length character" "bad use of %z" } */
|
||||
scanf ("%zg", fp); /* { dg-warning "length character" "bad use of %z" } */
|
||||
scanf ("%zG", fp); /* { dg-warning "length character" "bad use of %z" } */
|
||||
scanf ("%zs", s); /* { dg-warning "length character" "bad use of %z" } */
|
||||
scanf ("%z[ac]", s); /* { dg-warning "length character" "bad use of %z" } */
|
||||
scanf ("%zc", s); /* { dg-warning "length character" "bad use of %z" } */
|
||||
scanf ("%zp", pp); /* { dg-warning "length character" "bad use of %z" } */
|
||||
scanf ("%td%ti%to%tu%tx%tX%tn", tp, tp, utp, utp, utp, utp, tn);
|
||||
scanf ("%ta", fp); /* { dg-warning "length character" "bad use of %t" } */
|
||||
scanf ("%tA", fp); /* { dg-warning "length character" "bad use of %t" } */
|
||||
scanf ("%te", fp); /* { dg-warning "length character" "bad use of %t" } */
|
||||
scanf ("%tE", fp); /* { dg-warning "length character" "bad use of %t" } */
|
||||
scanf ("%tf", fp); /* { dg-warning "length character" "bad use of %t" } */
|
||||
scanf ("%tF", fp); /* { dg-warning "length character" "bad use of %t" } */
|
||||
scanf ("%tg", fp); /* { dg-warning "length character" "bad use of %t" } */
|
||||
scanf ("%tG", fp); /* { dg-warning "length character" "bad use of %t" } */
|
||||
scanf ("%ts", s); /* { dg-warning "length character" "bad use of %t" } */
|
||||
scanf ("%t[ac]", s); /* { dg-warning "length character" "bad use of %t" } */
|
||||
scanf ("%tc", s); /* { dg-warning "length character" "bad use of %t" } */
|
||||
scanf ("%tp", pp); /* { dg-warning "length character" "bad use of %t" } */
|
||||
scanf ("%La%LA%Le%LE%Lf%LF%Lg%LG", ldp, ldp, ldp, ldp, ldp, ldp, ldp, ldp);
|
||||
scanf ("%Ld", llp); /* { dg-warning "does not support" "bad use of %L" } */
|
||||
scanf ("%Li", llp); /* { dg-warning "does not support" "bad use of %L" } */
|
||||
scanf ("%Lo", ullp); /* { dg-warning "does not support" "bad use of %L" } */
|
||||
scanf ("%Lu", ullp); /* { dg-warning "does not support" "bad use of %L" } */
|
||||
scanf ("%Lx", ullp); /* { dg-warning "does not support" "bad use of %L" } */
|
||||
scanf ("%LX", ullp); /* { dg-warning "does not support" "bad use of %L" } */
|
||||
scanf ("%Ls", s); /* { dg-warning "length character" "bad use of %L" } */
|
||||
scanf ("%L[ac]", s); /* { dg-warning "length character" "bad use of %L" } */
|
||||
scanf ("%Lc", s); /* { dg-warning "length character" "bad use of %L" } */
|
||||
scanf ("%Lp", pp); /* { dg-warning "length character" "bad use of %L" } */
|
||||
scanf ("%Ln", n); /* { dg-warning "length character" "bad use of %L" } */
|
||||
/* Valid uses of each bare conversion. */
|
||||
scanf ("%d%i%o%u%x%X%a%A%e%E%f%F%g%G%s%[abc]%c%p%n%%", ip, ip, uip, uip, uip,
|
||||
uip, fp, fp, fp, fp, fp, fp, fp, fp, s, s, s, pp, n);
|
||||
/* Assert that %as is not treated as an extension in C99 mode. */
|
||||
scanf ("%as", fp);
|
||||
scanf ("%a[", fp);
|
||||
/* Tests for bad argument types: pointer target sign with %hh. */
|
||||
scanf ("%hhd", uhhp); /* { dg-warning "format" "%hhd sign" } */
|
||||
scanf ("%hhu", hhp); /* { dg-warning "format" "%hhu sign" } */
|
||||
}
|
27
gcc/testsuite/gcc.dg/c99-scanf-2.c
Normal file
27
gcc/testsuite/gcc.dg/c99-scanf-2.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* 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" } */
|
||||
}
|
49
gcc/testsuite/gcc.dg/c99-scanf-3.c
Normal file
49
gcc/testsuite/gcc.dg/c99-scanf-3.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* 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);
|
||||
}
|
118
gcc/testsuite/gcc.dg/format-xopen-1.c
Normal file
118
gcc/testsuite/gcc.dg/format-xopen-1.c
Normal file
|
@ -0,0 +1,118 @@
|
|||
/* 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" } */
|
||||
}
|
Loading…
Add table
Reference in a new issue