diff --git a/contrib/gcc/c-common.c b/contrib/gcc/c-common.c index 78b4d858acbf..eace598e1ae0 100644 --- a/contrib/gcc/c-common.c +++ b/contrib/gcc/c-common.c @@ -536,6 +536,7 @@ decl_attributes (node, attributes, prefix_attributes) int format_num; int first_arg_num; int is_scan; + int null_format_ok; tree argument; int arg_num; @@ -550,15 +551,30 @@ decl_attributes (node, attributes, prefix_attributes) && (!strcmp (IDENTIFIER_POINTER (format_type), "printf") || !strcmp (IDENTIFIER_POINTER (format_type), "__printf__"))) - is_scan = 0; + { + is_scan = 0; + null_format_ok = 0; + } + else if (TREE_CODE (format_type) == IDENTIFIER_NODE + && (!strcmp (IDENTIFIER_POINTER (format_type), "printf0") + || !strcmp (IDENTIFIER_POINTER (format_type), + "__printf0__"))) + { + is_scan = 0; + null_format_ok = 1; + } else if (TREE_CODE (format_type) == IDENTIFIER_NODE && (!strcmp (IDENTIFIER_POINTER (format_type), "scanf") || !strcmp (IDENTIFIER_POINTER (format_type), "__scanf__"))) - is_scan = 1; + { + is_scan = 1; + null_format_ok = 0; + } else { - error ("unrecognized format specifier for `%s'"); + error_with_decl (decl, + "unrecognized format specifier for `%s'"); continue; } @@ -625,7 +641,8 @@ decl_attributes (node, attributes, prefix_attributes) record_function_format (DECL_NAME (decl), DECL_ASSEMBLER_NAME (decl), - is_scan, format_num, first_arg_num); + is_scan, null_format_ok, format_num, + first_arg_num); break; } @@ -730,6 +747,7 @@ typedef struct function_format_info { tree name; /* identifier such as "printf" */ tree assembler_name; /* optional mangled identifier (for C++) */ int is_scan; /* TRUE if *scanf */ + int null_format_ok; /* TRUE if the format string may be NULL */ int format_num; /* number of format argument */ int first_arg_num; /* number of first arg (zero for varargs) */ } function_format_info; @@ -748,15 +766,15 @@ static void check_format_info PROTO((function_format_info *, tree)); void init_function_format_info () { - record_function_format (get_identifier ("printf"), NULL_TREE, 0, 1, 2); - record_function_format (get_identifier ("fprintf"), NULL_TREE, 0, 2, 3); - record_function_format (get_identifier ("sprintf"), NULL_TREE, 0, 2, 3); - record_function_format (get_identifier ("scanf"), NULL_TREE, 1, 1, 2); - record_function_format (get_identifier ("fscanf"), NULL_TREE, 1, 2, 3); - record_function_format (get_identifier ("sscanf"), NULL_TREE, 1, 2, 3); - record_function_format (get_identifier ("vprintf"), NULL_TREE, 0, 1, 0); - record_function_format (get_identifier ("vfprintf"), NULL_TREE, 0, 2, 0); - record_function_format (get_identifier ("vsprintf"), NULL_TREE, 0, 2, 0); + record_function_format (get_identifier ("printf"), NULL_TREE, 0, 0, 1, 2); + record_function_format (get_identifier ("fprintf"), NULL_TREE, 0, 0, 2, 3); + record_function_format (get_identifier ("sprintf"), NULL_TREE, 0, 0, 2, 3); + record_function_format (get_identifier ("scanf"), NULL_TREE, 1, 0, 1, 2); + record_function_format (get_identifier ("fscanf"), NULL_TREE, 1, 0, 2, 3); + record_function_format (get_identifier ("sscanf"), NULL_TREE, 1, 0, 2, 3); + record_function_format (get_identifier ("vprintf"), NULL_TREE, 0, 0, 1, 0); + record_function_format (get_identifier ("vfprintf"), NULL_TREE, 0, 0, 2, 0); + record_function_format (get_identifier ("vsprintf"), NULL_TREE, 0, 0, 2, 0); } /* Record information for argument format checking. FUNCTION_IDENT is @@ -769,11 +787,12 @@ init_function_format_info () (e.g. for varargs such as vfprintf). */ void -record_function_format (name, assembler_name, is_scan, +record_function_format (name, assembler_name, is_scan, null_format_ok, format_num, first_arg_num) tree name; tree assembler_name; int is_scan; + int null_format_ok; int format_num; int first_arg_num; { @@ -797,6 +816,7 @@ record_function_format (name, assembler_name, is_scan, } info->is_scan = is_scan; + info->null_format_ok = null_format_ok; info->format_num = format_num; info->first_arg_num = first_arg_num; } @@ -876,7 +896,8 @@ check_format_info (info, params) format_tree = TREE_OPERAND (format_tree, 0); /* strip coercion */ if (integer_zerop (format_tree)) { - warning ("null format string"); + if (!info->null_format_ok) + warning ("null format string"); return; } if (TREE_CODE (format_tree) != ADDR_EXPR) diff --git a/contrib/gcc/c-tree.h b/contrib/gcc/c-tree.h index 02f57c3b9dca..5d132d0a0d2f 100644 --- a/contrib/gcc/c-tree.h +++ b/contrib/gcc/c-tree.h @@ -159,7 +159,7 @@ extern void gen_aux_info_record PROTO((tree, int, int, int)); extern void declare_function_name PROTO((void)); extern void decl_attributes PROTO((tree, tree, tree)); extern void init_function_format_info PROTO((void)); -extern void record_function_format PROTO((tree, tree, int, int, int)); +extern void record_function_format PROTO((tree, tree, int, int, int, int)); extern void check_function_format PROTO((tree, tree, tree)); /* Print an error message for invalid operands to arith operation CODE. NOP_EXPR is used as a special case (see truthvalue_conversion). */ diff --git a/contrib/gcc/extend.texi b/contrib/gcc/extend.texi index e85799c610d5..8eee0305664b 100644 --- a/contrib/gcc/extend.texi +++ b/contrib/gcc/extend.texi @@ -1394,13 +1394,15 @@ for consistency with the @code{printf} style format string argument @code{my_format}. The parameter @var{archetype} determines how the format string is -interpreted, and should be either @code{printf} or @code{scanf}. The -parameter @var{string-index} specifies which argument is the format -string argument (starting from 1), while @var{first-to-check} is the -number of the first argument to check against the format string. For -functions where the arguments are not available to be checked (such as -@code{vprintf}), specify the third parameter as zero. In this case the -compiler only checks the format string for consistency. +interpreted, and should be @code{printf}, @code{printf0}, or +@code{scanf}. @code{printf0} allows the format string to be a null +pointer, while @code{printf} does not. The parameter @var{string-index} +specifies which argument is the format string argument (starting +from 1), while @var{first-to-check} is the number of the first +argument to check against the format string. For functions where +the arguments are not available to be checked (such as @code{vprintf}), +specify the third parameter as zero. In this case the compiler +only checks the format string for consistency. In the example above, the format string (@code{my_format}) is the second argument of the function @code{my_print}, and the arguments to check