Support printf format checking of FreeBSD kernel formats %[Dbrz].

This is enabled by the undocumented option -fformat-extensions.
This option should be named better and/or give more control over
the extensions.

Fixed a message - don't warn about the field width when it's the
precision that has the wrong type.  Didn't fix excessive checking
for the precision relative to the type - ANSI requires both to be
ints, but gcc permits the field width to be either int or unsigned
int.
This commit is contained in:
Bruce Evans 1998-08-24 06:33:52 +00:00
parent e2cadcb1bc
commit 0f79d73473
3 changed files with 69 additions and 2 deletions

View file

@ -713,6 +713,11 @@ typedef struct {
} format_char_info;
static format_char_info print_char_table[] = {
/* FreeBSD kernel extensions. */
{ "D", 1, T_C, NULL, NULL, NULL, NULL, "-wp" },
{ "b", 1, T_C, NULL, NULL, NULL, NULL, "-wp" },
{ "rz", 0, T_I, T_I, T_L, NULL, NULL, "-wp0 +#" },
#define unextended_print_char_table (print_char_table + 3)
{ "di", 0, T_I, T_I, T_L, T_LL, T_LL, "-wp0 +" },
{ "oxX", 0, T_UI, T_UI, T_UL, T_ULL, T_ULL, "-wp0#" },
{ "u", 0, T_UI, T_UI, T_UL, T_ULL, T_ULL, "-wp0" },
@ -1071,11 +1076,12 @@ check_format_info (info, params)
cur_param = TREE_VALUE (params);
params = TREE_CHAIN (params);
++arg_num;
/* XXX should we allow unsigned ints here? */
if (TYPE_MAIN_VARIANT (TREE_TYPE (cur_param))
!= integer_type_node)
{
sprintf (message,
"field width is not type int (arg %d)",
"precision is not type int (arg %d)",
arg_num);
warning (message);
}
@ -1088,6 +1094,56 @@ check_format_info (info, params)
}
}
}
if (*format_chars == 'b')
{
/* There should be an int arg to control the string arg. */
if (params == 0)
{
warning (tfaff);
return;
}
if (info->first_arg_num != 0)
{
cur_param = TREE_VALUE (params);
params = TREE_CHAIN (params);
++arg_num;
if ((TYPE_MAIN_VARIANT (TREE_TYPE (cur_param))
!= integer_type_node)
&&
(TYPE_MAIN_VARIANT (TREE_TYPE (cur_param))
!= unsigned_type_node))
{
sprintf (message, "bitmap is not type int (arg %d)",
arg_num);
warning (message);
}
}
}
if (*format_chars == 'D')
{
/* There should be an unsigned char * arg before the string arg. */
if (params == 0)
{
warning (tfaff);
return;
}
if (info->first_arg_num != 0)
{
cur_param = TREE_VALUE (params);
params = TREE_CHAIN (params);
++arg_num;
cur_type = TREE_TYPE (cur_param);
if (TREE_CODE (cur_type) != POINTER_TYPE
|| TYPE_MAIN_VARIANT (TREE_TYPE (cur_type))
!= unsigned_char_type_node)
{
sprintf (message,
"ethernet address is not type unsigned char * (arg %d)",
arg_num);
warning (message);
}
}
}
if (*format_chars == 'h' || *format_chars == 'l' || *format_chars == 'q' ||
*format_chars == 'L')
length_char = *format_chars++;
@ -1115,7 +1171,9 @@ check_format_info (info, params)
continue;
}
format_chars++;
fci = info->is_scan ? scan_char_table : print_char_table;
fci = info->is_scan ? scan_char_table
: flag_format_extensions ? print_char_table
: unextended_print_char_table;
while (fci->format_chars != 0
&& index (fci->format_chars, format_char) == 0)
++fci;

View file

@ -338,6 +338,10 @@ extern int flag_gnu_linker;
/* Tag all structures with __attribute__(packed) */
extern int flag_pack_struct;
/* Nonzero means that -Wformat accepts certain non-ANSI formats. */
extern int flag_format_extensions;
/* Other basic status info about current function. */

View file

@ -521,6 +521,10 @@ int flag_gnu_linker = 1;
/* Tag all structures with __attribute__(packed) */
int flag_pack_struct = 0;
/* Nonzero means that -Wformat accepts certain system-dependent formats. */
int flag_format_extensions = 0;
/* Table of language-independent -f options.
STRING is the option name. VARIABLE is the address of the variable.
ON_VALUE is the value to store in VARIABLE
@ -567,6 +571,7 @@ struct { char *string; int *variable; int on_value;} f_options[] =
{"verbose-asm", &flag_verbose_asm, 1},
{"gnu-linker", &flag_gnu_linker, 1},
{"pack-struct", &flag_pack_struct, 1},
{"format-extensions", &flag_format_extensions, 1},
{"bytecode", &output_bytecode, 1}
};