diff options
author | bde <bde@FreeBSD.org> | 1998-08-24 06:33:52 +0000 |
---|---|---|
committer | bde <bde@FreeBSD.org> | 1998-08-24 06:33:52 +0000 |
commit | f0825df2782f486722ece766eb1442debffcfc7c (patch) | |
tree | 2c0b7085e4925b2a1773ce56247a6c51a8cb7808 /contrib/gcc | |
parent | 4ce525c0fd15056ead6463b1dcd8b5a242506b71 (diff) | |
download | FreeBSD-src-f0825df2782f486722ece766eb1442debffcfc7c.zip FreeBSD-src-f0825df2782f486722ece766eb1442debffcfc7c.tar.gz |
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.
Diffstat (limited to 'contrib/gcc')
-rw-r--r-- | contrib/gcc/c-common.c | 62 | ||||
-rw-r--r-- | contrib/gcc/flags.h | 4 | ||||
-rw-r--r-- | contrib/gcc/toplev.c | 5 |
3 files changed, 69 insertions, 2 deletions
diff --git a/contrib/gcc/c-common.c b/contrib/gcc/c-common.c index eace598..c4ab381 100644 --- a/contrib/gcc/c-common.c +++ b/contrib/gcc/c-common.c @@ -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; diff --git a/contrib/gcc/flags.h b/contrib/gcc/flags.h index ed1cf57..3538549 100644 --- a/contrib/gcc/flags.h +++ b/contrib/gcc/flags.h @@ -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. */ diff --git a/contrib/gcc/toplev.c b/contrib/gcc/toplev.c index 1b6fccb..cf7ec18 100644 --- a/contrib/gcc/toplev.c +++ b/contrib/gcc/toplev.c @@ -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} }; |