aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2016-12-14 17:23:16 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2016-12-14 10:23:16 -0700
commit474da67ef9ec3658e4da9deb5373353532b2a840 (patch)
tree9216700dc546aef48d9bff1a0ab2203160ce0f8e /gcc/builtins.c
parentb4ba0852099ad28a533327ac25e8337910be28e8 (diff)
downloadgcc-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.c31
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));