Commit b691cb00 by Joseph Myers Committed by Joseph Myers

c-common.c (FMT_FLAG_DOLLAR_MULTIPLE): Define.

	* c-common.c (FMT_FLAG_DOLLAR_MULTIPLE): Define.
	(format_types): Use it for printf.
	(maybe_read_dollar_number): Add parameter for the kind of format
	involved.  Warn for multiple use for arguments if this is
	inappropriate for the kind of format involved.
	(check_format_info_main): Update calls to maybe_read_dollar_number.

testsuite:
	* gcc.dg/format-xopen-1.c: Update comments; adjust for checking
	for multiple use of arguments with scanf formats; add tests for
	multiple use of arguments.

From-SVN: r36905
parent 948eab23
2000-10-17 Joseph S. Myers <jsm28@cam.ac.uk>
* c-common.c (FMT_FLAG_DOLLAR_MULTIPLE): Define.
(format_types): Use it for printf.
(maybe_read_dollar_number): Add parameter for the kind of format
involved. Warn for multiple use for arguments if this is
inappropriate for the kind of format involved.
(check_format_info_main): Update calls to maybe_read_dollar_number.
2000-10-17 J. David Anglin <dave@hiauly1.hia.nrc.ca> 2000-10-17 J. David Anglin <dave@hiauly1.hia.nrc.ca>
* inclhack.def (hpux_maxint): Also apply fix to values.h. * inclhack.def (hpux_maxint): Also apply fix to values.h.
......
...@@ -1272,7 +1272,10 @@ enum ...@@ -1272,7 +1272,10 @@ enum
FMT_FLAG_SCANF_A_KLUDGE = 2, FMT_FLAG_SCANF_A_KLUDGE = 2,
/* A % during parsing a specifier is allowed to be a modified % rather /* A % during parsing a specifier is allowed to be a modified % rather
that indicating the format is broken and we are out-of-sync. */ that indicating the format is broken and we are out-of-sync. */
FMT_FLAG_FANCY_PERCENT_OK = 4 FMT_FLAG_FANCY_PERCENT_OK = 4,
/* With $ operand numbers, it is OK to reference the same argument more
than once. */
FMT_FLAG_DOLLAR_MULTIPLE = 8
/* Not included here: details of whether width or precision may occur /* Not included here: details of whether width or precision may occur
(controlled by width_char and precision_char); details of whether (controlled by width_char and precision_char); details of whether
'*' can be used for these (width_type and precision_type); details '*' can be used for these (width_type and precision_type); details
...@@ -1692,7 +1695,7 @@ static const format_kind_info format_types[] = ...@@ -1692,7 +1695,7 @@ static const format_kind_info format_types[] =
{ {
{ "printf", printf_length_specs, print_char_table, " +#0-'I", NULL, { "printf", printf_length_specs, print_char_table, " +#0-'I", NULL,
printf_flag_specs, printf_flag_pairs, printf_flag_specs, printf_flag_pairs,
FMT_FLAG_ARG_CONVERT, 'w', 'p', 0, 'L', FMT_FLAG_ARG_CONVERT|FMT_FLAG_DOLLAR_MULTIPLE, 'w', 'p', 0, 'L',
&integer_type_node, &integer_type_node &integer_type_node, &integer_type_node
}, },
{ "scanf", scanf_length_specs, scan_char_table, "*'I", NULL, { "scanf", scanf_length_specs, scan_char_table, "*'I", NULL,
...@@ -1769,7 +1772,8 @@ static void status_warning PARAMS ((int *, const char *, ...)) ...@@ -1769,7 +1772,8 @@ static void status_warning PARAMS ((int *, const char *, ...))
static void init_dollar_format_checking PARAMS ((int, tree)); static void init_dollar_format_checking PARAMS ((int, tree));
static int maybe_read_dollar_number PARAMS ((int *, const char **, int, static int maybe_read_dollar_number PARAMS ((int *, const char **, int,
tree, tree *)); tree, tree *,
const format_kind_info *));
static void finish_dollar_format_checking PARAMS ((int *, format_check_results *)); static void finish_dollar_format_checking PARAMS ((int *, format_check_results *));
static const format_flag_spec *get_flag_spec PARAMS ((const format_flag_spec *, static const format_flag_spec *get_flag_spec PARAMS ((const format_flag_spec *,
...@@ -2059,12 +2063,14 @@ init_dollar_format_checking (first_arg_num, params) ...@@ -2059,12 +2063,14 @@ init_dollar_format_checking (first_arg_num, params)
a $ format is found, *FORMAT is updated to point just after it. */ a $ format is found, *FORMAT is updated to point just after it. */
static int static int
maybe_read_dollar_number (status, format, dollar_needed, params, param_ptr) maybe_read_dollar_number (status, format, dollar_needed, params, param_ptr,
fki)
int *status; int *status;
const char **format; const char **format;
int dollar_needed; int dollar_needed;
tree params; tree params;
tree *param_ptr; tree *param_ptr;
const format_kind_info *fki;
{ {
int argnum; int argnum;
int overflow_flag; int overflow_flag;
...@@ -2125,6 +2131,15 @@ maybe_read_dollar_number (status, format, dollar_needed, params, param_ptr) ...@@ -2125,6 +2131,15 @@ maybe_read_dollar_number (status, format, dollar_needed, params, param_ptr)
nalloc - dollar_arguments_alloc); nalloc - dollar_arguments_alloc);
dollar_arguments_alloc = nalloc; dollar_arguments_alloc = nalloc;
} }
if (!(fki->flags & FMT_FLAG_DOLLAR_MULTIPLE)
&& dollar_arguments_used[argnum - 1] == 1)
{
dollar_arguments_used[argnum - 1] = 2;
status_warning (status,
"format argument %d used more than once in %s format",
argnum, fki->name);
}
else
dollar_arguments_used[argnum - 1] = 1; dollar_arguments_used[argnum - 1] = 1;
if (dollar_first_arg_num) if (dollar_first_arg_num)
{ {
...@@ -2531,7 +2546,7 @@ check_format_info_main (status, res, info, format_chars, format_length, ...@@ -2531,7 +2546,7 @@ check_format_info_main (status, res, info, format_chars, format_length,
int opnum; int opnum;
opnum = maybe_read_dollar_number (status, &format_chars, 0, opnum = maybe_read_dollar_number (status, &format_chars, 0,
first_fillin_param, first_fillin_param,
&main_arg_params); &main_arg_params, fki);
if (opnum == -1) if (opnum == -1)
return; return;
else if (opnum > 0) else if (opnum > 0)
...@@ -2583,7 +2598,7 @@ check_format_info_main (status, res, info, format_chars, format_length, ...@@ -2583,7 +2598,7 @@ check_format_info_main (status, res, info, format_chars, format_length,
opnum = maybe_read_dollar_number (status, &format_chars, opnum = maybe_read_dollar_number (status, &format_chars,
has_operand_number == 1, has_operand_number == 1,
first_fillin_param, first_fillin_param,
&params); &params, fki);
if (opnum == -1) if (opnum == -1)
return; return;
else if (opnum > 0) else if (opnum > 0)
...@@ -2662,7 +2677,7 @@ check_format_info_main (status, res, info, format_chars, format_length, ...@@ -2662,7 +2677,7 @@ check_format_info_main (status, res, info, format_chars, format_length,
opnum = maybe_read_dollar_number (status, &format_chars, opnum = maybe_read_dollar_number (status, &format_chars,
has_operand_number == 1, has_operand_number == 1,
first_fillin_param, first_fillin_param,
&params); &params, fki);
if (opnum == -1) if (opnum == -1)
return; return;
else if (opnum > 0) else if (opnum > 0)
......
2000-10-17 Joseph S. Myers <jsm28@cam.ac.uk>
* gcc.dg/format-xopen-1.c: Update comments; adjust for checking
for multiple use of arguments with scanf formats; add tests for
multiple use of arguments.
2000-10-17 Bernd Schmidt <bernds@redhat.co.uk> 2000-10-17 Bernd Schmidt <bernds@redhat.co.uk>
* gcc.dg/sequence-pt-1.c: Several new tests; remove xfail from some old tests. * gcc.dg/sequence-pt-1.c: Several new tests; remove xfail from some old tests.
......
/* Test for X/Open format extensions, as found in the /* Test for X/Open format extensions, as found in the
Single Unix Specification and in Austin Group draft 4, subject to some Single Unix Specification and in Austin Group draft 4, subject to some
Aardvark problem reports submitted. Aardvark problem reports approved as changes.
*/ */
/* Origin: Joseph Myers <jsm28@cam.ac.uk> */ /* Origin: Joseph Myers <jsm28@cam.ac.uk> */
/* { dg-do compile } */ /* { dg-do compile } */
...@@ -81,9 +81,6 @@ foo (int i, unsigned int u, wint_t lc, wchar_t *ls, int *ip, double d, ...@@ -81,9 +81,6 @@ foo (int i, unsigned int u, wint_t lc, wchar_t *ls, int *ip, double d,
*/ */
scanf ("%aS", fp); scanf ("%aS", fp);
/* The printf flag character ' is an X/Open extension. */ /* 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 ("%'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 ("%'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" } */
...@@ -97,9 +94,9 @@ foo (int i, unsigned int u, wint_t lc, wchar_t *ls, int *ip, double d, ...@@ -97,9 +94,9 @@ foo (int i, unsigned int u, wint_t lc, wchar_t *ls, int *ip, double d,
printf ("%'p", p); /* { 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" } */ printf ("%'n", n); /* { dg-warning "flag" "bad use of ' flag" } */
/* The use of operand number $ formats is an X/Open extension. */ /* The use of operand number $ formats is an X/Open extension. */
/* Banning gaps in the arguments used with scanf, and not objecting to /* Banning gaps in the arguments used with scanf was covered in Aardvark
multiple use of an argument with scanf, presumes acceptance of the report XSHd4 ERN 164, which was rejected, but implementation without
corresponding Aardvark reports. such a ban still isn't possible within ISO C.
*/ */
scanf ("%1$d", ip); scanf ("%1$d", ip);
printf ("%1$d", i); printf ("%1$d", i);
...@@ -119,5 +116,7 @@ foo (int i, unsigned int u, wint_t lc, wchar_t *ls, int *ip, double d, ...@@ -119,5 +116,7 @@ foo (int i, unsigned int u, wint_t lc, wchar_t *ls, int *ip, double d,
printf ("%3$d%1$d", i, i, i); /* { dg-warning "before used" "unused $ operand" } */ 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" } */ 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" } */ vprintf ("%3$d%1$d", va); /* { dg-warning "before used" "unused $ operand" } */
scanf ("%1$*d%1$d", ip); /* { dg-warning "operand" "operand number with suppression" } */ scanf ("%2$*d%1$d", ip, ip); /* { dg-warning "operand" "operand number with suppression" } */
printf ("%1$d%1$d", i);
scanf ("%1$d%1$d", ip); /* { dg-warning "more than once" "multiple use of scanf argument" } */
} }
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