summaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2019-11-22 17:14:17 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2019-11-22 10:14:17 -0700
commit54aa6b58fe2fe73bbe67e0485777e0c410a18673 (patch)
tree11281ae8b5d5a5f2a57ffc60d7d8cfe951a953d8 /gcc/builtins.c
parentb5338fb359ea3480d6ed37bbc52fe2df49b82fb9 (diff)
PR middle-end/83859 - attributes to associate pointer arguments and sizes
gcc/ChangeLog: PR middle-end/83859 * attribs.h (struct attr_access): New. * attribs.c (decl_attributes): Add an informational note. * builtins.c (check_access): Make extern. Consistently set no-warning after issuing a warning. Handle calls through function pointers. Set no-warning. * builtins.h (check_access): Declare. * calls.c (rdwr_access_hash): New type. (rdwr_map): Same. (init_attr_rdwr_indices): New function. (maybe_warn_rdwr_sizes): Same. (initialize_argument_information): Call init_attr_rdwr_indices. Call maybe_warn_rdwr_sizes. (get_size_range): Avoid null argument. * doc/extend.texi (attribute access): Document new attribute. gcc/c-family/ChangeLog: PR middle-end/83859 * c-attribs.c (handle_access_attribute): New function. (c_common_attribute_table): Add new attribute. (get_argument_type): New function. (append_access_attrs): New function. (get_nonnull_operand): Rename... (get_attribute_operand): ...to this. * c-common.c (get_nonnull_operand): Rename... (get_attribute_operand): ...to this. gcc/testsuite/ChangeLog: PR middle-end/83859 * c-c++-common/attr-nonstring-8.c: Adjust text of expected warning. * gcc.dg/Wstringop-overflow-23.c: New test. * gcc.dg/Wstringop-overflow-24.c: New test. * gcc.dg/attr-access-read-only.c: New test. * gcc.dg/attr-access-read-write.c: New test. * gcc.dg/attr-access-read-write-2.c: New test. * gcc.dg/attr-access-write-only.c: New test. From-SVN: r278624
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c215
1 files changed, 154 insertions, 61 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index f8cd4b44fa8..8296d846171 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -3340,7 +3340,7 @@ determine_block_size (tree len, rtx len_rtx,
If the call is successfully verified as safe return true, otherwise
return false. */
-static bool
+bool
check_access (tree exp, tree, tree, tree dstwrite,
tree maxread, tree srcstr, tree dstsize)
{
@@ -3436,16 +3436,26 @@ check_access (tree exp, tree, tree, tree dstwrite,
bool warned;
if (range[0] == range[1])
- warned = warning_at (loc, opt,
- "%K%qD specified size %E "
- "exceeds maximum object size %E",
- exp, func, range[0], maxobjsize);
+ warned = (func
+ ? warning_at (loc, opt,
+ "%K%qD specified size %E "
+ "exceeds maximum object size %E",
+ exp, func, range[0], maxobjsize)
+ : warning_at (loc, opt,
+ "%Kspecified size %E "
+ "exceeds maximum object size %E",
+ exp, range[0], maxobjsize));
else
- warned = warning_at (loc, opt,
- "%K%qD specified size between %E and %E "
- "exceeds maximum object size %E",
- exp, func,
- range[0], range[1], maxobjsize);
+ warned = (func
+ ? warning_at (loc, opt,
+ "%K%qD specified size between %E and %E "
+ "exceeds maximum object size %E",
+ exp, func,
+ range[0], range[1], maxobjsize)
+ : warning_at (loc, opt,
+ "%Kspecified size between %E and %E "
+ "exceeds maximum object size %E",
+ exp, range[0], range[1], maxobjsize));
if (warned)
TREE_NO_WARNING (exp) = true;
@@ -3474,37 +3484,69 @@ check_access (tree exp, tree, tree, tree dstwrite,
location_t loc = tree_nonartificial_location (exp);
loc = expansion_point_location_if_in_system_header (loc);
+ bool warned = false;
if (dstwrite == slen && at_least_one)
{
/* This is a call to strcpy with a destination of 0 size
and a source of unknown length. The call will write
at least one byte past the end of the destination. */
- warning_at (loc, opt,
- "%K%qD writing %E or more bytes into a region "
- "of size %E overflows the destination",
- exp, func, range[0], dstsize);
+ warned = (func
+ ? warning_at (loc, opt,
+ "%K%qD writing %E or more bytes into "
+ "a region of size %E overflows "
+ "the destination",
+ exp, func, range[0], dstsize)
+ : warning_at (loc, opt,
+ "%Kwriting %E or more bytes into "
+ "a region of size %E overflows "
+ "the destination",
+ exp, range[0], dstsize));
}
else if (tree_int_cst_equal (range[0], range[1]))
- warning_n (loc, opt, tree_to_uhwi (range[0]),
- "%K%qD writing %E byte into a region "
- "of size %E overflows the destination",
- "%K%qD writing %E bytes into a region "
- "of size %E overflows the destination",
- exp, func, range[0], dstsize);
+ warned = (func
+ ? warning_n (loc, opt, tree_to_uhwi (range[0]),
+ "%K%qD writing %E byte into a region "
+ "of size %E overflows the destination",
+ "%K%qD writing %E bytes into a region "
+ "of size %E overflows the destination",
+ exp, func, range[0], dstsize)
+ : warning_n (loc, opt, tree_to_uhwi (range[0]),
+ "%Kwriting %E byte into a region "
+ "of size %E overflows the destination",
+ "%Kwriting %E bytes into a region "
+ "of size %E overflows the destination",
+ exp, range[0], dstsize));
else if (tree_int_cst_sign_bit (range[1]))
{
/* Avoid printing the upper bound if it's invalid. */
- warning_at (loc, opt,
- "%K%qD writing %E or more bytes into a region "
- "of size %E overflows the destination",
- exp, func, range[0], dstsize);
+ warned = (func
+ ? warning_at (loc, opt,
+ "%K%qD writing %E or more bytes into "
+ "a region of size %E overflows "
+ "the destination",
+ exp, func, range[0], dstsize)
+ : warning_at (loc, opt,
+ "%Kwriting %E or more bytes into "
+ "a region of size %E overflows "
+ "the destination",
+ exp, range[0], dstsize));
}
else
- warning_at (loc, opt,
- "%K%qD writing between %E and %E bytes into "
- "a region of size %E overflows the destination",
- exp, func, range[0], range[1],
- dstsize);
+ warned = (func
+ ? warning_at (loc, opt,
+ "%K%qD writing between %E and %E bytes "
+ "into a region of size %E overflows "
+ "the destination",
+ exp, func, range[0], range[1],
+ dstsize)
+ : warning_at (loc, opt,
+ "%Kwriting between %E and %E bytes "
+ "into a region of size %E overflows "
+ "the destination",
+ exp, range[0], range[1],
+ dstsize));
+ if (warned)
+ TREE_NO_WARNING (exp) = true;
/* Return error when an overflow has been detected. */
return false;
@@ -3527,21 +3569,36 @@ check_access (tree exp, tree, tree, tree dstwrite,
if (TREE_NO_WARNING (exp))
return false;
+ bool warned = false;
+
/* Warn about crazy big sizes first since that's more
likely to be meaningful than saying that the bound
is greater than the object size if both are big. */
if (range[0] == range[1])
- warning_at (loc, opt,
- "%K%qD specified bound %E "
- "exceeds maximum object size %E",
- exp, func,
- range[0], maxobjsize);
+ warned = (func
+ ? warning_at (loc, opt,
+ "%K%qD specified bound %E "
+ "exceeds maximum object size %E",
+ exp, func, range[0], maxobjsize)
+ : warning_at (loc, opt,
+ "%Kspecified bound %E "
+ "exceeds maximum object size %E",
+ exp, range[0], maxobjsize));
else
- warning_at (loc, opt,
- "%K%qD specified bound between %E and %E "
- "exceeds maximum object size %E",
- exp, func,
- range[0], range[1], maxobjsize);
+ warned = (func
+ ? warning_at (loc, opt,
+ "%K%qD specified bound between "
+ "%E and %E exceeds maximum object "
+ "size %E",
+ exp, func,
+ range[0], range[1], maxobjsize)
+ : warning_at (loc, opt,
+ "%Kspecified bound between "
+ "%E and %E exceeds maximum object "
+ "size %E",
+ exp, range[0], range[1], maxobjsize));
+ if (warned)
+ TREE_NO_WARNING (exp) = true;
return false;
}
@@ -3551,18 +3608,34 @@ check_access (tree exp, tree, tree, tree dstwrite,
if (TREE_NO_WARNING (exp))
return false;
+ bool warned = false;
+
if (tree_int_cst_equal (range[0], range[1]))
- warning_at (loc, opt,
- "%K%qD specified bound %E "
- "exceeds destination size %E",
- exp, func,
- range[0], dstsize);
+ warned = (func
+ ? warning_at (loc, opt,
+ "%K%qD specified bound %E "
+ "exceeds destination size %E",
+ exp, func,
+ range[0], dstsize)
+ : warning_at (loc, opt,
+ "%Kspecified bound %E "
+ "exceeds destination size %E",
+ exp, range[0], dstsize));
else
- warning_at (loc, opt,
- "%K%qD specified bound between %E and %E "
- "exceeds destination size %E",
- exp, func,
- range[0], range[1], dstsize);
+ warned = (func
+ ? warning_at (loc, opt,
+ "%K%qD specified bound between %E "
+ "and %E exceeds destination size %E",
+ exp, func,
+ range[0], range[1], dstsize)
+ : warning_at (loc, opt,
+ "%Kspecified bound between %E "
+ "and %E exceeds destination size %E",
+ exp,
+ range[0], range[1], dstsize));
+ if (warned)
+ TREE_NO_WARNING (exp) = true;
+
return false;
}
}
@@ -3577,26 +3650,46 @@ check_access (tree exp, tree, tree, tree dstwrite,
if (TREE_NO_WARNING (exp))
return false;
+ bool warned = false;
location_t loc = tree_nonartificial_location (exp);
+ loc = expansion_point_location_if_in_system_header (loc);
if (tree_int_cst_equal (range[0], range[1]))
- warning_n (loc, opt, tree_to_uhwi (range[0]),
- "%K%qD reading %E byte from a region of size %E",
- "%K%qD reading %E bytes from a region of size %E",
- exp, func, range[0], slen);
+ warned = (func
+ ? warning_n (loc, opt, tree_to_uhwi (range[0]),
+ "%K%qD reading %E byte from a region of size %E",
+ "%K%qD reading %E bytes from a region of size %E",
+ exp, func, range[0], slen)
+ : warning_n (loc, opt, tree_to_uhwi (range[0]),
+ "%Kreading %E byte from a region of size %E",
+ "%Kreading %E bytes from a region of size %E",
+ exp, range[0], slen));
else if (tree_int_cst_sign_bit (range[1]))
{
/* Avoid printing the upper bound if it's invalid. */
- warning_at (loc, opt,
- "%K%qD reading %E or more bytes from a region "
- "of size %E",
- exp, func, range[0], slen);
+ warned = (func
+ ? warning_at (loc, opt,
+ "%K%qD reading %E or more bytes from a region "
+ "of size %E",
+ exp, func, range[0], slen)
+ : warning_at (loc, opt,
+ "%Kreading %E or more bytes from a region "
+ "of size %E",
+ exp, range[0], slen));
}
else
- warning_at (loc, opt,
- "%K%qD reading between %E and %E bytes from a region "
- "of size %E",
- exp, func, range[0], range[1], slen);
+ warned = (func
+ ? warning_at (loc, opt,
+ "%K%qD reading between %E and %E bytes from "
+ "a region of size %E",
+ exp, func, range[0], range[1], slen)
+ : warning_at (loc, opt,
+ "%Kreading between %E and %E bytes from "
+ "a region of size %E",
+ exp, range[0], range[1], slen));
+ if (warned)
+ TREE_NO_WARNING (exp) = true;
+
return false;
}