aboutsummaryrefslogtreecommitdiff
path: root/gcc/builtins.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-06-04 16:06:10 -0600
committerMartin Sebor <msebor@redhat.com>2020-06-04 16:08:32 -0600
commitb825a22890740f341eae566af27e18e528cd29a7 (patch)
treeb614b6b24e6395784b9eb80af79352ce9bca555f /gcc/builtins.c
parent2cbc99d18dc411ac3fdef94e22ce86859806e63c (diff)
downloadgcc-b825a22890740f341eae566af27e18e528cd29a7.zip
gcc-b825a22890740f341eae566af27e18e528cd29a7.tar.gz
gcc-b825a22890740f341eae566af27e18e528cd29a7.tar.bz2
Implement a solution for PR middle-end/10138 and PR middle-end/95136.
PR middle-end/10138 - warn for uninitialized arrays passed as const arguments PR middle-end/95136 - missing -Wuninitialized on an array access with a variable offset gcc/c-family/ChangeLog: PR middle-end/10138 PR middle-end/95136 * c-attribs.c (append_access_attrs): Handle attr_access::none. (handle_access_attribute): Same. gcc/ChangeLog: PR middle-end/10138 PR middle-end/95136 * attribs.c (init_attr_rdwr_indices): Move function here. * attribs.h (rdwr_access_hash, rdwr_map): Define. (attr_access): Add 'none'. (init_attr_rdwr_indices): Declared function. * builtins.c (warn_for_access)): New function. (check_access): Call it. * builtins.h (checK-access): Add an optional argument. * calls.c (rdwr_access_hash, rdwr_map): Move to attribs.h. (init_attr_rdwr_indices): Declare extern. (append_attrname): Handle attr_access::none. (maybe_warn_rdwr_sizes): Same. (initialize_argument_information): Update comments. * doc/extend.texi (attribute access): Document 'none'. * tree-ssa-uninit.c (struct wlimits): New. (maybe_warn_operand): New function. (maybe_warn_pass_by_reference): Same. (warn_uninitialized_vars): Refactor code into maybe_warn_operand. Also call for function calls. (pass_late_warn_uninitialized::execute): Adjust comments. (execute_early_warn_uninitialized): Same. gcc/testsuite/ChangeLog: PR middle-end/10138 PR middle-end/95136 * c-c++-common/Wsizeof-pointer-memaccess1.c: Prune out valid Wuninitialized. * c-c++-common/uninit-pr51010.c: Adjust expected warning format. * c-c++-common/goacc/uninit-dim-clause.c: Same. * c-c++-common/goacc/uninit-firstprivate-clause.c: Same. * c-c++-common/goacc/uninit-if-clause.c: Same. * c-c++-common/gomp/pr70550-1.c: Same. * c-c++-common/gomp/pr70550-2.c: Adjust. * g++.dg/20090107-1.C: Same. * g++.dg/20090121-1.C: Same. * g++.dg/ext/attr-access.C: Avoid -Wuninitialized. * gcc.dg/tree-ssa/forwprop-6.c: Prune out -Wuninitialized. * gcc.dg/Warray-bounds-52.c: Prune out valid -Wuninitialized. * gcc.dg/Warray-bounds-53.c: Same. * gcc.dg/Warray-bounds-54.c: Same. * gcc.dg/Wstringop-overflow-33.c: New test. * gcc.dg/attr-access-none.c: New test. * gcc.dg/attr-access-read-only.c: Adjust. * gcc.dg/attr-access-read-write.c: Same. * gcc.dg/attr-access-write-only.c: Same. * gcc.dg/pr71581.c: Adjust text of expected warning. * gcc.dg/uninit-15.c: Same. * gcc.dg/uninit-32.c: New test. * gcc.dg/uninit-33.c: New test. * gcc.dg/uninit-34.c: New test. * gcc.dg/uninit-36.c: New test. * gcc.dg/uninit-B-O0.c: Adjust text of expected warning. * gcc.dg/uninit-I-O0.c: Same. * gcc.dg/uninit-pr19430-O0.c: Same. * gcc.dg/uninit-pr19430.c: Same. * gcc.dg/uninit-pr95136.c: New test. * gfortran.dg/assignment_4.f90: Expect -Wuninitialized. * gfortran.dg/goacc/uninit-dim-clause.f95: Adjust text of expected warning. * gfortran.dg/goacc/uninit-firstprivate-clause.f95 * gfortran.dg/goacc/uninit-if-clause.f95 * gfortran.dg/pr66545_2.f90
Diffstat (limited to 'gcc/builtins.c')
-rw-r--r--gcc/builtins.c126
1 files changed, 90 insertions, 36 deletions
diff --git a/gcc/builtins.c b/gcc/builtins.c
index f7bb87e..667d36c 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -3310,6 +3310,90 @@ determine_block_size (tree len, rtx len_rtx,
GET_MODE_MASK (GET_MODE (len_rtx)));
}
+/* For an expression EXP issue an access warning controlled by option OPT
+ with access to a region SLEN bytes in size in the RANGE of sizes. */
+
+static bool
+warn_for_access (location_t loc, tree func, tree exp, int opt, tree range[2],
+ tree slen, bool access)
+{
+ bool warned = false;
+
+ if (access)
+ {
+ if (tree_int_cst_equal (range[0], range[1]))
+ 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. */
+ 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
+ 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));
+
+ return warned;
+ }
+
+ if (tree_int_cst_equal (range[0], range[1]))
+ warned = (func
+ ? warning_n (loc, opt, tree_to_uhwi (range[0]),
+ "%K%qD epecting %E byte in a region of size %E",
+ "%K%qD expecting %E bytes in a region of size %E",
+ exp, func, range[0], slen)
+ : warning_n (loc, opt, tree_to_uhwi (range[0]),
+ "%Kexpecting %E byte in a region of size %E",
+ "%Kexpecting %E bytes in 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. */
+ warned = (func
+ ? warning_at (loc, opt,
+ "%K%qD expecting %E or more bytes in a region "
+ "of size %E",
+ exp, func, range[0], slen)
+ : warning_at (loc, opt,
+ "%Kexpecting %E or more bytes in a region "
+ "of size %E",
+ exp, range[0], slen));
+ }
+ else
+ warned = (func
+ ? warning_at (loc, opt,
+ "%K%qD expecting between %E and %E bytes in "
+ "a region of size %E",
+ exp, func, range[0], range[1], slen)
+ : warning_at (loc, opt,
+ "%Kexpectting between %E and %E bytes in "
+ "a region of size %E",
+ exp, range[0], range[1], slen));
+ return warned;
+}
+
/* Try to verify that the sizes and lengths of the arguments to a string
manipulation function given by EXP are within valid bounds and that
the operation does not lead to buffer overflow or read past the end.
@@ -3336,12 +3420,16 @@ determine_block_size (tree len, rtx len_rtx,
When DSTWRITE is null LEN is checked to verify that it doesn't exceed
SIZE_MAX.
+ ACCESS is true for accesses, false for simple size checks in calls
+ to functions that neither read from nor write to the region.
+
If the call is successfully verified as safe return true, otherwise
return false. */
bool
check_access (tree exp, tree, tree, tree dstwrite,
- tree maxread, tree srcstr, tree dstsize)
+ tree maxread, tree srcstr, tree dstsize,
+ bool access /* = true */)
{
int opt = OPT_Wstringop_overflow_;
@@ -3649,44 +3737,10 @@ 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]))
- 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. */
- 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
- 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)
+ if (warn_for_access (loc, func, exp, opt, range, slen, access))
TREE_NO_WARNING (exp) = true;
return false;