summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJoseph Myers <jsm28@cam.ac.uk>2000-09-18 17:34:35 +0100
committerJoseph Myers <jsm28@gcc.gnu.org>2000-09-18 17:34:35 +0100
commitfc6df7e10bc1039f50f917ecfe3740d38aa40674 (patch)
treeafe91fed3f051f85e64931d64e2e92df5c5a70b3 /gcc
parenteffa55410383b2a76aee22e37c86c5d11e95aad9 (diff)
downloadgcc-fc6df7e10bc1039f50f917ecfe3740d38aa40674.tar.gz
c-common.c (check_format_info): Properly save the argument number and parameter for $ operand number formats in...
* c-common.c (check_format_info): Properly save the argument number and parameter for $ operand number formats in case width and precision arguments are also used. Allow printf width and precision arguments to have operand numbers even if none was specified for the main format, since this is OK for %*.*m. Only object to missing $ operand number if the format used requires an argument. testsuite: * gcc.dg/format-ext-1.c: Add tests for mixing %m with $ formats. * gcc.dg/format-xopen-1.c: Fix error in one $ format test. Add more $ format tests. From-SVN: r36493
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/c-common.c75
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/format-ext-1.c9
-rw-r--r--gcc/testsuite/gcc.dg/format-xopen-1.c4
5 files changed, 82 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index faaf564c2ee..4a0d658e38f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,15 @@
2000-09-18 Joseph S. Myers <jsm28@cam.ac.uk>
+ * c-common.c (check_format_info): Properly save the argument
+ number and parameter for $ operand number formats in case width
+ and precision arguments are also used. Allow printf width and
+ precision arguments to have operand numbers even if none was
+ specified for the main format, since this is OK for %*.*m. Only
+ object to missing $ operand number if the format used requires an
+ argument.
+
+2000-09-18 Joseph S. Myers <jsm28@cam.ac.uk>
+
* c-common.c (format_char_info): Add 'W' flag to comment.
(print_char_table, scan_char_table): Use it.
(check_format_info): Use the 'W' flag to determine whether a
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 7cdde8bd684..6a1e687f42c 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -1904,6 +1904,8 @@ check_format_info (info, params)
tree format_tree;
tree cur_param;
tree wanted_type;
+ int main_arg_num;
+ tree main_arg_params;
enum format_std_version wanted_type_std;
const char *wanted_type_name;
format_wanted_type width_wanted_type;
@@ -2051,6 +2053,8 @@ check_format_info (info, params)
}
flag_chars[0] = 0;
suppressed = wide = precise = FALSE;
+ main_arg_num = 0;
+ main_arg_params = 0;
if (info->format_type == scanf_format_type)
{
int non_zero_width_char = FALSE;
@@ -2062,13 +2066,14 @@ check_format_info (info, params)
int opnum;
opnum = maybe_read_dollar_number (&format_chars,
has_operand_number == 1,
- first_fillin_param, &params);
+ first_fillin_param,
+ &main_arg_params);
if (opnum == -1)
return;
else if (opnum > 0)
{
has_operand_number = 1;
- arg_num = opnum + info->first_arg_num - 1;
+ main_arg_num = opnum + info->first_arg_num - 1;
}
else
has_operand_number = 0;
@@ -2129,17 +2134,15 @@ check_format_info (info, params)
{
int opnum;
opnum = maybe_read_dollar_number (&format_chars,
- has_operand_number == 1,
- first_fillin_param, &params);
+ 0, first_fillin_param,
+ &main_arg_params);
if (opnum == -1)
return;
else if (opnum > 0)
{
has_operand_number = 1;
- arg_num = opnum + info->first_arg_num - 1;
+ main_arg_num = opnum + info->first_arg_num - 1;
}
- else
- has_operand_number = 0;
}
while (*format_chars != 0 && index (" +#0-'I", *format_chars) != 0)
@@ -2178,16 +2181,22 @@ check_format_info (info, params)
tfaff ();
return;
}
- if (has_operand_number > 0)
+ if (has_operand_number != 0)
{
int opnum;
- opnum = maybe_read_dollar_number (&format_chars, 1,
+ opnum = maybe_read_dollar_number (&format_chars,
+ has_operand_number == 1,
first_fillin_param,
&params);
- if (opnum <= 0)
+ if (opnum == -1)
return;
+ else if (opnum > 0)
+ {
+ has_operand_number = 1;
+ arg_num = opnum + info->first_arg_num - 1;
+ }
else
- arg_num = opnum + info->first_arg_num - 1;
+ has_operand_number = 0;
}
if (info->first_arg_num != 0)
{
@@ -2230,16 +2239,22 @@ check_format_info (info, params)
if (*format_chars == '*')
{
++format_chars;
- if (has_operand_number > 0)
+ if (has_operand_number != 0)
{
int opnum;
- opnum = maybe_read_dollar_number (&format_chars, 1,
+ opnum = maybe_read_dollar_number (&format_chars,
+ has_operand_number == 1,
first_fillin_param,
&params);
- if (opnum <= 0)
+ if (opnum == -1)
return;
+ else if (opnum > 0)
+ {
+ has_operand_number = 1;
+ arg_num = opnum + info->first_arg_num - 1;
+ }
else
- arg_num = opnum + info->first_arg_num - 1;
+ has_operand_number = 0;
}
if (info->first_arg_num != 0)
{
@@ -2466,16 +2481,36 @@ check_format_info (info, params)
/* Finally. . .check type of argument against desired type! */
if (info->first_arg_num == 0)
continue;
- if (!(fci->pointer_count == 0 && wanted_type == void_type_node))
+ if (fci->pointer_count == 0 && wanted_type == void_type_node)
{
- if (params == 0)
+ if (main_arg_num != 0)
+ warning ("operand number specified for format taking no argument");
+ }
+ else
+ {
+ if (main_arg_num != 0)
{
- tfaff ();
- return;
+ arg_num = main_arg_num;
+ params = main_arg_params;
+ }
+ else
+ {
+ ++arg_num;
+ if (has_operand_number > 0)
+ {
+ warning ("missing $ operand number in format");
+ return;
+ }
+ else
+ has_operand_number = 0;
+ if (params == 0)
+ {
+ tfaff ();
+ return;
+ }
}
cur_param = TREE_VALUE (params);
params = TREE_CHAIN (params);
- ++arg_num;
main_wanted_type.wanted_type = wanted_type;
main_wanted_type.wanted_type_name = wanted_type_name;
main_wanted_type.pointer_count = fci->pointer_count + aflag;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d688bf7e26e..1c133108712 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,11 @@
2000-09-18 Joseph S. Myers <jsm28@cam.ac.uk>
+ * gcc.dg/format-ext-1.c: Add tests for mixing %m with $ formats.
+ * gcc.dg/format-xopen-1.c: Fix error in one $ format test. Add
+ more $ format tests.
+
+2000-09-18 Joseph S. Myers <jsm28@cam.ac.uk>
+
* gcc.dg/format-errmk-1.c: New test.
2000-09-17 Greg McGary <greg@mcgary.org>
diff --git a/gcc/testsuite/gcc.dg/format-ext-1.c b/gcc/testsuite/gcc.dg/format-ext-1.c
index 459d114e67d..238a47802be 100644
--- a/gcc/testsuite/gcc.dg/format-ext-1.c
+++ b/gcc/testsuite/gcc.dg/format-ext-1.c
@@ -18,7 +18,7 @@ extern int printf (const char *, ...);
void
foo (quad_t q, u_quad_t uq, quad_t *qn, size_t z, size_t *zn, long long int ll,
unsigned long long int ull, int i, unsigned int u, double d,
- char *s, void *p, wchar_t *ls, wint_t lc, int *n)
+ char *s, void *p, wchar_t *ls, wint_t lc, int *n, long int l)
{
/* As an extension, GCC allows the BSD length "q" for integer formats.
This is largely obsoleted in C99 by %j, %ll and PRId64.
@@ -93,6 +93,13 @@ foo (quad_t q, u_quad_t uq, quad_t *qn, size_t z, size_t *zn, long long int ll,
printf ("%Lm", i); /* { dg-warning "length" "bad %Lm" } */
printf ("%qm", i); /* { dg-warning "length" "bad %qm" } */
printf ("%Zm", i); /* { dg-warning "length" "bad %Zm" } */
+ /* It should be OK to mix %m formats with $ operand number formats. */
+ printf ("%2$ld%m%1$d", i, l);
+ /* Likewise, %m formats with width and precision should not have an
+ operand number for the %m itself.
+ */
+ printf ("%*2$.*1$m", i, i);
+ printf ("%1$*2$.*1$m", i, i); /* { dg-warning "no argument" "printf %1\$m" } */
/* As an extension, glibc includes the "I" flag for decimal integer
formats, to output using the locale's digits (e.g. in Arabic).
In GCC, we require this to be in the standard place for flags, though
diff --git a/gcc/testsuite/gcc.dg/format-xopen-1.c b/gcc/testsuite/gcc.dg/format-xopen-1.c
index d5105eccf14..c57855a110a 100644
--- a/gcc/testsuite/gcc.dg/format-xopen-1.c
+++ b/gcc/testsuite/gcc.dg/format-xopen-1.c
@@ -103,13 +103,15 @@ foo (int i, unsigned int u, wint_t lc, wchar_t *ls, int *ip, double d,
*/
scanf ("%1$d", ip);
printf ("%1$d", i);
- printf ("%3$*2$.*1$d", i2, i, l);
+ printf ("%1$d", l); /* { dg-warning "arg 2" "mismatched args with $ format" } */
+ printf ("%3$*2$.*1$ld", 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" } */
+ 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 ("%*f%%%1$d%%%2$d", ip, ip);
printf ("%2$d", i); /* { dg-warning "operand" "$ number too large" } */