aboutsummaryrefslogtreecommitdiff
path: root/contrib/gcc
diff options
context:
space:
mode:
authorJohn Polstra <jdp@FreeBSD.org>1998-07-15 04:22:45 +0000
committerJohn Polstra <jdp@FreeBSD.org>1998-07-15 04:22:45 +0000
commit3bc25faee6f2707240c1f8d28280dfb06aaea0e4 (patch)
tree6637c2337264d21d778f377b7b8d2a639015770c /contrib/gcc
parent15c73825614ee62f8090d3831df899c72dbb8a16 (diff)
downloadsrc-3bc25faee6f2707240c1f8d28280dfb06aaea0e4.tar.gz
src-3bc25faee6f2707240c1f8d28280dfb06aaea0e4.zip
Add support for a new archetype "printf0" for the "format" function
attribute. It is like the existing "printf" archetype, except that it doesn't complain if the format string is a null pointer. See the node "Function Attributes" in the GCC info pages if you don't know what this is all about. This change will allow us to add format string checking for the err(3) family of functions.
Notes
Notes: svn path=/head/; revision=37654
Diffstat (limited to 'contrib/gcc')
-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