diff options
author | Martin Sebor <msebor@redhat.com> | 2016-12-14 17:23:16 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2016-12-14 10:23:16 -0700 |
commit | 474da67ef9ec3658e4da9deb5373353532b2a840 (patch) | |
tree | 9216700dc546aef48d9bff1a0ab2203160ce0f8e /gcc/builtins.c | |
parent | b4ba0852099ad28a533327ac25e8337910be28e8 (diff) | |
download | gcc-474da67ef9ec3658e4da9deb5373353532b2a840.zip gcc-474da67ef9ec3658e4da9deb5373353532b2a840.tar.gz gcc-474da67ef9ec3658e4da9deb5373353532b2a840.tar.bz2 |
PR c/78673 - sprintf missing attribute nonnull on destination argument
PR c/78673 - sprintf missing attribute nonnull on destination argument
PR c/17308 - nonnull attribute not as useful as it could be
gcc/ChangeLog:
PR c/17308
* builtin-attrs.def (ATTR_NONNULL_1_1, ATTR_NONNULL_1_2): Defined.
(ATTR_NONNULL_1_3, ATTR_NONNULL_1_4, ATTR_NONNULL_1_5): Same.
(ATTR_NOTHROW_NONNULL_1_1, ATTR_NOTHROW_NONNULL_1_2): Same.
(ATTR_NOTHROW_NONNULL_1_3, ATTR_NOTHROW_NONNULL_1_4): Same.
(ATTR_NOTHROW_NONNULL_1_5): Same.
(ATTR_NONNULL_1_FORMAT_PRINTF_1_2): Same.
(ATTR_NONNULL_1_FORMAT_PRINTF_2_0): Same.
(ATTR_NONNULL_1_FORMAT_PRINTF_2_3): Same.
(ATTR_NONNULL_1_FORMAT_PRINTF_3_0): Same.
(ATTR_NONNULL_1_FORMAT_PRINTF_3_4): Same.
(ATTR_NONNULL_1_FORMAT_PRINTF_4_0): Same.
(ATTR_NONNULL_1_FORMAT_PRINTF_4_5): Same.
* builtins.c (validate_arg): Add argument. Treat null pointers
passed to nonnull arguments as invalid.
(validate_arglist): Same.
* builtins.def (fprintf, fprintf_unlocked): Add nonnull attribute.
(printf, printf_unlocked, sprintf. vfprintf, vsprintf): Same.
(__sprintf_chk, __vsprintf_chk, __fprintf_chk, __vfprintf_chk): Same.
* calls.c (get_nonnull_ags, maybe_warn_null_arg): New functions.
(initialize_argument_information): Diagnose null pointers passed to
arguments declared nonnull.
* calls.h (get_nonnull_args): Declared.
gcc/c-family/ChangeLog:
PR c/17308
* c-common.c (check_nonnull_arg): Disable when optimization
is enabled.
gcc/testsuite/ChangeLog:
PR c/17308
* gcc.dg/builtins-nonnull.c: New test.
* gcc.dg/nonnull-4.c: New test.
From-SVN: r243661
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r-- | gcc/builtins.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c index b056e12..ca038cd 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -147,7 +147,7 @@ static tree fold_builtin_classify_type (tree); static tree fold_builtin_strlen (location_t, tree, tree); static tree fold_builtin_inf (location_t, tree, int); static tree rewrite_call_expr (location_t, tree, int, tree, int, ...); -static bool validate_arg (const_tree, enum tree_code code); +static bool validate_arg (const_tree, enum tree_code code, bool = false); static rtx expand_builtin_fabs (tree, rtx, rtx); static rtx expand_builtin_signbit (tree, rtx); static tree fold_builtin_memcmp (location_t, tree, tree, tree); @@ -1034,7 +1034,7 @@ more_const_call_expr_args_p (const const_call_expr_arg_iterator *iter) /* This function validates the types of a function call argument list against a specified list of tree_codes. If the last specifier is a 0, - that represents an ellipses, otherwise the last specifier must be a + that represents an ellipsis, otherwise the last specifier must be a VOID_TYPE. */ static bool @@ -1049,9 +1049,14 @@ validate_arglist (const_tree callexpr, ...) va_start (ap, callexpr); init_const_call_expr_arg_iterator (callexpr, &iter); - do + /* Get a bitmap of pointer argument numbers declared attribute nonnull. */ + bitmap argmap = get_nonnull_args (callexpr); + + for (unsigned argno = 1; ; ++argno) { code = (enum tree_code) va_arg (ap, int); + bool nonnull = false; + switch (code) { case 0: @@ -1063,23 +1068,31 @@ validate_arglist (const_tree callexpr, ...) true, otherwise return false. */ res = !more_const_call_expr_args_p (&iter); goto end; + case POINTER_TYPE: + /* The actual argument must be nonnull when either the whole + called function has been declared nonnull, or when the formal + argument corresponding to the actual argument has been. */ + if (argmap) + nonnull = bitmap_empty_p (argmap) || bitmap_bit_p (argmap, argno); + /* FALLTHRU */ default: /* If no parameters remain or the parameter's code does not match the specified code, return false. Otherwise continue checking any remaining arguments. */ arg = next_const_call_expr_arg (&iter); - if (!validate_arg (arg, code)) + if (!validate_arg (arg, code, nonnull)) goto end; break; } } - while (1); /* We need gotos here since we can only have one VA_CLOSE in a function. */ end: ; va_end (ap); + BITMAP_FREE (argmap); + return res; } @@ -9121,15 +9134,17 @@ rewrite_call_expr (location_t loc, tree exp, int skip, tree fndecl, int n, ...) } /* Validate a single argument ARG against a tree code CODE representing - a type. */ + a type. When NONNULL is true consider a pointer argument valid only + if it's non-null. Return true when argument is valid. */ static bool -validate_arg (const_tree arg, enum tree_code code) +validate_arg (const_tree arg, enum tree_code code, bool nonnull /*= false*/) { if (!arg) return false; else if (code == POINTER_TYPE) - return POINTER_TYPE_P (TREE_TYPE (arg)); + return POINTER_TYPE_P (TREE_TYPE (arg)) + && (!nonnull || !integer_zerop (arg)); else if (code == INTEGER_TYPE) return INTEGRAL_TYPE_P (TREE_TYPE (arg)); return code == TREE_CODE (TREE_TYPE (arg)); |