aboutsummaryrefslogtreecommitdiff
path: root/gcc/calls.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2018-06-18 16:32:59 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2018-06-18 10:32:59 -0600
commit781ff3d80e88d7d0df019eb3e82ef2a3fb64429c (patch)
tree01c31801fe48b1c21114b772785de9eefe119e7b /gcc/calls.c
parent7314856c61938db90d66f4cead8e4df73ea5d3af (diff)
downloadgcc-781ff3d80e88d7d0df019eb3e82ef2a3fb64429c.zip
gcc-781ff3d80e88d7d0df019eb3e82ef2a3fb64429c.tar.gz
gcc-781ff3d80e88d7d0df019eb3e82ef2a3fb64429c.tar.bz2
PR tree-optimization/81384 - built-in form of strnlen missing
gcc/ChangeLog: PR tree-optimization/81384 * builtin-types.def (BT_FN_SIZE_CONST_STRING_SIZE): New. * builtins.c (expand_builtin_strnlen): New function. (expand_builtin): Call it. (fold_builtin_n): Avoid setting TREE_NO_WARNING. * builtins.def (BUILT_IN_STRNLEN): New. * calls.c (maybe_warn_nonstring_arg): Handle BUILT_IN_STRNLEN. Warn for bounds in excess of maximum object size. * tree-ssa-strlen.c (maybe_set_strlen_range): Return tree representing single-value ranges. Handle strnlen. (handle_builtin_strlen): Handle strnlen. (strlen_check_and_optimize_stmt): Same. * doc/extend.texi (Other Builtins): Document strnlen. gcc/testsuite/ChangeLog: PR tree-optimization/81384 * gcc.c-torture/execute/builtins/lib/strnlen.c: New test. * gcc.c-torture/execute/builtins/strnlen-lib.c: New test. * gcc.c-torture/execute/builtins/strnlen.c: New test. * gcc.dg/attr-nonstring-2.c: New test. * gcc.dg/attr-nonstring-3.c: New test. * gcc.dg/attr-nonstring-4.c: New test. * gcc.dg/strlenopt-45.c: New test. * gcc.dg/strlenopt.h (strnlen): Declare. From-SVN: r261705
Diffstat (limited to 'gcc/calls.c')
-rw-r--r--gcc/calls.c51
1 files changed, 40 insertions, 11 deletions
diff --git a/gcc/calls.c b/gcc/calls.c
index 3311d1c..02562dd 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1613,6 +1613,9 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
if (!fndecl || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL)
return;
+ if (TREE_NO_WARNING (exp))
+ return;
+
unsigned nargs = call_expr_nargs (exp);
/* The bound argument to a bounded string function like strncpy. */
@@ -1647,18 +1650,23 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
case BUILT_IN_STPNCPY:
case BUILT_IN_STRNCPY:
- {
- unsigned argno = 2;
- if (argno < nargs)
- bound = CALL_EXPR_ARG (exp, argno);
- break;
- }
+ if (2 < nargs)
+ bound = CALL_EXPR_ARG (exp, 2);
+ break;
case BUILT_IN_STRNDUP:
+ if (1 < nargs)
+ bound = CALL_EXPR_ARG (exp, 1);
+ break;
+
+ case BUILT_IN_STRNLEN:
{
- unsigned argno = 1;
- if (argno < nargs)
- bound = CALL_EXPR_ARG (exp, argno);
+ tree arg = CALL_EXPR_ARG (exp, 0);
+ if (!get_attr_nonstring_decl (arg))
+ get_range_strlen (arg, lenrng);
+
+ if (1 < nargs)
+ bound = CALL_EXPR_ARG (exp, 1);
break;
}
@@ -1674,6 +1682,29 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
get_size_range (bound, bndrng);
}
+ location_t loc = EXPR_LOCATION (exp);
+
+ if (bndrng[0])
+ {
+ /* Diagnose excessive bound prior the adjustment below and
+ regardless of attribute nonstring. */
+ tree maxobjsize = max_object_size ();
+ if (tree_int_cst_lt (maxobjsize, bndrng[0]))
+ {
+ if (tree_int_cst_equal (bndrng[0], bndrng[1]))
+ warning_at (loc, OPT_Wstringop_overflow_,
+ "%K%qD specified bound %E "
+ "exceeds maximum object size %E",
+ exp, fndecl, bndrng[0], maxobjsize);
+ else
+ warning_at (loc, OPT_Wstringop_overflow_,
+ "%K%qD specified bound [%E, %E] "
+ "exceeds maximum object size %E",
+ exp, fndecl, bndrng[0], bndrng[1], maxobjsize);
+ return;
+ }
+ }
+
if (*lenrng)
{
/* Add one for the nul. */
@@ -1766,8 +1797,6 @@ maybe_warn_nonstring_arg (tree fndecl, tree exp)
else if (bound == void_type_node)
bound = NULL_TREE;
- location_t loc = EXPR_LOCATION (exp);
-
bool warned = false;
if (wi::ltu_p (asize, wibnd))