diff options
author | YamaArashi <shadow962@live.com> | 2016-04-29 05:24:01 -0700 |
---|---|---|
committer | YamaArashi <shadow962@live.com> | 2016-04-29 05:24:01 -0700 |
commit | fb026be50ef59b1affc44b9d46cf50c9bafe6bf5 (patch) | |
tree | 75527f7920a023c4be3da3b5dae8e302931b9323 /gcc | |
parent | 4bd39ff94b984ff6531ffc8a533e947dff9812aa (diff) |
remove format checking
Diffstat (limited to 'gcc')
-rwxr-xr-x | gcc/c-common.c | 1039 | ||||
-rwxr-xr-x | gcc/c-decl.c | 12 | ||||
-rwxr-xr-x | gcc/c-tree.h | 6 | ||||
-rwxr-xr-x | gcc/c-typeck.c | 5 |
4 files changed, 1 insertions, 1061 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c index cfa2db2..8384da4 100755 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -46,19 +46,13 @@ int skip_evaluation; enum attrs {A_PACKED, A_NOCOMMON, A_COMMON, A_NORETURN, A_CONST, A_T_UNION, A_NO_CHECK_MEMORY_USAGE, A_NO_INSTRUMENT_FUNCTION, A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED, - A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS, + A_UNUSED, A_WEAK, A_ALIAS, A_INIT_PRIORITY}; -enum format_type { printf_format_type, scanf_format_type, - strftime_format_type }; - static void declare_hidden_char_array (char *, char *); static void add_attribute (enum attrs, char *, int, int, int); static void init_attributes (void); -static void record_function_format (tree, tree, enum format_type, - int, int); -static void record_international_format (tree, tree, int); static tree c_find_base_decl (tree); /* Keep a stack of if statements. We record the number of compound @@ -380,8 +374,6 @@ init_attributes () add_attribute (A_MODE, "mode", 1, 1, 1); add_attribute (A_SECTION, "section", 1, 1, 1); add_attribute (A_ALIGNED, "aligned", 0, 1, 0); - add_attribute (A_FORMAT, "format", 3, 3, 1); - add_attribute (A_FORMAT_ARG, "format_arg", 1, 1, 1); add_attribute (A_WEAK, "weak", 0, 0, 1); add_attribute (A_ALIAS, "alias", 1, 1, 1); add_attribute (A_INIT_PRIORITY, "init_priority", 0, 1, 0); @@ -647,179 +639,6 @@ decl_attributes (node, attributes, prefix_attributes) } break; - case A_FORMAT: - { - tree format_type_id = TREE_VALUE (args); - tree format_num_expr = TREE_VALUE (TREE_CHAIN (args)); - tree first_arg_num_expr - = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args))); - int format_num; - int first_arg_num; - enum format_type format_type; - tree argument; - int arg_num; - - if (TREE_CODE (decl) != FUNCTION_DECL) - { - error_with_decl (decl, - "argument format specified for non-function `%s'"); - continue; - } - - if (TREE_CODE (format_type_id) != IDENTIFIER_NODE) - { - error ("unrecognized format specifier"); - continue; - } - else - { - char *p = IDENTIFIER_POINTER (format_type_id); - - if (!strcmp (p, "printf") || !strcmp (p, "__printf__")) - format_type = printf_format_type; - else if (!strcmp (p, "scanf") || !strcmp (p, "__scanf__")) - format_type = scanf_format_type; - else if (!strcmp (p, "strftime") - || !strcmp (p, "__strftime__")) - format_type = strftime_format_type; - else - { - error ("`%s' is an unrecognized format function type", p); - continue; - } - } - - /* Strip any conversions from the string index and first arg number - and verify they are constants. */ - while (TREE_CODE (format_num_expr) == NOP_EXPR - || TREE_CODE (format_num_expr) == CONVERT_EXPR - || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR) - format_num_expr = TREE_OPERAND (format_num_expr, 0); - - while (TREE_CODE (first_arg_num_expr) == NOP_EXPR - || TREE_CODE (first_arg_num_expr) == CONVERT_EXPR - || TREE_CODE (first_arg_num_expr) == NON_LVALUE_EXPR) - first_arg_num_expr = TREE_OPERAND (first_arg_num_expr, 0); - - if (TREE_CODE (format_num_expr) != INTEGER_CST - || TREE_CODE (first_arg_num_expr) != INTEGER_CST) - { - error ("format string has non-constant operand number"); - continue; - } - - format_num = TREE_INT_CST_LOW (format_num_expr); - first_arg_num = TREE_INT_CST_LOW (first_arg_num_expr); - if (first_arg_num != 0 && first_arg_num <= format_num) - { - error ("format string arg follows the args to be formatted"); - continue; - } - - /* If a parameter list is specified, verify that the format_num - argument is actually a string, in case the format attribute - is in error. */ - argument = TYPE_ARG_TYPES (type); - if (argument) - { - for (arg_num = 1; ; ++arg_num) - { - if (argument == 0 || arg_num == format_num) - break; - argument = TREE_CHAIN (argument); - } - if (! argument - || TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE - || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument))) - != char_type_node)) - { - error ("format string arg not a string type"); - continue; - } - if (first_arg_num != 0) - { - /* Verify that first_arg_num points to the last arg, - the ... */ - while (argument) - arg_num++, argument = TREE_CHAIN (argument); - if (arg_num != first_arg_num) - { - error ("args to be formatted is not ..."); - continue; - } - } - } - - record_function_format (DECL_NAME (decl), - DECL_ASSEMBLER_NAME (decl), - format_type, format_num, first_arg_num); - break; - } - - case A_FORMAT_ARG: - { - tree format_num_expr = TREE_VALUE (args); - int format_num, arg_num; - tree argument; - - if (TREE_CODE (decl) != FUNCTION_DECL) - { - error_with_decl (decl, - "argument format specified for non-function `%s'"); - continue; - } - - /* Strip any conversions from the first arg number and verify it - is a constant. */ - while (TREE_CODE (format_num_expr) == NOP_EXPR - || TREE_CODE (format_num_expr) == CONVERT_EXPR - || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR) - format_num_expr = TREE_OPERAND (format_num_expr, 0); - - if (TREE_CODE (format_num_expr) != INTEGER_CST) - { - error ("format string has non-constant operand number"); - continue; - } - - format_num = TREE_INT_CST_LOW (format_num_expr); - - /* If a parameter list is specified, verify that the format_num - argument is actually a string, in case the format attribute - is in error. */ - argument = TYPE_ARG_TYPES (type); - if (argument) - { - for (arg_num = 1; ; ++arg_num) - { - if (argument == 0 || arg_num == format_num) - break; - argument = TREE_CHAIN (argument); - } - if (! argument - || TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE - || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument))) - != char_type_node)) - { - error ("format string arg not a string type"); - continue; - } - } - - if (TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) != POINTER_TYPE - || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (TREE_TYPE (decl)))) - != char_type_node)) - { - error ("function does not return string type"); - continue; - } - - record_international_format (DECL_NAME (decl), - DECL_ASSEMBLER_NAME (decl), - format_num); - break; - } - case A_WEAK: declare_weak (decl); break; @@ -1034,863 +853,7 @@ strip_attrs (specs_attrs) return specs; } - -/* Check a printf/fprintf/sprintf/scanf/fscanf/sscanf format against - a parameter list. */ - -#define T_I &integer_type_node -#define T_L &long_integer_type_node -#define T_LL &long_long_integer_type_node -#define T_S &short_integer_type_node -#define T_UI &unsigned_type_node -#define T_UL &long_unsigned_type_node -#define T_ULL &long_long_unsigned_type_node -#define T_US &short_unsigned_type_node -#define T_F &float_type_node -#define T_D &double_type_node -#define T_LD &long_double_type_node -#define T_C &char_type_node -#define T_UC &unsigned_char_type_node -#define T_V &void_type_node -#define T_W &wchar_type_node -#define T_ST &sizetype - -typedef struct { - char *format_chars; - int pointer_count; - /* Type of argument if no length modifier is used. */ - tree *nolen; - /* Type of argument if length modifier for shortening to byte is used. - If NULL, then this modifier is not allowed. */ - tree *hhlen; - /* Type of argument if length modifier for shortening is used. - If NULL, then this modifier is not allowed. */ - tree *hlen; - /* Type of argument if length modifier `l' is used. - If NULL, then this modifier is not allowed. */ - tree *llen; - /* Type of argument if length modifier `q' or `ll' is used. - If NULL, then this modifier is not allowed. */ - tree *qlen; - /* Type of argument if length modifier `L' is used. - If NULL, then this modifier is not allowed. */ - tree *bigllen; - /* Type of argument if length modifier `Z' is used. - If NULL, then this modifier is not allowed. */ - tree *zlen; - /* List of other modifier characters allowed with these options. */ - char *flag_chars; -} format_char_info; - -static format_char_info print_char_table[] = { - { "di", 0, T_I, T_I, T_I, T_L, T_LL, T_LL, T_ST, "-wp0 +" }, - { "oxX", 0, T_UI, T_UI, T_UI, T_UL, T_ULL, T_ULL, T_ST, "-wp0#" }, - { "u", 0, T_UI, T_UI, T_UI, T_UL, T_ULL, T_ULL, T_ST, "-wp0" }, -/* A GNU extension. */ - { "m", 0, T_V, NULL, NULL, NULL, NULL, NULL, NULL, "-wp" }, - { "feEgGaA", 0, T_D, NULL, NULL, NULL, NULL, T_LD, NULL, "-wp0 +#" }, - { "c", 0, T_I, NULL, NULL, T_W, NULL, NULL, NULL, "-w" }, - { "C", 0, T_W, NULL, NULL, NULL, NULL, NULL, NULL, "-w" }, - { "s", 1, T_C, NULL, NULL, T_W, NULL, NULL, NULL, "-wp" }, - { "S", 1, T_W, NULL, NULL, NULL, NULL, NULL, NULL, "-wp" }, - { "p", 1, T_V, NULL, NULL, NULL, NULL, NULL, NULL, "-w" }, - { "n", 1, T_I, NULL, T_S, T_L, T_LL, NULL, NULL, "" }, - { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } -}; - -static format_char_info scan_char_table[] = { - { "di", 1, T_I, T_C, T_S, T_L, T_LL, T_LL, NULL, "*" }, - { "ouxX", 1, T_UI, T_UC, T_US, T_UL, T_ULL, T_ULL, NULL, "*" }, - { "efgEGaA", 1, T_F, NULL, NULL, T_D, NULL, T_LD, NULL, "*" }, - { "c", 1, T_C, NULL, NULL, T_W, NULL, NULL, NULL, "*" }, - { "s", 1, T_C, NULL, NULL, T_W, NULL, NULL, NULL, "*a" }, - { "[", 1, T_C, NULL, NULL, NULL, NULL, NULL, NULL, "*a" }, - { "C", 1, T_W, NULL, NULL, NULL, NULL, NULL, NULL, "*" }, - { "S", 1, T_W, NULL, NULL, NULL, NULL, NULL, NULL, "*a" }, - { "p", 2, T_V, NULL, NULL, NULL, NULL, NULL, NULL, "*" }, - { "n", 1, T_I, T_C, T_S, T_L, T_LL, NULL, NULL, "" }, - { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } -}; - -/* Handle format characters recognized by glibc's strftime.c. - '2' - MUST do years as only two digits - '3' - MAY do years as only two digits (depending on locale) - 'E' - E modifier is acceptable - 'O' - O modifier is acceptable to Standard C - 'o' - O modifier is acceptable as a GNU extension - 'G' - other GNU extensions */ - -static format_char_info time_char_table[] = { - { "y", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "2EO-_0w" }, - { "D", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "2" }, - { "g", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "2O-_0w" }, - { "cx", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "3E" }, - { "%RTXnrt", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "" }, - { "P", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "G" }, - { "HIMSUWdemw", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "-_0Ow" }, - { "Vju", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "-_0Oow" }, - { "Gklsz", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "-_0OGw" }, - { "ABZa", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "^#" }, - { "p", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "#" }, - { "bh", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "^" }, - { "CY", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "-_0EOw" }, - { NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } -}; - -typedef struct function_format_info -{ - struct function_format_info *next; /* next structure on the list */ - tree name; /* identifier such as "printf" */ - tree assembler_name; /* optional mangled identifier (for C++) */ - enum format_type format_type; /* type of format (printf, scanf, etc.) */ - int format_num; /* number of format argument */ - int first_arg_num; /* number of first arg (zero for varargs) */ -} function_format_info; - -static function_format_info *function_format_list = NULL; - -typedef struct international_format_info -{ - struct international_format_info *next; /* next structure on the list */ - tree name; /* identifier such as "gettext" */ - tree assembler_name; /* optional mangled identifier (for C++) */ - int format_num; /* number of format argument */ -} international_format_info; - -static international_format_info *international_format_list = NULL; - -static void check_format_info (function_format_info *, tree); - -/* Initialize the table of functions to perform format checking on. - The ANSI functions are always checked (whether <stdio.h> is - included or not), since it is common to call printf without - including <stdio.h>. There shouldn't be a problem with this, - since ANSI reserves these function names whether you include the - header file or not. In any case, the checking is harmless. - - Also initialize the name of function that modify the format string for - internationalization purposes. */ - -void -init_function_format_info () -{ - record_function_format (get_identifier ("printf"), NULL_TREE, - printf_format_type, 1, 2); - record_function_format (get_identifier ("fprintf"), NULL_TREE, - printf_format_type, 2, 3); - record_function_format (get_identifier ("sprintf"), NULL_TREE, - printf_format_type, 2, 3); - record_function_format (get_identifier ("scanf"), NULL_TREE, - scanf_format_type, 1, 2); - record_function_format (get_identifier ("fscanf"), NULL_TREE, - scanf_format_type, 2, 3); - record_function_format (get_identifier ("sscanf"), NULL_TREE, - scanf_format_type, 2, 3); - record_function_format (get_identifier ("vprintf"), NULL_TREE, - printf_format_type, 1, 0); - record_function_format (get_identifier ("vfprintf"), NULL_TREE, - printf_format_type, 2, 0); - record_function_format (get_identifier ("vsprintf"), NULL_TREE, - printf_format_type, 2, 0); - record_function_format (get_identifier ("strftime"), NULL_TREE, - strftime_format_type, 3, 0); -} -/* Record information for argument format checking. FUNCTION_IDENT is - the identifier node for the name of the function to check (its decl - need not exist yet). - FORMAT_TYPE specifies the type of format checking. FORMAT_NUM is the number - of the argument which is the format control string (starting from 1). - FIRST_ARG_NUM is the number of the first actual argument to check - against the format string, or zero if no checking is not be done - (e.g. for varargs such as vfprintf). */ - -static void -record_function_format (name, assembler_name, format_type, - format_num, first_arg_num) - tree name; - tree assembler_name; - enum format_type format_type; - int format_num; - int first_arg_num; -{ - function_format_info *info; - - /* Re-use existing structure if it's there. */ - - for (info = function_format_list; info; info = info->next) - { - if (info->name == name && info->assembler_name == assembler_name) - break; - } - if (! info) - { - info = (function_format_info *) xmalloc (sizeof (function_format_info)); - info->next = function_format_list; - function_format_list = info; - - info->name = name; - info->assembler_name = assembler_name; - } - - info->format_type = format_type; - info->format_num = format_num; - info->first_arg_num = first_arg_num; -} - -/* Record information for the names of function that modify the format - argument to format functions. FUNCTION_IDENT is the identifier node for - the name of the function (its decl need not exist yet) and FORMAT_NUM is - the number of the argument which is the format control string (starting - from 1). */ - -static void -record_international_format (name, assembler_name, format_num) - tree name; - tree assembler_name; - int format_num; -{ - international_format_info *info; - - /* Re-use existing structure if it's there. */ - - for (info = international_format_list; info; info = info->next) - { - if (info->name == name && info->assembler_name == assembler_name) - break; - } - - if (! info) - { - info - = (international_format_info *) - xmalloc (sizeof (international_format_info)); - info->next = international_format_list; - international_format_list = info; - - info->name = name; - info->assembler_name = assembler_name; - } - - info->format_num = format_num; -} - -static char tfaff[] = "too few arguments for format"; - -/* Check the argument list of a call to printf, scanf, etc. - NAME is the function identifier. - ASSEMBLER_NAME is the function's assembler identifier. - (Either NAME or ASSEMBLER_NAME, but not both, may be NULL_TREE.) - PARAMS is the list of argument values. */ - -void -check_function_format (name, assembler_name, params) - tree name; - tree assembler_name; - tree params; -{ - function_format_info *info; - - /* See if this function is a format function. */ - for (info = function_format_list; info; info = info->next) - { - if (info->assembler_name - ? (info->assembler_name == assembler_name) - : (info->name == name)) - { - /* Yup; check it. */ - check_format_info (info, params); - break; - } - } -} - -/* Check the argument list of a call to printf, scanf, etc. - INFO points to the function_format_info structure. - PARAMS is the list of argument values. */ - -static void -check_format_info (info, params) - function_format_info *info; - tree params; -{ - int i; - int arg_num; - int suppressed, wide, precise; - int length_char = 0; - int format_char; - int format_length; - tree format_tree; - tree cur_param; - tree cur_type; - tree wanted_type; - tree first_fillin_param; - char *format_chars; - format_char_info *fci = NULL; - char flag_chars[8]; - int has_operand_number = 0; - - /* Skip to format argument. If the argument isn't available, there's - no work for us to do; prototype checking will catch the problem. */ - for (arg_num = 1; ; ++arg_num) - { - if (params == 0) - return; - if (arg_num == info->format_num) - break; - params = TREE_CHAIN (params); - } - format_tree = TREE_VALUE (params); - params = TREE_CHAIN (params); - if (format_tree == 0) - return; - - /* We can only check the format if it's a string constant. */ - while (TREE_CODE (format_tree) == NOP_EXPR) - format_tree = TREE_OPERAND (format_tree, 0); /* strip coercion */ - - if (TREE_CODE (format_tree) == CALL_EXPR - && TREE_CODE (TREE_OPERAND (format_tree, 0)) == ADDR_EXPR - && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (format_tree, 0), 0)) - == FUNCTION_DECL)) - { - tree function = TREE_OPERAND (TREE_OPERAND (format_tree, 0), 0); - - /* See if this is a call to a known internationalization function - that modifies the format arg. */ - international_format_info *info; - - for (info = international_format_list; info; info = info->next) - if (info->assembler_name - ? (info->assembler_name == DECL_ASSEMBLER_NAME (function)) - : (info->name == DECL_NAME (function))) - { - tree inner_args; - int i; - - for (inner_args = TREE_OPERAND (format_tree, 1), i = 1; - inner_args != 0; - inner_args = TREE_CHAIN (inner_args), i++) - if (i == info->format_num) - { - format_tree = TREE_VALUE (inner_args); - - while (TREE_CODE (format_tree) == NOP_EXPR) - format_tree = TREE_OPERAND (format_tree, 0); - } - } - } - - if (integer_zerop (format_tree)) - { - warning ("null format string"); - return; - } - if (TREE_CODE (format_tree) != ADDR_EXPR) - return; - format_tree = TREE_OPERAND (format_tree, 0); - if (TREE_CODE (format_tree) != STRING_CST) - return; - format_chars = TREE_STRING_POINTER (format_tree); - format_length = TREE_STRING_LENGTH (format_tree); - if (format_length <= 1) - warning ("zero-length format string"); - if (format_chars[--format_length] != 0) - { - warning ("unterminated format string"); - return; - } - /* Skip to first argument to check. */ - while (arg_num + 1 < info->first_arg_num) - { - if (params == 0) - return; - params = TREE_CHAIN (params); - ++arg_num; - } - - first_fillin_param = params; - while (1) - { - int aflag; - if (*format_chars == 0) - { - if (format_chars - TREE_STRING_POINTER (format_tree) != format_length) - warning ("embedded `\\0' in format"); - if (info->first_arg_num != 0 && params != 0 && ! has_operand_number) - warning ("too many arguments for format"); - return; - } - if (*format_chars++ != '%') - continue; - if (*format_chars == 0) - { - warning ("spurious trailing `%%' in format"); - continue; - } - if (*format_chars == '%') - { - ++format_chars; - continue; - } - flag_chars[0] = 0; - suppressed = wide = precise = FALSE; - if (info->format_type == scanf_format_type) - { - suppressed = *format_chars == '*'; - if (suppressed) - ++format_chars; - while (ISDIGIT (*format_chars)) - ++format_chars; - } - else if (info->format_type == strftime_format_type) - { - while (*format_chars != 0 && strchr ("_-0^#", *format_chars) != 0) - { - if (pedantic) - warning ("ANSI C does not support the strftime `%c' flag", - *format_chars); - if (strchr (flag_chars, *format_chars) != 0) - { - warning ("repeated `%c' flag in format", - *format_chars); - ++format_chars; - } - else - { - i = strlen (flag_chars); - flag_chars[i++] = *format_chars++; - flag_chars[i] = 0; - } - } - while (ISDIGIT ((unsigned char) *format_chars)) - { - wide = TRUE; - ++format_chars; - } - if (wide && pedantic) - warning ("ANSI C does not support strftime format width"); - if (*format_chars == 'E' || *format_chars == 'O') - { - i = strlen (flag_chars); - flag_chars[i++] = *format_chars++; - flag_chars[i] = 0; - if (*format_chars == 'E' || *format_chars == 'O') - { - warning ("multiple E/O modifiers in format"); - while (*format_chars == 'E' || *format_chars == 'O') - ++format_chars; - } - } - } - else if (info->format_type == printf_format_type) - { - /* See if we have a number followed by a dollar sign. If we do, - it is an operand number, so set PARAMS to that operand. */ - if (*format_chars >= '0' && *format_chars <= '9') - { - char *p = format_chars; - - while (*p >= '0' && *p++ <= '9') - ; - - if (*p == '$') - { - int opnum = atoi (format_chars); - - params = first_fillin_param; - format_chars = p + 1; - has_operand_number = 1; - - for (i = 1; i < opnum && params != 0; i++) - params = TREE_CHAIN (params); - - if (opnum == 0 || params == 0) - { - warning ("operand number out of range in format"); - return; - } - } - } - - while (*format_chars != 0 && strchr (" +#0-", *format_chars) != 0) - { - if (strchr (flag_chars, *format_chars) != 0) - warning ("repeated `%c' flag in format", *format_chars++); - else - { - i = strlen (flag_chars); - flag_chars[i++] = *format_chars++; - flag_chars[i] = 0; - } - } - /* "If the space and + flags both appear, - the space flag will be ignored." */ - if (strchr (flag_chars, ' ') != 0 - && strchr (flag_chars, '+') != 0) - warning ("use of both ` ' and `+' flags in format"); - /* "If the 0 and - flags both appear, - the 0 flag will be ignored." */ - if (strchr (flag_chars, '0') != 0 - && strchr (flag_chars, '-') != 0) - warning ("use of both `0' and `-' flags in format"); - if (*format_chars == '*') - { - wide = TRUE; - /* "...a field width...may be indicated by an asterisk. - In this case, an int argument supplies the field width..." */ - ++format_chars; - if (params == 0) - { - warning (tfaff); - return; - } - if (info->first_arg_num != 0) - { - cur_param = TREE_VALUE (params); - params = TREE_CHAIN (params); - ++arg_num; - /* size_t is generally not valid here. - It will work on most machines, because size_t and int - have the same mode. But might as well warn anyway, - since it will fail on other machines. */ - if ((TYPE_MAIN_VARIANT (TREE_TYPE (cur_param)) - != integer_type_node) - && - (TYPE_MAIN_VARIANT (TREE_TYPE (cur_param)) - != unsigned_type_node)) - warning ("field width is not type int (arg %d)", arg_num); - } - } - else - { - while (ISDIGIT (*format_chars)) - { - wide = TRUE; - ++format_chars; - } - } - if (*format_chars == '.') - { - precise = TRUE; - ++format_chars; - if (*format_chars != '*' && !ISDIGIT (*format_chars)) - warning ("`.' not followed by `*' or digit in format"); - /* "...a...precision...may be indicated by an asterisk. - In this case, an int argument supplies the...precision." */ - if (*format_chars == '*') - { - if (info->first_arg_num != 0) - { - ++format_chars; - if (params == 0) - { - warning (tfaff); - return; - } - cur_param = TREE_VALUE (params); - params = TREE_CHAIN (params); - ++arg_num; - if (TYPE_MAIN_VARIANT (TREE_TYPE (cur_param)) - != integer_type_node) - warning ("field width is not type int (arg %d)", - arg_num); - } - } - else - { - while (ISDIGIT (*format_chars)) - ++format_chars; - } - } - } - - aflag = 0; - - if (info->format_type != strftime_format_type) - { - if (*format_chars == 'h' || *format_chars == 'l') - length_char = *format_chars++; - else if (*format_chars == 'q' || *format_chars == 'L') - { - length_char = *format_chars++; - if (pedantic) - warning ("ANSI C does not support the `%c' length modifier", - length_char); - } - else if (*format_chars == 'Z') - { - length_char = *format_chars++; - if (pedantic) - warning ("ANSI C does not support the `Z' length modifier"); - } - else - length_char = 0; - if (length_char == 'l' && *format_chars == 'l') - { - length_char = 'q', format_chars++; - /* FIXME: Is allowed in ISO C 9x. */ - if (pedantic) - warning ("ANSI C does not support the `ll' length modifier"); - } - else if (length_char == 'h' && *format_chars == 'h') - { - length_char = 'H', format_chars++; - /* FIXME: Is allowed in ISO C 9x. */ - if (pedantic) - warning ("ANSI C does not support the `hh' length modifier"); - } - if (*format_chars == 'a' && info->format_type == scanf_format_type) - { - if (format_chars[1] == 's' || format_chars[1] == 'S' - || format_chars[1] == '[') - { - /* `a' is used as a flag. */ - aflag = 1; - format_chars++; - } - } - if (suppressed && length_char != 0) - warning ("use of `*' and `%c' together in format", length_char); - } - format_char = *format_chars; - if (format_char == 0 - || (info->format_type != strftime_format_type && format_char == '%')) - { - warning ("conversion lacks type at end of format"); - continue; - } - /* The m, C, and S formats are GNU extensions. */ - if (pedantic && info->format_type != strftime_format_type - && (format_char == 'm' || format_char == 'C' || format_char == 'S')) - warning ("ANSI C does not support the `%c' format", format_char); - /* ??? The a and A formats are C9X extensions, and should be allowed - when a C9X option is added. */ - if (pedantic && info->format_type != strftime_format_type - && (format_char == 'a' || format_char == 'A')) - warning ("ANSI C does not support the `%c' format", format_char); - format_chars++; - switch (info->format_type) - { - case printf_format_type: - fci = print_char_table; - break; - case scanf_format_type: - fci = scan_char_table; - break; - case strftime_format_type: - fci = time_char_table; - break; - default: - abort (); - } - while (fci->format_chars != 0 - && strchr (fci->format_chars, format_char) == 0) - ++fci; - if (fci->format_chars == 0) - { - if (format_char >= 040 && format_char < 0177) - warning ("unknown conversion type character `%c' in format", - format_char); - else - warning ("unknown conversion type character 0x%x in format", - format_char); - continue; - } - if (pedantic) - { - if (strchr (fci->flag_chars, 'G') != 0) - warning ("ANSI C does not support `%%%c'", format_char); - if (strchr (fci->flag_chars, 'o') != 0 - && strchr (flag_chars, 'O') != 0) - warning ("ANSI C does not support `%%O%c'", format_char); - } - if (wide && strchr (fci->flag_chars, 'w') == 0) - warning ("width used with `%c' format", format_char); - if (strchr (fci->flag_chars, '2') != 0) - warning ("`%%%c' yields only last 2 digits of year", format_char); - else if (strchr (fci->flag_chars, '3') != 0) - warning ("`%%%c' yields only last 2 digits of year in some locales", - format_char); - if (precise && strchr (fci->flag_chars, 'p') == 0) - warning ("precision used with `%c' format", format_char); - if (aflag && strchr (fci->flag_chars, 'a') == 0) - { - warning ("`a' flag used with `%c' format", format_char); - /* To simplify the following code. */ - aflag = 0; - } - /* The a flag is a GNU extension. */ - else if (pedantic && aflag) - warning ("ANSI C does not support the `a' flag"); - if (info->format_type == scanf_format_type && format_char == '[') - { - /* Skip over scan set, in case it happens to have '%' in it. */ - if (*format_chars == '^') - ++format_chars; - /* Find closing bracket; if one is hit immediately, then - it's part of the scan set rather than a terminator. */ - if (*format_chars == ']') - ++format_chars; - while (*format_chars && *format_chars != ']') - ++format_chars; - if (*format_chars != ']') - /* The end of the format string was reached. */ - warning ("no closing `]' for `%%[' format"); - } - if (suppressed) - { - if (strchr (fci->flag_chars, '*') == 0) - warning ("suppression of `%c' conversion in format", format_char); - continue; - } - for (i = 0; flag_chars[i] != 0; ++i) - { - if (strchr (fci->flag_chars, flag_chars[i]) == 0) - warning ("flag `%c' used with type `%c'", - flag_chars[i], format_char); - } - if (info->format_type == strftime_format_type) - continue; - if (precise && strchr (flag_chars, '0') != 0 - && (format_char == 'd' || format_char == 'i' - || format_char == 'o' || format_char == 'u' - || format_char == 'x' || format_char == 'X')) - warning ("`0' flag ignored with precision specifier and `%c' format", - format_char); - switch (length_char) - { - default: wanted_type = fci->nolen ? *(fci->nolen) : 0; break; - case 'H': wanted_type = fci->hhlen ? *(fci->hhlen) : 0; break; - case 'h': wanted_type = fci->hlen ? *(fci->hlen) : 0; break; - case 'l': wanted_type = fci->llen ? *(fci->llen) : 0; break; - case 'q': wanted_type = fci->qlen ? *(fci->qlen) : 0; break; - case 'L': wanted_type = fci->bigllen ? *(fci->bigllen) : 0; break; - case 'Z': wanted_type = fci->zlen ? *fci->zlen : 0; break; - } - if (wanted_type == 0) - warning ("use of `%c' length character with `%c' type character", - length_char, format_char); - - /* Finally. . .check type of argument against desired type! */ - if (info->first_arg_num == 0) - continue; - if (fci->pointer_count == 0 && wanted_type == void_type_node) - /* This specifier takes no argument. */ - continue; - if (params == 0) - { - warning (tfaff); - return; - } - cur_param = TREE_VALUE (params); - params = TREE_CHAIN (params); - ++arg_num; - cur_type = TREE_TYPE (cur_param); - - STRIP_NOPS (cur_param); - - /* Check the types of any additional pointer arguments - that precede the "real" argument. */ - for (i = 0; i < fci->pointer_count + aflag; ++i) - { - if (TREE_CODE (cur_type) == POINTER_TYPE) - { - cur_type = TREE_TYPE (cur_type); - - if (cur_param != 0 && TREE_CODE (cur_param) == ADDR_EXPR) - cur_param = TREE_OPERAND (cur_param, 0); - else - cur_param = 0; - - continue; - } - if (TREE_CODE (cur_type) != ERROR_MARK) - warning ("format argument is not a %s (arg %d)", - ((fci->pointer_count + aflag == 1) - ? "pointer" : "pointer to a pointer"), - arg_num); - break; - } - - /* See if this is an attempt to write into a const type with - scanf or with printf "%n". */ - if ((info->format_type == scanf_format_type - || (info->format_type == printf_format_type - && format_char == 'n')) - && i == fci->pointer_count + aflag - && wanted_type != 0 - && TREE_CODE (cur_type) != ERROR_MARK - && (TYPE_READONLY (cur_type) - || (cur_param != 0 - && (TREE_CODE_CLASS (TREE_CODE (cur_param)) == 'c' - || (TREE_CODE_CLASS (TREE_CODE (cur_param)) == 'd' - && TREE_READONLY (cur_param)))))) - warning ("writing into constant object (arg %d)", arg_num); - - /* Check the type of the "real" argument, if there's a type we want. */ - if (i == fci->pointer_count + aflag && wanted_type != 0 - && TREE_CODE (cur_type) != ERROR_MARK - && wanted_type != TYPE_MAIN_VARIANT (cur_type) - /* If we want `void *', allow any pointer type. - (Anything else would already have got a warning.) */ - && ! (wanted_type == void_type_node - && fci->pointer_count > 0) - /* Don't warn about differences merely in signedness. */ - && !(TREE_CODE (wanted_type) == INTEGER_TYPE - && TREE_CODE (TYPE_MAIN_VARIANT (cur_type)) == INTEGER_TYPE - && (TREE_UNSIGNED (wanted_type) - ? wanted_type == (cur_type = unsigned_type (cur_type)) - : wanted_type == (cur_type = signed_type (cur_type)))) - /* Likewise, "signed char", "unsigned char" and "char" are - equivalent but the above test won't consider them equivalent. */ - && ! (wanted_type == char_type_node - && (TYPE_MAIN_VARIANT (cur_type) == signed_char_type_node - || TYPE_MAIN_VARIANT (cur_type) == unsigned_char_type_node))) - { - register char *this; - register char *that; - - this = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (wanted_type))); - that = 0; - if (TREE_CODE (cur_type) != ERROR_MARK - && TYPE_NAME (cur_type) != 0 - && TREE_CODE (cur_type) != INTEGER_TYPE - && !(TREE_CODE (cur_type) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (cur_type)) == INTEGER_TYPE)) - { - if (TREE_CODE (TYPE_NAME (cur_type)) == TYPE_DECL - && DECL_NAME (TYPE_NAME (cur_type)) != 0) - that = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (cur_type))); - else - that = IDENTIFIER_POINTER (TYPE_NAME (cur_type)); - } - - /* A nameless type can't possibly match what the format wants. - So there will be a warning for it. - Make up a string to describe vaguely what it is. */ - if (that == 0) - { - if (TREE_CODE (cur_type) == POINTER_TYPE) - that = "pointer"; - else - that = "different type"; - } - - /* Make the warning better in case of mismatch of int vs long. */ - if (TREE_CODE (cur_type) == INTEGER_TYPE - && TREE_CODE (wanted_type) == INTEGER_TYPE - && TYPE_PRECISION (cur_type) == TYPE_PRECISION (wanted_type) - && TYPE_NAME (cur_type) != 0 - && TREE_CODE (TYPE_NAME (cur_type)) == TYPE_DECL) - that = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (cur_type))); - - if (strcmp (this, that) != 0) - warning ("%s format, %s arg (arg %d)", this, that, arg_num); - } - } -} - /* Print a warning if a constant expression had overflow in folding. Invoke this function on every expression that the language requires to be a constant expression. diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 2ea334c..5578e9a 100755 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -543,10 +543,6 @@ int warn_redundant_decls = 0; int warn_nested_externs = 0; -/* Warn about *printf or *scanf format/argument anomalies. */ - -int warn_format; - /* Warn about a subscript that has type char. */ int warn_char_subscripts = 0; @@ -761,10 +757,6 @@ c_decode_option (p) warn_traditional = 1; else if (!strcmp (p, "-Wno-traditional")) warn_traditional = 0; - else if (!strcmp (p, "-Wformat")) - warn_format = 1; - else if (!strcmp (p, "-Wno-format")) - warn_format = 0; else if (!strcmp (p, "-Wchar-subscripts")) warn_char_subscripts = 1; else if (!strcmp (p, "-Wno-char-subscripts")) @@ -805,7 +797,6 @@ c_decode_option (p) warn_return_type = 1; warn_unused = 1; warn_switch = 1; - warn_format = 1; warn_char_subscripts = 1; warn_parentheses = 1; warn_missing_braces = 1; @@ -3485,9 +3476,6 @@ init_decl_processing () start_identifier_warnings (); - /* Prepare to check format strings against argument lists. */ - init_function_format_info (); - init_iterators (); incomplete_decl_finalize_hook = finish_incomplete_decl; diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 6ce8e4d..01f2191 100755 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -167,8 +167,6 @@ extern void gen_aux_info_record (tree, int, int, int); /* in c-common.c */ extern void declare_function_name (void); extern void decl_attributes (tree, tree, tree); -extern void init_function_format_info (void); -extern void check_function_format (tree, tree, tree); extern int c_get_alias_set (tree); extern void c_apply_type_quals_to_decl (int, tree); /* Print an error message for invalid operands to arith operation CODE. @@ -478,10 +476,6 @@ extern int warn_missing_noreturn; extern int warn_traditional; -/* Warn about *printf or *scanf format/argument anomalies. */ - -extern int warn_format; - /* Warn about a subscript that has type char. */ extern int warn_char_subscripts; diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index d5a77d6..807dfcf 100755 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -1560,11 +1560,6 @@ build_function_call (function, params) coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype), params, name, fundecl); - /* Check for errors in format strings. */ - - if (warn_format && (name || assembler_name)) - check_function_format (name, assembler_name, coerced_params); - /* Recognize certain built-in functions so we can make tree-codes other than CALL_EXPR. We do this when it enables fold-const.c to do something useful. */ |