-Wformat: fix nonsensical "wide character" message (PR c/84258)
authorDavid Malcolm <dmalcolm@redhat.com>
Tue, 1 May 2018 18:51:15 +0000 (18:51 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Tue, 1 May 2018 18:51:15 +0000 (18:51 +0000)
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
gcc/c-family/c-format.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/Wformat-pr84258.c [new file with mode: 0644]

index ab85a73bd1b5983242ba924125036263ed94979f..a6ae85f24cdf49001b4c999f202382f35f959889 100644 (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
index ee7c33d97f2291756b201bb286082d297ce3e67f..a0192dd3296bc18b6ebd7355a4e93785a8b89761 100644 (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);
index cefe1ca326d9d207c21ad0a6815511dbfee84369..f5b94c65dafa4a989992f5a1c957eee14330a6b0 100644 (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
diff --git a/gcc/testsuite/c-c++-common/Wformat-pr84258.c b/gcc/testsuite/c-c++-common/Wformat-pr84258.c
new file mode 100644 (file)
index 0000000..d2870a8
--- /dev/null
@@ -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;
+}