+2018-02-27 Martin Sebor <msebor@redhat.com>
+
+ PR translation/84207
+ * diagnostic-core.h (warning_n, error_n, inform_n): Change
+ n argument to unsigned HOST_WIDE_INT.
+ * diagnostic.c (warning_n, error_n, inform_n): Ditto.
+ (diagnostic_n_impl): Ditto. Handle arguments in excess of LONG_MAX.
+ * gimple-ssa-sprintf.c (format_directive): Simplify inform_n call.
+ * tree-ssa-strlen.c (maybe_diag_stxncpy_trunc): Use warning_n.
+
2018-02-27 Richard Biener <rguenther@suse.de>
PR tree-optimization/84512
ATTRIBUTE_GCC_DIAG(1,2) ATTRIBUTE_NORETURN;
/* Pass one of the OPT_W* from options.h as the first parameter. */
extern bool warning (int, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
-extern bool warning_n (location_t, int, int, const char *, const char *, ...)
+extern bool warning_n (location_t, int, unsigned HOST_WIDE_INT,
+ const char *, const char *, ...)
ATTRIBUTE_GCC_DIAG(4,6) ATTRIBUTE_GCC_DIAG(5,6);
-extern bool warning_n (rich_location *, int, int, const char *,
- const char *, ...)
+extern bool warning_n (rich_location *, int, unsigned HOST_WIDE_INT,
+ const char *, const char *, ...)
ATTRIBUTE_GCC_DIAG(4, 6) ATTRIBUTE_GCC_DIAG(5, 6);
extern bool warning_at (location_t, int, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,4);
extern bool warning_at (rich_location *, int, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,4);
extern void error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
-extern void error_n (location_t, int, const char *, const char *, ...)
+extern void error_n (location_t, unsigned HOST_WIDE_INT, const char *,
+ const char *, ...)
ATTRIBUTE_GCC_DIAG(3,5) ATTRIBUTE_GCC_DIAG(4,5);
extern void error_at (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
extern void error_at (rich_location *, const char *, ...)
extern void sorry (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
extern void inform (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
extern void inform (rich_location *, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
-extern void inform_n (location_t, int, const char *, const char *, ...)
+extern void inform_n (location_t, unsigned HOST_WIDE_INT, const char *,
+ const char *, ...)
ATTRIBUTE_GCC_DIAG(3,5) ATTRIBUTE_GCC_DIAG(4,5);
extern void verbatim (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
extern bool emit_diagnostic (diagnostic_t, location_t, int,
/* Prototypes. */
static bool diagnostic_impl (rich_location *, int, const char *,
va_list *, diagnostic_t) ATTRIBUTE_GCC_DIAG(3,0);
-static bool diagnostic_n_impl (rich_location *, int, int, const char *,
- const char *, va_list *,
+static bool diagnostic_n_impl (rich_location *, int, unsigned HOST_WIDE_INT,
+ const char *, const char *, va_list *,
diagnostic_t) ATTRIBUTE_GCC_DIAG(5,0);
static void error_recursion (diagnostic_context *) ATTRIBUTE_NORETURN;
/* Implement inform_n, warning_n, and error_n, as documented and
defined below. */
static bool
-diagnostic_n_impl (rich_location *richloc, int opt, int n,
+diagnostic_n_impl (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
const char *singular_gmsgid,
const char *plural_gmsgid,
va_list *ap, diagnostic_t kind)
{
diagnostic_info diagnostic;
- diagnostic_set_info_translated (&diagnostic,
- ngettext (singular_gmsgid, plural_gmsgid, n),
- ap, richloc, kind);
+ 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, kind);
if (kind == DK_WARNING)
diagnostic.option_index = opt;
return diagnostic_report_diagnostic (global_dc, &diagnostic);
/* An informative note at LOCATION. Use this for additional details on an
error message. */
void
-inform_n (location_t location, int n, const char *singular_gmsgid,
- const char *plural_gmsgid, ...)
+inform_n (location_t location, unsigned HOST_WIDE_INT n,
+ const char *singular_gmsgid, const char *plural_gmsgid, ...)
{
va_list ap;
va_start (ap, plural_gmsgid);
/* Same as warning_n plural variant below, but using RICHLOC. */
bool
-warning_n (rich_location *richloc, int opt, int n,
+warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
const char *singular_gmsgid, const char *plural_gmsgid, ...)
{
gcc_assert (richloc);
Returns true if the warning was printed, false if it was inhibited. */
bool
-warning_n (location_t location, int opt, int n, const char *singular_gmsgid,
- const char *plural_gmsgid, ...)
+warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
+ const char *singular_gmsgid, const char *plural_gmsgid, ...)
{
va_list ap;
va_start (ap, plural_gmsgid);
/* A hard error: the code is definitely ill-formed, and an object file
will not be produced. */
void
-error_n (location_t location, int n, const char *singular_gmsgid,
- const char *plural_gmsgid, ...)
+error_n (location_t location, unsigned HOST_WIDE_INT n,
+ const char *singular_gmsgid, const char *plural_gmsgid, ...)
{
va_list ap;
va_start (ap, plural_gmsgid);
&& 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 > INT_MAX
- ? (fmtres.range.likely % 1000000) + 1000000
- : fmtres.range.likely,
+ inform_n (info.fmtloc, fmtres.range.likely,
"assuming directive output of %wu byte",
"assuming directive output of %wu bytes",
fmtres.range.likely);
gcall *call = as_a <gcall *> (stmt);
if (lenrange[0] == cntrange[1] && cntrange[0] == cntrange[1])
- return warning_at (callloc, OPT_Wstringop_truncation,
- (integer_onep (cnt)
- ? G_("%G%qD output truncated before terminating "
- "nul copying %E byte from a string of the "
- "same length")
- : G_("%G%qD output truncated before terminating nul "
- "copying %E bytes from a string of the same "
- "length")),
- call, func, cnt);
+ return warning_n (callloc, OPT_Wstringop_truncation,
+ cntrange[0].to_uhwi (),
+ "%G%qD output truncated before terminating "
+ "nul copying %E byte from a string of the "
+ "same length",
+ "%G%qD output truncated before terminating nul "
+ "copying %E bytes from a string of the same "
+ "length",
+ call, func, cnt);
else if (wi::geu_p (lenrange[0], cntrange[1]))
{
/* The shortest string is longer than the upper bound of
the count so the truncation is certain. */
if (cntrange[0] == cntrange[1])
- return warning_at (callloc, OPT_Wstringop_truncation,
- integer_onep (cnt)
- ? G_("%G%qD output truncated copying %E byte "
- "from a string of length %wu")
- : G_("%G%qD output truncated copying %E bytes "
- "from a string of length %wu"),
- call, func, cnt, lenrange[0].to_uhwi ());
+ return warning_n (callloc, OPT_Wstringop_truncation,
+ cntrange[0].to_uhwi (),
+ "%G%qD output truncated copying %E byte "
+ "from a string of length %wu",
+ "%G%qD output truncated copying %E bytes "
+ "from a string of length %wu",
+ call, func, cnt, lenrange[0].to_uhwi ());
return warning_at (callloc, OPT_Wstringop_truncation,
"%G%qD output truncated copying between %wu "
/* The longest string is longer than the upper bound of
the count so the truncation is possible. */
if (cntrange[0] == cntrange[1])
- return warning_at (callloc, OPT_Wstringop_truncation,
- integer_onep (cnt)
- ? G_("%G%qD output may be truncated copying %E "
- "byte from a string of length %wu")
- : G_("%G%qD output may be truncated copying %E "
- "bytes from a string of length %wu"),
- call, func, cnt, lenrange[1].to_uhwi ());
+ return warning_n (callloc, OPT_Wstringop_truncation,
+ cntrange[0].to_uhwi (),
+ "%G%qD output may be truncated copying %E "
+ "byte from a string of length %wu",
+ "%G%qD output may be truncated copying %E "
+ "bytes from a string of length %wu",
+ call, func, cnt, lenrange[1].to_uhwi ());
return warning_at (callloc, OPT_Wstringop_truncation,
"%G%qD output may be truncated copying between %wu "