+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
/* 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
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;
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");
}
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);
--- /dev/null
+/* { 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;
+}