diff options
author | Martin Sebor <msebor@redhat.com> | 2020-06-04 16:06:10 -0600 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2020-06-04 16:08:32 -0600 |
commit | b825a22890740f341eae566af27e18e528cd29a7 (patch) | |
tree | b614b6b24e6395784b9eb80af79352ce9bca555f /gcc/builtins.c | |
parent | 2cbc99d18dc411ac3fdef94e22ce86859806e63c (diff) | |
download | gcc-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.c | 126 |
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; |