summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/gcc/c-common.c51
-rw-r--r--contrib/gcc/c-tree.h2
-rw-r--r--contrib/gcc/extend.texi16
3 files changed, 46 insertions, 23 deletions
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