c-common.c (FMT_FLAG_DOLLAR_MULTIPLE): Define.
authorJoseph Myers <jsm28@cam.ac.uk>
Tue, 17 Oct 2000 18:16:15 +0000 (19:16 +0100)
committerJoseph Myers <jsm28@gcc.gnu.org>
Tue, 17 Oct 2000 18:16:15 +0000 (19:16 +0100)
* 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

gcc/ChangeLog
gcc/c-common.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/format-xopen-1.c

index f523e43eaa7637fd4090dfae88e2543ada824b33..ddd043fb3a74b86e4eef9930b4b4a3c233156b46 100644 (file)
@@ -1,3 +1,12 @@
+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>
 
        * inclhack.def (hpux_maxint): Also apply fix to values.h.
index f1989e5f396c44bc18851b641d84a35ebdc3ce9b..2fb63fde5a04d76ca5010afa5b27e986273f1776 100644 (file)
@@ -1272,7 +1272,10 @@ enum
   FMT_FLAG_SCANF_A_KLUDGE = 2,
   /* A % during parsing a specifier is allowed to be a modified % rather
      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
      (controlled by width_char and precision_char); details of whether
      '*' can be used for these (width_type and precision_type); details
@@ -1692,7 +1695,7 @@ static const format_kind_info format_types[] =
 {
   { "printf",   printf_length_specs, print_char_table, " +#0-'I", NULL, 
     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
   },
   { "scanf",    scanf_length_specs,  scan_char_table,  "*'I", NULL, 
@@ -1769,7 +1772,8 @@ static void status_warning PARAMS ((int *, const char *, ...))
 
 static void init_dollar_format_checking                PARAMS ((int, tree));
 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 const format_flag_spec *get_flag_spec   PARAMS ((const format_flag_spec *,
@@ -2059,12 +2063,14 @@ init_dollar_format_checking (first_arg_num, params)
    a $ format is found, *FORMAT is updated to point just after it.  */
 
 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;
      const char **format;
      int dollar_needed;
      tree params;
      tree *param_ptr;
+     const format_kind_info *fki;
 {
   int argnum;
   int overflow_flag;
@@ -2125,7 +2131,16 @@ maybe_read_dollar_number (status, format, dollar_needed, params, param_ptr)
              nalloc - dollar_arguments_alloc);
       dollar_arguments_alloc = nalloc;
     }
-  dollar_arguments_used[argnum - 1] = 1;
+  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;
   if (dollar_first_arg_num)
     {
       int i;
@@ -2531,7 +2546,7 @@ check_format_info_main (status, res, info, format_chars, format_length,
          int opnum;
          opnum = maybe_read_dollar_number (status, &format_chars, 0,
                                            first_fillin_param,
-                                           &main_arg_params);
+                                           &main_arg_params, fki);
          if (opnum == -1)
            return;
          else if (opnum > 0)
@@ -2583,7 +2598,7 @@ check_format_info_main (status, res, info, format_chars, format_length,
                  opnum = maybe_read_dollar_number (status, &format_chars,
                                                    has_operand_number == 1,
                                                    first_fillin_param,
-                                                   &params);
+                                                   &params, fki);
                  if (opnum == -1)
                    return;
                  else if (opnum > 0)
@@ -2662,7 +2677,7 @@ check_format_info_main (status, res, info, format_chars, format_length,
                  opnum = maybe_read_dollar_number (status, &format_chars,
                                                    has_operand_number == 1,
                                                    first_fillin_param,
-                                                   &params);
+                                                   &params, fki);
                  if (opnum == -1)
                    return;
                  else if (opnum > 0)
index 65aadee0f2564bce21843b70f551d954b23ec5bd..0859351eb8baf22d88b943d4f3b662ca622e3233 100644 (file)
@@ -1,3 +1,9 @@
+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>
 
        * gcc.dg/sequence-pt-1.c: Several new tests; remove xfail from some old tests.
index 0eb8d70eaa740542b3a380499d2607c2d5a061ba..99d571bb0061504046485d215df89406a710a31f 100644 (file)
@@ -1,6 +1,6 @@
 /* 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.
+   Aardvark problem reports approved as changes.
 */
 /* Origin: Joseph Myers <jsm28@cam.ac.uk> */
 /* { dg-do compile } */
@@ -81,9 +81,6 @@ foo (int i, unsigned int u, wint_t lc, wchar_t *ls, int *ip, double d,
   */
   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" } */
@@ -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 ("%'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.
+  /* Banning gaps in the arguments used with scanf was covered in Aardvark
+     report XSHd4 ERN 164, which was rejected, but implementation without
+     such a ban still isn't possible within ISO C.
   */
   scanf ("%1$d", ip);
   printf ("%1$d", i);
@@ -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 ("%2$d%1$d", i, i, i); /* { dg-warning "unused" "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" } */
 }