On Thu, Mar 01, 2018 at 06:05:30PM -0700, Martin Sebor wrote:
> > --- gcc/gimple-ssa-sprintf.c.jj     2018-02-27 23:16:19.747948912 +0100
> > +++ gcc/gimple-ssa-sprintf.c        2018-03-01 21:26:37.728861287 +0100
> > @@ -592,14 +592,12 @@ get_format_string (tree format, location
> >  /* The format_warning_at_substring function is not used here in a way
> >     that makes using attribute format viable.  Suppress the warning.  */
> > 
> > -#pragma GCC diagnostic push
> > -#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
> > -
> 
> The comment above the #pragmas should be removed too.

Done below.

> >  /* For convenience and brevity.  */
> > 
> >  static bool
> >    (* const fmtwarn) (const substring_loc &, location_t,
> >                  const char *, int, const char *, ...)
> > +  ATTRIBUTE_GCC_DIAG (5, 6)
> >    = format_warning_at_substring;
> 
> So add
> 
>   static bool
>     (* const fmtwarn_n) (const substring_loc &, location_t,
>                        const char *, int, unsigned HOST_WIDE_INT,
>                          const char *, const char*, ...)
>     ATTRIBUTE_GCC_DIAG (5, 6)

That would have to be ATTRIBUTE_GCC_DIAG (6, 8) ATTRIBUTE_GCC_DIAG (7, 8)

>     = format_warning_at_substring_n;
> 
> and use the pointer instead?

As I said, that doesn't really work; it works for -Wformat, but doesn't
work with exgettext.  Which is why for fmtwarn one has to use
  fmtwarn (......, G_("foobarbaz"), ...);
instead of
  fmtwarn (......, "foobarbaz", ...);
even when it is not conditional.

What we can do though is just duplicate the
format_warning_at_substring and format_warning_at_substring_n functions
(which are short and simple enough) as static under the shorter names.
This way we can also get rid of the G_( ... ) wrapping of non-conditional
fmtwarn arguments.

I've verified generated gcc.pot is the same between previous and this
patch, except for line numbers in the comments, and if I comment out
the (int) casts from dir.len in both one of fmtwarn and one of fmtwarn_n
calls, gcc properly warns.  Ok for trunk if it passes bootstrap/regtest?

2018-03-02  Jakub Jelinek  <ja...@redhat.com>

        * substring-locations.h (format_warning_va): Formatting fix for
        ATTRIBUTE_GCC_DIAG.
        (format_warning_at_substring): Fix up ATTRIBUTE_GCC_DIAG second
        argument.
        (format_warning_n_va, format_warning_at_substring_n): New prototypes.
        * substring-locations.c: Include intl.h.
        (format_warning_va): Turned into small wrapper around
        format_warning_n_va, renamed to ...
        (format_warning_n_va): ... this, add N and PLURAL_GMSGID arguments,
        rename GMSGID to SINGULAR_GMSGID, if SINGULAR_GMSGID != PLURAL_GMSGID,
        use ngettext.
        (format_warning_at_substring_n): New function.
        * gimple-ssa-sprintf.c: Remove GCC diagnostic ignored pragma.
        (fmtwarn): Add ATTRIBUTE_GCC_DIAG.  Turn into a copy of
        format_warning_at_substring with just a shorter name instead of
        const function pointer.
        (fmtwarn_n): New function.
        (maybe_warn, format_directive, parse_directive): Use fmtwarn_n where
        appropriate, get rid of all the fmtstr temporaries, move conditionals
        with G_() wrapped string literals directly into fmtwarn arguments,
        cast dir.len to (int), formatting fixes.

--- gcc/substring-locations.h.jj        2018-03-02 00:15:43.663782300 +0100
+++ gcc/substring-locations.h   2018-03-02 08:11:45.825500655 +0100
@@ -80,13 +80,29 @@ extern bool format_warning_va (const sub
                               location_t param_loc,
                               const char *corrected_substring,
                               int opt, const char *gmsgid, va_list *ap)
-  ATTRIBUTE_GCC_DIAG (5,0);
+  ATTRIBUTE_GCC_DIAG (5, 0);
+
+extern bool format_warning_n_va (const substring_loc &fmt_loc,
+                                location_t param_loc,
+                                const char *corrected_substring,
+                                int opt, unsigned HOST_WIDE_INT n,
+                                const char *singular_gmsgid,
+                                const char *plural_gmsgid, va_list *ap)
+  ATTRIBUTE_GCC_DIAG (6, 0) ATTRIBUTE_GCC_DIAG (7, 0);
 
 extern bool format_warning_at_substring (const substring_loc &fmt_loc,
                                         location_t param_loc,
                                         const char *corrected_substring,
                                         int opt, const char *gmsgid, ...)
-  ATTRIBUTE_GCC_DIAG (5,0);
+  ATTRIBUTE_GCC_DIAG (5, 6);
+
+extern bool format_warning_at_substring_n (const substring_loc &fmt_loc,
+                                          location_t param_loc,
+                                          const char *corrected_substring,
+                                          int opt, unsigned HOST_WIDE_INT n,
+                                          const char *singular_gmsgid,
+                                          const char *plural_gmsgid, ...)
+  ATTRIBUTE_GCC_DIAG (6, 8) ATTRIBUTE_GCC_DIAG (7, 8);
 
 /* Implementation detail, for use when implementing
    LANG_HOOKS_GET_SUBSTRING_LOCATION.  */
--- gcc/substring-locations.c.jj        2018-03-02 00:15:43.593782308 +0100
+++ gcc/substring-locations.c   2018-03-02 08:11:45.825500655 +0100
@@ -20,14 +20,17 @@ along with GCC; see the file COPYING3.
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "intl.h"
 #include "diagnostic.h"
 #include "cpplib.h"
 #include "tree.h"
 #include "langhooks.h"
 #include "substring-locations.h"
 
-/* Emit a warning governed by option OPT, using GMSGID as the format
-   string and AP as its arguments.
+/* Emit a warning governed by option OPT, using SINGULAR_GMSGID as the
+   format string (or if PLURAL_GMSGID is different from SINGULAR_GMSGID,
+   using SINGULAR_GMSGID, PLURAL_GMSGID and N as arguments to ngettext)
+   and AP as its arguments.
 
    Attempt to obtain precise location information within a string
    literal from FMT_LOC.
@@ -97,12 +100,13 @@ along with GCC; see the file COPYING3.
 
    Return true if a warning was emitted, false otherwise.  */
 
-ATTRIBUTE_GCC_DIAG (5,0)
 bool
-format_warning_va (const substring_loc &fmt_loc,
-                  location_t param_loc,
-                  const char *corrected_substring,
-                  int opt, const char *gmsgid, va_list *ap)
+format_warning_n_va (const substring_loc &fmt_loc,
+                    location_t param_loc,
+                    const char *corrected_substring,
+                    int opt, unsigned HOST_WIDE_INT n,
+                    const char *singular_gmsgid,
+                    const char *plural_gmsgid, va_list *ap)
 {
   bool substring_within_range = false;
   location_t primary_loc;
@@ -143,7 +147,25 @@ format_warning_va (const substring_loc &
     richloc.add_fixit_replace (fmt_substring_range, corrected_substring);
 
   diagnostic_info diagnostic;
-  diagnostic_set_info (&diagnostic, gmsgid, ap, &richloc, DK_WARNING);
+  if (singular_gmsgid != plural_gmsgid)
+    {
+      unsigned long gtn;
+
+      if (sizeof n <= sizeof gtn)
+       gtn = n;
+      else
+       /* Use the largest number ngettext can handle, otherwise
+          preserve the six least significant decimal digits for
+          languages where the plural form depends on them.  */
+       gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
+
+      const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
+      diagnostic_set_info_translated (&diagnostic, text, ap, &richloc,
+                                     DK_WARNING);
+    }
+  else
+    diagnostic_set_info (&diagnostic, singular_gmsgid, ap, &richloc,
+                        DK_WARNING);
   diagnostic.option_index = opt;
   bool warned = diagnostic_report_diagnostic (global_dc, &diagnostic);
 
@@ -162,6 +184,18 @@ format_warning_va (const substring_loc &
   return warned;
 }
 
+/* Singular-only version of the above.  */
+
+bool
+format_warning_va (const substring_loc &fmt_loc,
+                  location_t param_loc,
+                  const char *corrected_substring,
+                  int opt, const char *gmsgid, va_list *ap)
+{
+  return format_warning_n_va (fmt_loc, param_loc, corrected_substring, opt,
+                             0, gmsgid, gmsgid, ap);
+}
+
 /* Variadic call to format_warning_va.  */
 
 bool
@@ -177,6 +211,26 @@ format_warning_at_substring (const subst
   va_end (ap);
 
   return warned;
+}
+
+/* Variadic call to format_warning_n_va.  */
+
+bool
+format_warning_at_substring_n (const substring_loc &fmt_loc,
+                              location_t param_loc,
+                              const char *corrected_substring,
+                              int opt, unsigned HOST_WIDE_INT n,
+                              const char *singular_gmsgid,
+                              const char *plural_gmsgid, ...)
+{
+  va_list ap;
+  va_start (ap, plural_gmsgid);
+  bool warned = format_warning_n_va (fmt_loc, param_loc, corrected_substring,
+                                    opt, n, singular_gmsgid, plural_gmsgid,
+                                    &ap);
+  va_end (ap);
+
+  return warned;
 }
 
 /* Attempt to determine the source location of the substring.
--- gcc/gimple-ssa-sprintf.c.jj 2018-03-02 00:15:44.016782257 +0100
+++ gcc/gimple-ssa-sprintf.c    2018-03-02 08:29:17.212201866 +0100
@@ -589,18 +589,40 @@ get_format_string (tree format, location
   return fmtstr;
 }
 
-/* The format_warning_at_substring function is not used here in a way
-   that makes using attribute format viable.  Suppress the warning.  */
+/* For convenience and brevity, shorter named entrypoints of
+   format_warning_at_substring and format_warning_at_substring_n.
+   These have to be functions with the attribute so that exgettext
+   works properly.  */
 
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
+static bool
+ATTRIBUTE_GCC_DIAG (5, 6)
+fmtwarn (const substring_loc &fmt_loc, location_t param_loc,
+        const char *corrected_substring, int opt, const char *gmsgid, ...)
+{
+  va_list ap;
+  va_start (ap, gmsgid);
+  bool warned = format_warning_va (fmt_loc, param_loc, corrected_substring,
+                                  opt, gmsgid, &ap);
+  va_end (ap);
 
-/* For convenience and brevity.  */
+  return warned;
+}
 
 static bool
-  (* const fmtwarn) (const substring_loc &, location_t,
-                    const char *, int, const char *, ...)
-  = format_warning_at_substring;
+ATTRIBUTE_GCC_DIAG (6, 8) ATTRIBUTE_GCC_DIAG (7, 8)
+fmtwarn_n (const substring_loc &fmt_loc, location_t param_loc,
+          const char *corrected_substring, int opt, unsigned HOST_WIDE_INT n,
+          const char *singular_gmsgid, const char *plural_gmsgid, ...)
+{
+  va_list ap;
+  va_start (ap, plural_gmsgid);
+  bool warned = format_warning_n_va (fmt_loc, param_loc, corrected_substring,
+                                    opt, n, singular_gmsgid, plural_gmsgid,
+                                    &ap);
+  va_end (ap);
+
+  return warned;
+}
 
 /* Format length modifiers.  */
 
@@ -2489,113 +2511,105 @@ maybe_warn (substring_loc &dirloc, locat
          /* This is the terminating nul.  */
          gcc_assert (res.min == 1 && res.min == res.max);
 
-         const char *fmtstr
-           = (info.bounded
-              ? (maybe
-                 ? G_("%qE output may be truncated before the last format "
-                      "character")
-                 : G_("%qE output truncated before the last format character"))
-              : (maybe
-                 ? G_("%qE may write a terminating nul past the end "
-                      "of the destination")
-                 : G_("%qE writing a terminating nul past the end "
-                      "of the destination")));
-
          return fmtwarn (dirloc, UNKNOWN_LOCATION, NULL, info.warnopt (),
-                         fmtstr, info.func);
+                         info.bounded
+                         ? (maybe
+                            ? G_("%qE output may be truncated before the "
+                                 "last format character")
+                            : G_("%qE output truncated before the last "
+                                 "format character"))
+                         : (maybe
+                            ? G_("%qE may write a terminating nul past the "
+                                 "end of the destination")
+                            : G_("%qE writing a terminating nul past the "
+                                 "end of the destination")),
+                         info.func);
        }
 
       if (res.min == res.max)
        {
-         const char* fmtstr
-           = (res.min == 1
-              ? (info.bounded
-                 ? (maybe
-                    ? G_("%<%.*s%> directive output may be truncated writing "
-                         "%wu byte into a region of size %wu")
-                    : G_("%<%.*s%> directive output truncated writing "
-                         "%wu byte into a region of size %wu"))
-                 : G_("%<%.*s%> directive writing %wu byte "
-                      "into a region of size %wu"))
-              : (info.bounded
-                 ? (maybe
-                    ? G_("%<%.*s%> directive output may be truncated writing "
-                         "%wu bytes into a region of size %wu")
-                    : G_("%<%.*s%> directive output truncated writing "
-                         "%wu bytes into a region of size %wu"))
-                 : G_("%<%.*s%> directive writing %wu bytes "
-                      "into a region of size %wu")));
-         return fmtwarn (dirloc, argloc, NULL,
-                         info.warnopt (), fmtstr, dir.len,
-                         target_to_host (hostdir, sizeof hostdir, dir.beg),
-                         res.min, navail);
+         const char *d = target_to_host (hostdir, sizeof hostdir, dir.beg);
+         if (!info.bounded)
+           return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min,
+                             "%<%.*s%> directive writing %wu byte into a "
+                             "region of size %wu",
+                             "%<%.*s%> directive writing %wu bytes into a "
+                             "region of size %wu",
+                             (int) dir.len, d, res.min, navail);
+         else if (maybe)
+           return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min,
+                             "%<%.*s%> directive output may be truncated "
+                             "writing %wu byte into a region of size %wu",
+                             "%<%.*s%> directive output may be truncated "
+                             "writing %wu bytes into a region of size %wu",
+                             (int) dir.len, d, res.min, navail);
+         else
+           return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min,
+                             "%<%.*s%> directive output truncated writing "
+                             "%wu byte into a region of size %wu",
+                             "%<%.*s%> directive output truncated writing "
+                             "%wu bytes into a region of size %wu",
+                             (int) dir.len, d, res.min, navail);
        }
-
       if (res.min == 0 && res.max < maxbytes)
-       {
-         const char* fmtstr
-           = (info.bounded
-              ? (maybe
-                 ? G_("%<%.*s%> directive output may be truncated writing "
-                      "up to %wu bytes into a region of size %wu")
-                 : G_("%<%.*s%> directive output truncated writing "
-                      "up to %wu bytes into a region of size %wu"))
-              : G_("%<%.*s%> directive writing up to %wu bytes "
-                   "into a region of size %wu"));
-         return fmtwarn (dirloc, argloc, NULL,
-                         info.warnopt (), fmtstr, dir.len,
-                         target_to_host (hostdir, sizeof hostdir, dir.beg),
-                         res.max, navail);
-       }
+       return fmtwarn (dirloc, argloc, NULL,
+                       info.warnopt (),
+                       info.bounded
+                       ? (maybe
+                          ? G_("%<%.*s%> directive output may be truncated "
+                               "writing up to %wu bytes into a region of "
+                               "size %wu")
+                          : G_("%<%.*s%> directive output truncated writing "
+                               "up to %wu bytes into a region of size %wu"))
+                       : G_("%<%.*s%> directive writing up to %wu bytes "
+                            "into a region of size %wu"), (int) dir.len,
+                       target_to_host (hostdir, sizeof hostdir, dir.beg),
+                       res.max, navail);
 
       if (res.min == 0 && maxbytes <= res.max)
-       {
-         /* This is a special case to avoid issuing the potentially
-            confusing warning:
-              writing 0 or more bytes into a region of size 0.  */
-         const char* fmtstr
-           = (info.bounded
-              ? (maybe
-                 ? G_("%<%.*s%> directive output may be truncated writing "
-                      "likely %wu or more bytes into a region of size %wu")
-                 : G_("%<%.*s%> directive output truncated writing "
-                      "likely %wu or more bytes into a region of size %wu"))
-              : G_("%<%.*s%> directive writing likely %wu or more bytes "
-                   "into a region of size %wu"));
-         return fmtwarn (dirloc, argloc, NULL,
-                         info.warnopt (), fmtstr, dir.len,
-                         target_to_host (hostdir, sizeof hostdir, dir.beg),
-                         res.likely, navail);
-       }
+       /* This is a special case to avoid issuing the potentially
+          confusing warning:
+            writing 0 or more bytes into a region of size 0.  */
+       return fmtwarn (dirloc, argloc, NULL, info.warnopt (),
+                       info.bounded
+                       ? (maybe
+                          ? G_("%<%.*s%> directive output may be truncated "
+                               "writing likely %wu or more bytes into a "
+                               "region of size %wu")
+                          : G_("%<%.*s%> directive output truncated writing "
+                               "likely %wu or more bytes into a region of "
+                               "size %wu"))
+                       : G_("%<%.*s%> directive writing likely %wu or more "
+                            "bytes into a region of size %wu"), (int) dir.len,
+                       target_to_host (hostdir, sizeof hostdir, dir.beg),
+                       res.likely, navail);
 
       if (res.max < maxbytes)
-       {
-         const char* fmtstr
-           = (info.bounded
-              ? (maybe
-                 ? G_("%<%.*s%> directive output may be truncated writing "
-                      "between %wu and %wu bytes into a region of size %wu")
-                 : G_("%<%.*s%> directive output truncated writing "
-                      "between %wu and %wu bytes into a region of size %wu"))
-              : G_("%<%.*s%> directive writing between %wu and "
-                   "%wu bytes into a region of size %wu"));
-         return fmtwarn (dirloc, argloc, NULL,
-                         info.warnopt (), fmtstr, dir.len,
-                         target_to_host (hostdir, sizeof hostdir, dir.beg),
-                         res.min, res.max, navail);
-       }
-
-      const char* fmtstr
-       = (info.bounded
-          ? (maybe
-             ? G_("%<%.*s%> directive output may be truncated writing "
-                  "%wu or more bytes into a region of size %wu")
-             : G_("%<%.*s%> directive output truncated writing "
-                  "%wu or more bytes into a region of size %wu"))
-          : G_("%<%.*s%> directive writing %wu or more bytes "
-               "into a region of size %wu"));
-      return fmtwarn (dirloc, argloc, NULL,
-                     info.warnopt (), fmtstr, dir.len,
+       return fmtwarn (dirloc, argloc, NULL, info.warnopt (),
+                       info.bounded
+                       ? (maybe
+                          ? G_("%<%.*s%> directive output may be truncated "
+                               "writing between %wu and %wu bytes into a "
+                               "region of size %wu")
+                          : G_("%<%.*s%> directive output truncated "
+                               "writing between %wu and %wu bytes into a "
+                               "region of size %wu"))
+                       : G_("%<%.*s%> directive writing between %wu and "
+                            "%wu bytes into a region of size %wu"),
+                       (int) dir.len,
+                       target_to_host (hostdir, sizeof hostdir, dir.beg),
+                       res.min, res.max, navail);
+
+      return fmtwarn (dirloc, argloc, NULL, info.warnopt (),
+                     info.bounded
+                     ? (maybe
+                        ? G_("%<%.*s%> directive output may be truncated "
+                             "writing %wu or more bytes into a region of "
+                             "size %wu")
+                        : G_("%<%.*s%> directive output truncated writing "
+                             "%wu or more bytes into a region of size %wu"))
+                     : G_("%<%.*s%> directive writing %wu or more bytes "
+                          "into a region of size %wu"), (int) dir.len,
                      target_to_host (hostdir, sizeof hostdir, dir.beg),
                      res.min, navail);
     }
@@ -2617,122 +2631,111 @@ maybe_warn (substring_loc &dirloc, locat
     {
       gcc_assert (res.min == 1 && res.min == res.max);
 
-      const char *fmtstr
-       = (info.bounded
-          ? (maybe
-             ? G_("%qE output may be truncated before the last format "
-                  "character")
-             : G_("%qE output truncated before the last format character"))
-          : (maybe
-             ? G_("%qE may write a terminating nul past the end "
-                  "of the destination")
-             : G_("%qE writing a terminating nul past the end "
-                  "of the destination")));
-
-      return fmtwarn (dirloc, UNKNOWN_LOCATION, NULL, info.warnopt (), fmtstr,
-                     info.func);
+      return fmtwarn (dirloc, UNKNOWN_LOCATION, NULL, info.warnopt (),
+                     info.bounded
+                     ? (maybe
+                        ? G_("%qE output may be truncated before the last "
+                             "format character")
+                        : G_("%qE output truncated before the last format "
+                             "character"))
+                     : (maybe
+                        ? G_("%qE may write a terminating nul past the end "
+                             "of the destination")
+                        : G_("%qE writing a terminating nul past the end "
+                             "of the destination")), info.func);
     }
 
   if (res.min == res.max)
     {
-      const char* fmtstr
-       = (res.min == 1
-          ? (info.bounded
-             ? (maybe
-                ? G_("%<%.*s%> directive output may be truncated writing "
-                     "%wu byte into a region of size between %wu and %wu")
-                : G_("%<%.*s%> directive output truncated writing "
-                     "%wu byte into a region of size between %wu and %wu"))
-             : G_("%<%.*s%> directive writing %wu byte "
-                  "into a region of size between %wu and %wu"))
-          : (info.bounded
-             ? (maybe
-                ? G_("%<%.*s%> directive output may be truncated writing "
-                     "%wu bytes into a region of size between %wu and %wu")
-                : G_("%<%.*s%> directive output truncated writing "
-                     "%wu bytes into a region of size between %wu and %wu"))
-             : G_("%<%.*s%> directive writing %wu bytes "
-                  "into a region of size between %wu and %wu")));
-
-      return fmtwarn (dirloc, argloc, NULL,
-                     info.warnopt (), fmtstr, dir.len,
-                     target_to_host (hostdir, sizeof hostdir, dir.beg),
-                     res.min, avail_range.min, avail_range.max);
+      const char *d = target_to_host (hostdir, sizeof hostdir, dir.beg);
+      if (!info.bounded)
+       return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min,
+                         "%<%.*s%> directive writing %wu byte into a region "
+                         "of size between %wu and %wu",
+                         "%<%.*s%> directive writing %wu bytes into a region "
+                         "of size between %wu and %wu", (int) dir.len, d,
+                         res.min, avail_range.min, avail_range.max);
+      else if (maybe)
+       return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min,
+                         "%<%.*s%> directive output may be truncated writing "
+                         "%wu byte into a region of size between %wu and %wu",
+                         "%<%.*s%> directive output may be truncated writing "
+                         "%wu bytes into a region of size between %wu and "
+                         "%wu", (int) dir.len, d, res.min, avail_range.min,
+                         avail_range.max);
+      else
+       return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min,
+                         "%<%.*s%> directive output truncated writing %wu "
+                         "byte into a region of size between %wu and %wu",
+                         "%<%.*s%> directive output truncated writing %wu "
+                         "bytes into a region of size between %wu and %wu",
+                         (int) dir.len, d, res.min, avail_range.min,
+                         avail_range.max);
     }
 
   if (res.min == 0 && res.max < maxbytes)
-    {
-      const char* fmtstr
-       = (info.bounded
-          ? (maybe
-             ? G_("%<%.*s%> directive output may be truncated writing "
-                  "up to %wu bytes into a region of size between "
-                  "%wu and %wu")
-             : G_("%<%.*s%> directive output truncated writing "
-                  "up to %wu bytes into a region of size between "
-                  "%wu and %wu"))
-          : G_("%<%.*s%> directive writing up to %wu bytes "
-               "into a region of size between %wu and %wu"));
-      return fmtwarn (dirloc, argloc, NULL,
-                     info.warnopt (), fmtstr, dir.len,
-                     target_to_host (hostdir, sizeof hostdir, dir.beg),
-                     res.max, avail_range.min, avail_range.max);
-    }
+    return fmtwarn (dirloc, argloc, NULL, info.warnopt (),
+                   info.bounded
+                   ? (maybe
+                      ? G_("%<%.*s%> directive output may be truncated "
+                           "writing up to %wu bytes into a region of size "
+                           "between %wu and %wu")
+                      : G_("%<%.*s%> directive output truncated writing "
+                           "up to %wu bytes into a region of size between "
+                           "%wu and %wu"))
+                   : G_("%<%.*s%> directive writing up to %wu bytes "
+                        "into a region of size between %wu and %wu"),
+                   (int) dir.len,
+                   target_to_host (hostdir, sizeof hostdir, dir.beg),
+                   res.max, avail_range.min, avail_range.max);
 
   if (res.min == 0 && maxbytes <= res.max)
-    {
-      /* This is a special case to avoid issuing the potentially confusing
-        warning:
-          writing 0 or more bytes into a region of size between 0 and N.  */
-      const char* fmtstr
-       = (info.bounded
-          ? (maybe
-             ? G_("%<%.*s%> directive output may be truncated writing "
-                  "likely %wu or more bytes into a region of size between "
-                  "%wu and %wu")
-             : G_("%<%.*s%> directive output truncated writing likely "
-                  "%wu or more bytes into a region of size between "
-                  "%wu and %wu"))
-          : G_("%<%.*s%> directive writing likely %wu or more bytes "
-               "into a region of size between %wu and %wu"));
-      return fmtwarn (dirloc, argloc, NULL,
-                     info.warnopt (), fmtstr, dir.len,
-                     target_to_host (hostdir, sizeof hostdir, dir.beg),
-                     res.likely, avail_range.min, avail_range.max);
-    }
+    /* This is a special case to avoid issuing the potentially confusing
+       warning:
+        writing 0 or more bytes into a region of size between 0 and N.  */
+    return fmtwarn (dirloc, argloc, NULL, info.warnopt (),
+                   info.bounded
+                   ? (maybe
+                      ? G_("%<%.*s%> directive output may be truncated "
+                           "writing likely %wu or more bytes into a region "
+                           "of size between %wu and %wu")
+                      : G_("%<%.*s%> directive output truncated writing "
+                           "likely %wu or more bytes into a region of size "
+                           "between %wu and %wu"))
+                   : G_("%<%.*s%> directive writing likely %wu or more bytes "
+                        "into a region of size between %wu and %wu"),
+                   (int) dir.len,
+                   target_to_host (hostdir, sizeof hostdir, dir.beg),
+                   res.likely, avail_range.min, avail_range.max);
 
   if (res.max < maxbytes)
-    {
-      const char* fmtstr
-       = (info.bounded
-          ? (maybe
-             ? G_("%<%.*s%> directive output may be truncated writing "
-                  "between %wu and %wu bytes into a region of size "
-                  "between %wu and %wu")
-             : G_("%<%.*s%> directive output truncated writing "
-                  "between %wu and %wu bytes into a region of size "
-                  "between %wu and %wu"))
-          : G_("%<%.*s%> directive writing between %wu and "
-               "%wu bytes into a region of size between %wu and %wu"));
-      return fmtwarn (dirloc, argloc, NULL,
-                     info.warnopt (), fmtstr, dir.len,
-                     target_to_host (hostdir, sizeof hostdir, dir.beg),
-                     res.min, res.max, avail_range.min, avail_range.max);
-    }
+    return fmtwarn (dirloc, argloc, NULL, info.warnopt (),
+                   info.bounded
+                   ? (maybe
+                      ? G_("%<%.*s%> directive output may be truncated "
+                           "writing between %wu and %wu bytes into a region "
+                           "of size between %wu and %wu")
+                      : G_("%<%.*s%> directive output truncated writing "
+                           "between %wu and %wu bytes into a region of size "
+                           "between %wu and %wu"))
+                   : G_("%<%.*s%> directive writing between %wu and "
+                        "%wu bytes into a region of size between %wu and "
+                        "%wu"), (int) dir.len,
+                   target_to_host (hostdir, sizeof hostdir, dir.beg),
+                   res.min, res.max, avail_range.min, avail_range.max);
 
-  const char* fmtstr
-    = (info.bounded
-       ? (maybe
-         ? G_("%<%.*s%> directive output may be truncated writing "
-              "%wu or more bytes into a region of size between "
-              "%wu and %wu")
-         : G_("%<%.*s%> directive output truncated writing "
-              "%wu or more bytes into a region of size between "
-              "%wu and %wu"))
-       : G_("%<%.*s%> directive writing %wu or more bytes "
-           "into a region of size between %wu and %wu"));
-  return fmtwarn (dirloc, argloc, NULL,
-                 info.warnopt (), fmtstr, dir.len,
+  return fmtwarn (dirloc, argloc, NULL, info.warnopt (),
+                 info.bounded
+                 ? (maybe
+                    ? G_("%<%.*s%> directive output may be truncated writing "
+                         "%wu or more bytes into a region of size between "
+                         "%wu and %wu")
+                    : G_("%<%.*s%> directive output truncated writing "
+                         "%wu or more bytes into a region of size between "
+                         "%wu and %wu"))
+                 : G_("%<%.*s%> directive writing %wu or more bytes "
+                      "into a region of size between %wu and %wu"),
+                 (int) dir.len,
                  target_to_host (hostdir, sizeof hostdir, dir.beg),
                  res.min, avail_range.min, avail_range.max);
 }
@@ -2883,27 +2886,22 @@ format_directive (const sprintf_dom_walk
         (like Glibc does under some conditions).  */
 
       if (fmtres.range.min == fmtres.range.max)
-       warned = fmtwarn (dirloc, argloc, NULL,
-                         info.warnopt (),
+       warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (),
                          "%<%.*s%> directive output of %wu bytes exceeds "
-                         "minimum required size of 4095",
-                         dirlen,
+                         "minimum required size of 4095", dirlen,
                          target_to_host (hostdir, sizeof hostdir, dir.beg),
                          fmtres.range.min);
       else
-       {
-         const char *fmtstr
-           = (minunder4k
-              ? G_("%<%.*s%> directive output between %wu and %wu "
-                   "bytes may exceed minimum required size of 4095")
-              : G_("%<%.*s%> directive output between %wu and %wu "
-                   "bytes exceeds minimum required size of 4095"));
-
-         warned = fmtwarn (dirloc, argloc, NULL,
-                           info.warnopt (), fmtstr, dirlen,
-                           target_to_host (hostdir, sizeof hostdir, dir.beg),
-                           fmtres.range.min, fmtres.range.max);
-       }
+       warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (),
+                         minunder4k
+                         ? G_("%<%.*s%> directive output between %wu and %wu "
+                              "bytes may exceed minimum required size of "
+                              "4095")
+                         : G_("%<%.*s%> directive output between %wu and %wu "
+                              "bytes exceeds minimum required size of 4095"),
+                         dirlen,
+                         target_to_host (hostdir, sizeof hostdir, dir.beg),
+                         fmtres.range.min, fmtres.range.max);
     }
 
   /* Has the likely and maximum directive output exceeded INT_MAX?  */
@@ -2929,29 +2927,24 @@ format_directive (const sprintf_dom_walk
       if (fmtres.range.min == fmtres.range.max)
        warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (),
                          "%<%.*s%> directive output of %wu bytes causes "
-                         "result to exceed %<INT_MAX%>",
-                         dirlen,
+                         "result to exceed %<INT_MAX%>", dirlen,
                          target_to_host (hostdir, sizeof hostdir, dir.beg),
                          fmtres.range.min);
       else
-       {
-         const char *fmtstr
-           = (fmtres.range.min > target_int_max ()
-              ? G_ ("%<%.*s%> directive output between %wu and %wu "
-                    "bytes causes result to exceed %<INT_MAX%>")
-              : G_ ("%<%.*s%> directive output between %wu and %wu "
-                    "bytes may cause result to exceed %<INT_MAX%>"));
-         warned = fmtwarn (dirloc, argloc, NULL,
-                           info.warnopt (), fmtstr, dirlen,
-                           target_to_host (hostdir, sizeof hostdir, dir.beg),
-                           fmtres.range.min, fmtres.range.max);
-       }
+       warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (),
+                         fmtres.range.min > target_int_max ()
+                         ? G_ ("%<%.*s%> directive output between %wu and "
+                               "%wu bytes causes result to exceed "
+                               "%<INT_MAX%>")
+                         : G_ ("%<%.*s%> directive output between %wu and "
+                               "%wu bytes may cause result to exceed "
+                               "%<INT_MAX%>"), dirlen,
+                         target_to_host (hostdir, sizeof hostdir, dir.beg),
+                         fmtres.range.min, fmtres.range.max);
     }
 
   if (warned && fmtres.range.min < fmtres.range.likely
       && fmtres.range.likely < fmtres.range.max)
-    /* Some languages have special plural rules even for large values,
-       but it is periodic with period of 10, 100, 1000 etc.  */
     inform_n (info.fmtloc, fmtres.range.likely,
              "assuming directive output of %wu byte",
              "assuming directive output of %wu bytes",
@@ -3022,8 +3015,6 @@ format_directive (const sprintf_dom_walk
   return true;
 }
 
-#pragma GCC diagnostic pop
-
 /* Parse a format directive in function call described by INFO starting
    at STR and populate DIR structure.  Bump up *ARGNO by the number of
    arguments extracted for the directive.  Return the length of
@@ -3373,9 +3364,9 @@ parse_directive (sprintf_dom_walker::cal
          substring_loc dirloc (info.fmtloc, TREE_TYPE (info.format),
                                caret, begin, end);
 
-         fmtwarn (dirloc, UNKNOWN_LOCATION, NULL,
-                  info.warnopt (), "%<%.*s%> directive width out of range",
-                  dir.len, target_to_host (hostdir, sizeof hostdir, dir.beg));
+         fmtwarn (dirloc, UNKNOWN_LOCATION, NULL, info.warnopt (),
+                  "%<%.*s%> directive width out of range", (int) dir.len,
+                  target_to_host (hostdir, sizeof hostdir, dir.beg));
        }
 
       dir.set_width (width);
@@ -3407,9 +3398,9 @@ parse_directive (sprintf_dom_walker::cal
          substring_loc dirloc (info.fmtloc, TREE_TYPE (info.format),
                                caret, begin, end);
 
-         fmtwarn (dirloc, UNKNOWN_LOCATION, NULL,
-                  info.warnopt (), "%<%.*s%> directive precision out of range",
-                  dir.len, target_to_host (hostdir, sizeof hostdir, dir.beg));
+         fmtwarn (dirloc, UNKNOWN_LOCATION, NULL, info.warnopt (),
+                  "%<%.*s%> directive precision out of range", (int) dir.len,
+                  target_to_host (hostdir, sizeof hostdir, dir.beg));
        }
 
       dir.set_precision (precision);


        Jakub

Reply via email to