From 2cc7d3a7da20bcfd854302b1f265c6551b8a3741 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Tue, 1 May 2018 18:51:15 +0000 Subject: [PATCH] -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 --- gcc/c-family/ChangeLog | 9 +++++++++ gcc/c-family/c-format.c | 18 ++++++++++++++++-- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/c-c++-common/Wformat-pr84258.c | 19 +++++++++++++++++++ 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/Wformat-pr84258.c diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index ab85a73bd1b..a6ae85f24cd 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,12 @@ +2018-05-01 David Malcolm + + 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 * c-format.c (get_corrected_substring): Update for diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c index ee7c33d97f2..a0192dd3296 100644 --- a/gcc/c-family/c-format.c +++ b/gcc/c-family/c-format.c @@ -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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cefe1ca326d..f5b94c65daf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-05-01 David Malcolm + + PR c/84258 + * c-c++-common/Wformat-pr84258.c: New test. + 2018-05-01 Prathamesh Kulkarni PR tree-optimization/82665 diff --git a/gcc/testsuite/c-c++-common/Wformat-pr84258.c b/gcc/testsuite/c-c++-common/Wformat-pr84258.c new file mode 100644 index 00000000000..d2870a88701 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wformat-pr84258.c @@ -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; +} -- 2.30.2