-Wformat: fix nonsensical "wide character" message (PR c/84258)

gcc/c-family/ChangeLog:
	PR c/84258
	* c-format.c (struct format_check_results): Add field
	"number_non_char".
	(check_format_info): Initialize it, and warn if encountered.
	(check_format_arg): Distinguish between wide char and
	everything else when detecting arrays of non-char.

gcc/testsuite/ChangeLog:
	PR c/84258
	* c-c++-common/Wformat-pr84258.c: New test.

From-SVN: r259807
This commit is contained in:
David Malcolm 2018-05-01 18:51:15 +00:00 committed by David Malcolm
parent 41e2c1b0b4
commit 2cc7d3a7da
4 changed files with 49 additions and 2 deletions

View File

@ -1,3 +1,12 @@
2018-05-01 David Malcolm <dmalcolm@redhat.com>
PR c/84258
* c-format.c (struct format_check_results): Add field
"number_non_char".
(check_format_info): Initialize it, and warn if encountered.
(check_format_arg): Distinguish between wide char and
everything else when detecting arrays of non-char.
2018-04-30 David Malcolm <dmalcolm@redhat.com>
* c-format.c (get_corrected_substring): Update for

View File

@ -974,6 +974,8 @@ struct format_check_results
/* Number of leaves of the format argument that were wide string
literals. */
int number_wide;
/* Number of leaves of the format argument that are not array of "char". */
int number_non_char;
/* Number of leaves of the format argument that were empty strings. */
int number_empty;
/* Number of leaves of the format argument that were unterminated
@ -1435,6 +1437,7 @@ check_format_info (function_format_info *info, tree params,
res.extra_arg_loc = UNKNOWN_LOCATION;
res.number_dollar_extra_args = 0;
res.number_wide = 0;
res.number_non_char = 0;
res.number_empty = 0;
res.number_unterminated = 0;
res.number_other = 0;
@ -1511,6 +1514,10 @@ check_format_info (function_format_info *info, tree params,
if (res.number_wide > 0)
warning_at (loc, OPT_Wformat_, "format is a wide character string");
if (res.number_non_char > 0)
warning_at (loc, OPT_Wformat_,
"format string is not an array of type %qs", "char");
if (res.number_unterminated > 0)
warning_at (loc, OPT_Wformat_, "unterminated format string");
}
@ -1656,9 +1663,16 @@ check_format_arg (void *ctx, tree format_tree,
res->number_non_literal++;
return;
}
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (format_tree))) != char_type_node)
tree underlying_type
= TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (format_tree)));
if (underlying_type != char_type_node)
{
res->number_wide++;
if (underlying_type == char16_type_node
|| underlying_type == char32_type_node
|| underlying_type == wchar_type_node)
res->number_wide++;
else
res->number_non_char++;
return;
}
format_chars = TREE_STRING_POINTER (format_tree);

View File

@ -1,3 +1,8 @@
2018-05-01 David Malcolm <dmalcolm@redhat.com>
PR c/84258
* c-c++-common/Wformat-pr84258.c: New test.
2018-05-01 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
PR tree-optimization/82665

View File

@ -0,0 +1,19 @@
/* { dg-options "-Wformat" } */
int main (int argc, char **argv)
{
char buf[10];
char c[] = "%i";
unsigned char uc[] = "%i";
const char cc[] = "%i";
const unsigned char cuc[] = "%i";
__builtin_sprintf(buf, (char *)c, 1);
__builtin_sprintf(buf, (char *)uc, 1);
__builtin_sprintf(buf, (char *)cc, 1);
__builtin_sprintf(buf, (char *)cuc, 1); /* { dg-warning "format string is not an array of type 'char'" } */
__builtin_sprintf(buf, (const char *)L"foo"); /* { dg-warning "format is a wide character string" } */
return 0;
}