From 346114b54da37792ec1759a1e76626eb4d3a5594 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 2 Mar 2018 20:04:58 +0100 Subject: [PATCH] substring-locations.h (format_warning_va): Formatting fix for ATTRIBUTE_GCC_DIAG. * 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. From-SVN: r258154 --- gcc/ChangeLog | 24 ++ gcc/gimple-ssa-sprintf.c | 491 +++++++++++++++++++------------------- gcc/substring-locations.c | 70 +++++- gcc/substring-locations.h | 20 +- 4 files changed, 345 insertions(+), 260 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 662b72fcc74..a05934316e8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,27 @@ +2018-03-02 Jakub Jelinek + + * 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. + 2018-03-02 Thomas Schwinge * doc/invoke.texi: Remove "Cilk Plus" references. diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c index 83d71f0d644..4ec58605ce8 100644 --- a/gcc/gimple-ssa-sprintf.c +++ b/gcc/gimple-ssa-sprintf.c @@ -589,18 +589,40 @@ get_format_string (tree format, location_t *ploc) 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, location_t argloc, /* 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, location_t argloc, { 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); - } - - 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 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); + + 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_walker::call_info &info, (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_walker::call_info &info, if (fmtres.range.min == fmtres.range.max) warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (), "%<%.*s%> directive output of %wu bytes causes " - "result to exceed %", - dirlen, + "result to exceed %", 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 %") - : G_ ("%<%.*s%> directive output between %wu and %wu " - "bytes may cause result to exceed %")); - 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 " + "%") + : G_ ("%<%.*s%> directive output between %wu and " + "%wu bytes may cause result to exceed " + "%"), 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_walker::call_info &info, 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::call_info &info, 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::call_info &info, 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); diff --git a/gcc/substring-locations.c b/gcc/substring-locations.c index cf3ec4fe697..2d7f0c15133 100644 --- a/gcc/substring-locations.c +++ b/gcc/substring-locations.c @@ -20,14 +20,17 @@ along with GCC; see the file COPYING3. If not see #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. If not see 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 &fmt_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 &fmt_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 @@ -179,6 +213,26 @@ format_warning_at_substring (const substring_loc &fmt_loc, 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. If successful, return NULL and write the source location to *OUT_LOC. Otherwise return an error message. Error messages are intended diff --git a/gcc/substring-locations.h b/gcc/substring-locations.h index 7c8a0acc4bf..fca6fd333c4 100644 --- a/gcc/substring-locations.h +++ b/gcc/substring-locations.h @@ -80,13 +80,29 @@ extern 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) - 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. */ -- 2.30.2