Commit e9a75776 by Joseph Myers Committed by Joseph Myers

re PR c/15444 (Bad warning message in printf format checking)

	PR c/15444
	* c-format.c (avoid_dollar_number): New function.
	(check_format_info_main): Call avoid_dollar_number when operand
	numbers might occur but has_operand_number == 0.

testsuite:
	* gcc.dg/format/xopen-1.c: Adjust expected message.
	* gcc.dg/format/xopen-3.c: New test.

From-SVN: r81871
parent 5c3be6fd
2004-05-15 Joseph S. Myers <jsm@polyomino.org.uk>
PR c/15444
* c-format.c (avoid_dollar_number): New function.
(check_format_info_main): Call avoid_dollar_number when operand
numbers might occur but has_operand_number == 0.
2004-05-14 Richard Earnshaw <rearnsha@arm.com> 2004-05-14 Richard Earnshaw <rearnsha@arm.com>
* arm.md (all peephole2 patterns): Use predicates that validate * arm.md (all peephole2 patterns): Use predicates that validate
......
...@@ -1023,6 +1023,7 @@ static void status_warning (int *, const char *, ...) ...@@ -1023,6 +1023,7 @@ static void status_warning (int *, const char *, ...)
static void init_dollar_format_checking (int, tree); static void init_dollar_format_checking (int, tree);
static int maybe_read_dollar_number (int *, const char **, int, static int maybe_read_dollar_number (int *, const char **, int,
tree, tree *, const format_kind_info *); tree, tree *, const format_kind_info *);
static bool avoid_dollar_number (int *, const char *);
static void finish_dollar_format_checking (int *, format_check_results *, int); static void finish_dollar_format_checking (int *, format_check_results *, int);
static const format_flag_spec *get_flag_spec (const format_flag_spec *, static const format_flag_spec *get_flag_spec (const format_flag_spec *,
...@@ -1304,6 +1305,26 @@ maybe_read_dollar_number (int *status, const char **format, ...@@ -1304,6 +1305,26 @@ maybe_read_dollar_number (int *status, const char **format,
return argnum; return argnum;
} }
/* Ensure that FORMAT does not start with a decimal number followed by
a $; give a diagnostic and return true if it does, false otherwise. */
static bool
avoid_dollar_number (int *status, const char *format)
{
if (!ISDIGIT (*format))
return false;
while (ISDIGIT (*format))
format++;
if (*format == '$')
{
status_warning (status,
"$ operand number used after format"
" without operand number");
return true;
}
return false;
}
/* Finish the checking for a format string that used $ operand number formats /* Finish the checking for a format string that used $ operand number formats
instead of non-$ formats. We check for unused operands before used ones instead of non-$ formats. We check for unused operands before used ones
...@@ -1721,6 +1742,11 @@ check_format_info_main (int *status, format_check_results *res, ...@@ -1721,6 +1742,11 @@ check_format_info_main (int *status, format_check_results *res,
main_arg_num = opnum + info->first_arg_num - 1; main_arg_num = opnum + info->first_arg_num - 1;
} }
} }
else if (fki->flags & FMT_FLAG_USE_DOLLAR)
{
if (avoid_dollar_number (status, format_chars))
return;
}
/* Read any format flags, but do not yet validate them beyond removing /* Read any format flags, but do not yet validate them beyond removing
duplicates, since in general validation depends on the rest of duplicates, since in general validation depends on the rest of
...@@ -1780,6 +1806,11 @@ check_format_info_main (int *status, format_check_results *res, ...@@ -1780,6 +1806,11 @@ check_format_info_main (int *status, format_check_results *res,
else else
has_operand_number = 0; has_operand_number = 0;
} }
else
{
if (avoid_dollar_number (status, format_chars))
return;
}
if (info->first_arg_num != 0) if (info->first_arg_num != 0)
{ {
if (params == 0) if (params == 0)
...@@ -1879,6 +1910,11 @@ check_format_info_main (int *status, format_check_results *res, ...@@ -1879,6 +1910,11 @@ check_format_info_main (int *status, format_check_results *res,
else else
has_operand_number = 0; has_operand_number = 0;
} }
else
{
if (avoid_dollar_number (status, format_chars))
return;
}
if (info->first_arg_num != 0) if (info->first_arg_num != 0)
{ {
if (params == 0) if (params == 0)
......
2004-05-15 Joseph S. Myers <jsm@polyomino.org.uk>
PR c/15444
* gcc.dg/format/xopen-1.c: Adjust expected message.
* gcc.dg/format/xopen-3.c: New test.
2004-05-14 Victor Leikehman <lei@haifasphere.co.il> 2004-05-14 Victor Leikehman <lei@haifasphere.co.il>
* gfortran.fortran-torture/execute/def_init_3.f90: New test. * gfortran.fortran-torture/execute/def_init_3.f90: New test.
......
...@@ -95,7 +95,7 @@ foo (int i, unsigned int u, wint_t lc, wchar_t *ls, int *ip, double d, ...@@ -95,7 +95,7 @@ foo (int i, unsigned int u, wint_t lc, wchar_t *ls, int *ip, double d,
scanf ("%4$ld%7$ld%5$d%6$d%3$d%1$d%2$d", ip, ip, ip, lp, ip, ip, lp); 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%d", i, i); /* { dg-warning "missing" "mixing $ and non-$ formats" } */
printf ("%%%1$d%%%2$d", i, i); printf ("%%%1$d%%%2$d", i, i);
printf ("%d%2$d", i); /* { dg-warning "type character" "mixing $ and non-$ formats" } */ printf ("%d%2$d", i); /* { dg-warning "used after format" "mixing $ and non-$ formats" } */
printf ("%1$*d", i, i); /* { dg-warning "missing" "mixing $ and non-$ formats" } */ printf ("%1$*d", i, i); /* { dg-warning "missing" "mixing $ and non-$ formats" } */
printf ("%*1$d", i); /* { dg-warning "missing" "mixing $ and non-$ formats" } */ printf ("%*1$d", i); /* { dg-warning "missing" "mixing $ and non-$ formats" } */
scanf ("%1$d%d", ip, ip); /* { dg-warning "missing" "mixing $ and non-$ formats" } */ scanf ("%1$d%d", ip, ip); /* { dg-warning "missing" "mixing $ and non-$ formats" } */
......
/* Test for warnings for $ operand numbers after ordinary formats.
Bug c/15444 from james-gcc-bugzilla-501qll3d at and dot org. */
/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
/* { dg-do compile } */
/* { dg-options "-std=gnu99 -Wformat" } */
#include "format.h"
void
foo (int i)
{
printf ("%d%2$d", i); /* { dg-warning "used after format" "mixing $ and non-$ formats" } */
printf ("%d%*1$d", i, i); /* { dg-warning "used after format" "mixing $ and non-$ formats" } */
printf ("%d%.*1$d", i, i); /* { dg-warning "used after format" "mixing $ and non-$ formats" } */
}
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