[PR109071,PR85788,PR88771,PR106762,PR108770,PR115274,PR117179] During array out-of-bound checking or -Wstringop-* warning checking, the "move_history" that was attached to the gimple statement is used to form a sequence of diagnostic events that are added to the corresponding rich location to be used to report the warning message.
PR tree-optimization/109071 PR tree-optimization/85788 PR tree-optimization/88771 PR tree-optimization/106762 PR tree-optimization/108770 PR tree-optimization/115274 PR tree-optimization/117179 gcc/ChangeLog: * Makefile.in (OBJS): Add move-history-rich-location.o. * gimple-array-bounds.cc (check_out_of_bounds_and_warn): Add one new parameter. Use rich location with details for warning_at. (array_bounds_checker::check_array_ref): Use rich location with ditails for warning_at. (array_bounds_checker::check_mem_ref): Add one new parameter. Use rich location with details for warning_at. (array_bounds_checker::check_addr_expr): Use rich location with move_history_diagnostic_path for warning_at. (array_bounds_checker::check_array_bounds): Call check_mem_ref with one more parameter. * gimple-array-bounds.h: Update prototype for check_mem_ref. * gimple-ssa-warn-restrict.cc (maybe_diag_access_bounds): Use rich location with details for warning_at. * gimple-ssa-warn-access.cc (warn_string_no_nul): Likewise. (maybe_warn_nonstring_arg): Likewise. (maybe_warn_for_bound): Likewise. (warn_for_access): Likewise. (check_access): Likewise. (pass_waccess::check_strncat): Likewise. (pass_waccess::maybe_check_access_sizes): Likewise. * move-history-rich-location.cc: New file. * move-history-rich-location.h: New file. gcc/testsuite/ChangeLog: * gcc.dg/pr109071.c: New test. * gcc.dg/pr109071_1.c: New test. * gcc.dg/pr109071_2.c: New test. * gcc.dg/pr109071_3.c: New test. * gcc.dg/pr109071_4.c: New test. * gcc.dg/pr109071_5.c: New test. * gcc.dg/pr109071_6.c: New test. --- gcc/Makefile.in | 1 + gcc/gimple-array-bounds.cc | 39 +++++---- gcc/gimple-array-bounds.h | 2 +- gcc/gimple-ssa-warn-access.cc | 131 +++++++++++++++++------------- gcc/gimple-ssa-warn-restrict.cc | 25 +++--- gcc/move-history-rich-location.cc | 56 +++++++++++++ gcc/move-history-rich-location.h | 65 +++++++++++++++ gcc/testsuite/gcc.dg/pr109071.c | 43 ++++++++++ gcc/testsuite/gcc.dg/pr109071_1.c | 36 ++++++++ gcc/testsuite/gcc.dg/pr109071_2.c | 50 ++++++++++++ gcc/testsuite/gcc.dg/pr109071_3.c | 42 ++++++++++ gcc/testsuite/gcc.dg/pr109071_4.c | 41 ++++++++++ gcc/testsuite/gcc.dg/pr109071_5.c | 33 ++++++++ gcc/testsuite/gcc.dg/pr109071_6.c | 49 +++++++++++ 14 files changed, 530 insertions(+), 83 deletions(-) create mode 100644 gcc/move-history-rich-location.cc create mode 100644 gcc/move-history-rich-location.h create mode 100644 gcc/testsuite/gcc.dg/pr109071.c create mode 100644 gcc/testsuite/gcc.dg/pr109071_1.c create mode 100644 gcc/testsuite/gcc.dg/pr109071_2.c create mode 100644 gcc/testsuite/gcc.dg/pr109071_3.c create mode 100644 gcc/testsuite/gcc.dg/pr109071_4.c create mode 100644 gcc/testsuite/gcc.dg/pr109071_5.c create mode 100644 gcc/testsuite/gcc.dg/pr109071_6.c diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 29663be1d48..0a4bde23dc0 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1621,6 +1621,7 @@ OBJS = \ mcf.o \ mode-switching.o \ modulo-sched.o \ + move-history-rich-location.o \ multiple_target.o \ omp-offload.o \ omp-expand.o \ diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc index 22286cbb4cc..79236e6b9c7 100644 --- a/gcc/gimple-array-bounds.cc +++ b/gcc/gimple-array-bounds.cc @@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ +#define INCLUDE_MEMORY #include "config.h" #include "system.h" #include "coretypes.h" @@ -31,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-dfa.h" #include "fold-const.h" #include "diagnostic-core.h" +#include "move-history-rich-location.h" #include "intl.h" #include "tree-vrp.h" #include "alloc-pool.h" @@ -262,6 +264,7 @@ get_up_bounds_for_array_ref (tree ref, tree *decl, static bool check_out_of_bounds_and_warn (location_t location, tree ref, + gimple *stmt, tree low_sub_org, tree low_sub, tree up_sub, tree up_bound, tree up_bound_p1, const irange *vr, @@ -275,12 +278,13 @@ check_out_of_bounds_and_warn (location_t location, tree ref, bool warned = false; *out_of_bound = false; + rich_location_with_details richloc (location, stmt); /* Empty array. */ if (up_bound && tree_int_cst_equal (low_bound, up_bound_p1)) { *out_of_bound = true; if (for_array_bound) - warned = warning_at (location, OPT_Warray_bounds_, + warned = warning_at (&richloc, OPT_Warray_bounds_, "array subscript %E is outside array" " bounds of %qT", low_sub_org, artype); } @@ -299,7 +303,7 @@ check_out_of_bounds_and_warn (location_t location, tree ref, { *out_of_bound = true; if (for_array_bound) - warned = warning_at (location, OPT_Warray_bounds_, + warned = warning_at (&richloc, OPT_Warray_bounds_, "array subscript [%E, %E] is outside " "array bounds of %qT", low_sub, up_sub, artype); @@ -313,7 +317,7 @@ check_out_of_bounds_and_warn (location_t location, tree ref, { *out_of_bound = true; if (for_array_bound) - warned = warning_at (location, OPT_Warray_bounds_, + warned = warning_at (&richloc, OPT_Warray_bounds_, "array subscript %E is above array bounds of %qT", up_sub, artype); } @@ -322,7 +326,7 @@ check_out_of_bounds_and_warn (location_t location, tree ref, { *out_of_bound = true; if (for_array_bound) - warned = warning_at (location, OPT_Warray_bounds_, + warned = warning_at (&richloc, OPT_Warray_bounds_, "array subscript %E is below array bounds of %qT", low_sub, artype); } @@ -388,15 +392,16 @@ array_bounds_checker::check_array_ref (location_t location, tree ref, } } - warned = check_out_of_bounds_and_warn (location, ref, + warned = check_out_of_bounds_and_warn (location, ref, stmt, low_sub_org, low_sub, up_sub, up_bound, up_bound_p1, &vr, ignore_off_by_one, warn_array_bounds, &out_of_bound); + rich_location_with_details richloc (location, stmt); if (!warned && sam == special_array_member::int_0) - warned = warning_at (location, OPT_Wzero_length_bounds, + warned = warning_at (&richloc, OPT_Wzero_length_bounds, (TREE_CODE (low_sub) == INTEGER_CST ? G_("array subscript %E is outside the bounds " "of an interior zero-length array %qT") @@ -420,7 +425,7 @@ array_bounds_checker::check_array_ref (location_t location, tree ref, && DECL_NOT_FLEXARRAY (afield_decl)) { bool warned1 - = warning_at (location, OPT_Wstrict_flex_arrays, + = warning_at (&richloc, OPT_Wstrict_flex_arrays, "trailing array %qT should not be used as " "a flexible array member", artype); @@ -478,6 +483,7 @@ array_bounds_checker::check_array_ref (location_t location, tree ref, bool array_bounds_checker::check_mem_ref (location_t location, tree ref, + gimple *stmt, bool ignore_off_by_one) { if (warning_suppressed_p (ref, OPT_Warray_bounds_)) @@ -576,16 +582,17 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref, } } + rich_location_with_details richloc (location, stmt); bool warned = false; if (lboob) { if (offrange[0] == offrange[1]) - warned = warning_at (location, OPT_Warray_bounds_, + warned = warning_at (&richloc, OPT_Warray_bounds_, "array subscript %wi is outside array bounds " "of %qT", offrange[0].to_shwi (), reftype); else - warned = warning_at (location, OPT_Warray_bounds_, + warned = warning_at (&richloc, OPT_Warray_bounds_, "array subscript [%wi, %wi] is outside " "array bounds of %qT", offrange[0].to_shwi (), @@ -599,8 +606,7 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref, it were an untyped array of bytes. */ backtype = build_array_type_nelts (unsigned_char_type_node, aref.sizrng[1].to_uhwi ()); - - warned = warning_at (location, OPT_Warray_bounds_, + warned = warning_at (&richloc, OPT_Warray_bounds_, "array subscript %<%T[%wi]%> is partly " "outside array bounds of %qT", axstype, offrange[0].to_shwi (), backtype); @@ -623,7 +629,7 @@ array_bounds_checker::check_mem_ref (location_t location, tree ref, { HOST_WIDE_INT tmpidx = (aref.offmax[i] / eltsize).to_shwi (); - if (warning_at (location, OPT_Warray_bounds_, + if (warning_at (&richloc, OPT_Warray_bounds_, "intermediate array offset %wi is outside array bounds " "of %qT", tmpidx, reftype)) { @@ -656,7 +662,7 @@ array_bounds_checker::check_addr_expr (location_t location, tree t, ignore_off_by_one = false; } else if (TREE_CODE (t) == MEM_REF) - warned = check_mem_ref (location, t, ignore_off_by_one); + warned = check_mem_ref (location, t, stmt, ignore_off_by_one); if (warned) suppress_warning (t, OPT_Warray_bounds_); @@ -692,6 +698,7 @@ array_bounds_checker::check_addr_expr (location_t location, tree t, if (!mem_ref_offset (t).is_constant (&idx)) return; + rich_location_with_details richloc (location, stmt); bool warned = false; idx = wi::sdiv_trunc (idx, wi::to_offset (el_sz)); if (idx < 0) @@ -702,7 +709,7 @@ array_bounds_checker::check_addr_expr (location_t location, tree t, dump_generic_expr (MSG_NOTE, TDF_SLIM, t); fprintf (dump_file, "\n"); } - warned = warning_at (location, OPT_Warray_bounds_, + warned = warning_at (&richloc, OPT_Warray_bounds_, "array subscript %wi is below " "array bounds of %qT", idx.to_shwi (), TREE_TYPE (tem)); @@ -716,7 +723,7 @@ array_bounds_checker::check_addr_expr (location_t location, tree t, dump_generic_expr (MSG_NOTE, TDF_SLIM, t); fprintf (dump_file, "\n"); } - warned = warning_at (location, OPT_Warray_bounds_, + warned = warning_at (&richloc, OPT_Warray_bounds_, "array subscript %wu is above " "array bounds of %qT", idx.to_uhwi (), TREE_TYPE (tem)); @@ -811,7 +818,7 @@ array_bounds_checker::check_array_bounds (tree *tp, int *walk_subtree, warned = checker->check_array_ref (location, t, wi->stmt, false/*ignore_off_by_one*/); else if (TREE_CODE (t) == MEM_REF) - warned = checker->check_mem_ref (location, t, + warned = checker->check_mem_ref (location, t, wi->stmt, false /*ignore_off_by_one*/); else if (TREE_CODE (t) == ADDR_EXPR) { diff --git a/gcc/gimple-array-bounds.h b/gcc/gimple-array-bounds.h index bdf8a3428a6..611bcdf17e3 100644 --- a/gcc/gimple-array-bounds.h +++ b/gcc/gimple-array-bounds.h @@ -33,7 +33,7 @@ public: private: static tree check_array_bounds (tree *tp, int *walk_subtree, void *data); bool check_array_ref (location_t, tree, gimple *, bool ignore_off_by_one); - bool check_mem_ref (location_t, tree, bool ignore_off_by_one); + bool check_mem_ref (location_t, tree, gimple *, bool ignore_off_by_one); void check_addr_expr (location_t, tree, gimple *); void get_value_range (irange &r, const_tree op, gimple *); diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc index 305b63567fe..aef098fe80b 100644 --- a/gcc/gimple-ssa-warn-access.cc +++ b/gcc/gimple-ssa-warn-access.cc @@ -57,6 +57,7 @@ #include "pointer-query.h" #include "pretty-print-markup.h" #include "gcc-urlifier.h" +#include "move-history-rich-location.h" /* Return true if tree node X has an associated location. */ @@ -169,17 +170,19 @@ warn_string_no_nul (location_t loc, GimpleOrTree expr, const char *fname, if (expr) { tree func = get_callee_fndecl (expr); + rich_location_with_details richloc (loc, expr); + if (bndrng) { if (wi::ltu_p (maxsiz, bndrng[0])) - warned = warning_at (loc, opt, + warned = warning_at (&richloc, opt, "%qD specified bound %s exceeds " "maximum object size %E", func, bndstr, maxobjsize); else { bool maybe = wi::to_wide (size) == bndrng[0]; - warned = warning_at (loc, opt, + warned = warning_at (&richloc, opt, exact ? G_("%qD specified bound %s exceeds " "the size %E of unterminated array") @@ -194,7 +197,7 @@ warn_string_no_nul (location_t loc, GimpleOrTree expr, const char *fname, } } else - warned = warning_at (loc, opt, + warned = warning_at (&richloc, opt, "%qD argument missing terminating nul", func); } @@ -486,14 +489,16 @@ maybe_warn_nonstring_arg (tree fndecl, GimpleOrTree exp) tree maxobjsize = max_object_size (); if (tree_int_cst_lt (maxobjsize, bndrng[0])) { + rich_location_with_details richloc (loc, exp); + bool warned = false; if (tree_int_cst_equal (bndrng[0], bndrng[1])) - warned = warning_at (loc, OPT_Wstringop_overread, + warned = warning_at (&richloc, OPT_Wstringop_overread, "%qD specified bound %E " "exceeds maximum object size %E", fndecl, bndrng[0], maxobjsize); else - warned = warning_at (loc, OPT_Wstringop_overread, + warned = warning_at (&richloc, OPT_Wstringop_overread, "%qD specified bound [%E, %E] " "exceeds maximum object size %E", fndecl, bndrng[0], bndrng[1], @@ -645,20 +650,21 @@ maybe_warn_nonstring_arg (tree fndecl, GimpleOrTree exp) auto_diagnostic_group d; if (wi::ltu_p (asize, wibnd)) { + rich_location_with_details richloc (loc, exp); if (bndrng[0] == bndrng[1]) - warned = warning_at (loc, OPT_Wstringop_overread, + warned = warning_at (&richloc, OPT_Wstringop_overread, "%qD argument %i declared attribute " "%<nonstring%> is smaller than the specified " "bound %wu", fndecl, argno + 1, wibnd.to_uhwi ()); else if (wi::ltu_p (asize, wi::to_offset (bndrng[0]))) - warned = warning_at (loc, OPT_Wstringop_overread, + warned = warning_at (&richloc, OPT_Wstringop_overread, "%qD argument %i declared attribute " "%<nonstring%> is smaller than " "the specified bound [%E, %E]", fndecl, argno + 1, bndrng[0], bndrng[1]); else - warned = warning_at (loc, OPT_Wstringop_overread, + warned = warning_at (&richloc, OPT_Wstringop_overread, "%qD argument %i declared attribute " "%<nonstring%> may be smaller than " "the specified bound [%E, %E]", @@ -730,16 +736,17 @@ maybe_warn_for_bound (opt_code opt, location_t loc, GimpleOrTree exp, tree func, auto_diagnostic_group d; if (tree_int_cst_lt (maxobjsize, bndrng[0])) { + rich_location_with_details richloc (loc, exp); if (bndrng[0] == bndrng[1]) warned = (func - ? warning_at (loc, opt, + ? warning_at (&richloc, opt, (maybe ? G_("%qD specified bound %E may " "exceed maximum object size %E") : G_("%qD specified bound %E " "exceeds maximum object size %E")), func, bndrng[0], maxobjsize) - : warning_at (loc, opt, + : warning_at (&richloc, opt, (maybe ? G_("specified bound %E may " "exceed maximum object size %E") @@ -748,7 +755,7 @@ maybe_warn_for_bound (opt_code opt, location_t loc, GimpleOrTree exp, tree func, bndrng[0], maxobjsize)); else warned = (func - ? warning_at (loc, opt, + ? warning_at (&richloc, opt, (maybe ? G_("%qD specified bound [%E, %E] may " "exceed maximum object size %E") @@ -756,7 +763,7 @@ maybe_warn_for_bound (opt_code opt, location_t loc, GimpleOrTree exp, tree func, "exceeds maximum object size %E")), func, bndrng[0], bndrng[1], maxobjsize) - : warning_at (loc, opt, + : warning_at (&richloc, opt, (maybe ? G_("specified bound [%E, %E] may " "exceed maximum object size %E") @@ -767,37 +774,43 @@ maybe_warn_for_bound (opt_code opt, location_t loc, GimpleOrTree exp, tree func, else if (!size || tree_int_cst_le (bndrng[0], size)) return false; else if (tree_int_cst_equal (bndrng[0], bndrng[1])) - warned = (func - ? warning_at (loc, opt, + { + rich_location_with_details richloc (loc, exp); + warned = (func + ? warning_at (&richloc, opt, (maybe ? G_("%qD specified bound %E may exceed " "source size %E") : G_("%qD specified bound %E exceeds " "source size %E")), func, bndrng[0], size) - : warning_at (loc, opt, + : warning_at (&richloc, opt, (maybe ? G_("specified bound %E may exceed " "source size %E") : G_("specified bound %E exceeds " "source size %E")), bndrng[0], size)); + } else - warned = (func - ? warning_at (loc, opt, + { + rich_location_with_details richloc (loc, exp); + warned = (func + ? warning_at (&richloc, opt, (maybe ? G_("%qD specified bound [%E, %E] may " "exceed source size %E") : G_("%qD specified bound [%E, %E] exceeds " "source size %E")), func, bndrng[0], bndrng[1], size) - : warning_at (loc, opt, + : warning_at (&richloc, opt, (maybe ? G_("specified bound [%E, %E] may exceed " "source size %E") : G_("specified bound [%E, %E] exceeds " "source size %E")), bndrng[0], bndrng[1], size)); + } if (warned) { if (pad && pad->src.ref @@ -811,6 +824,7 @@ maybe_warn_for_bound (opt_code opt, location_t loc, GimpleOrTree exp, tree func, } bool maybe = pad && pad->dst.phi (); + rich_location_with_details richloc (loc, exp); if (maybe) { /* Issue a "maybe" warning only if the PHI refers to objects @@ -824,14 +838,14 @@ maybe_warn_for_bound (opt_code opt, location_t loc, GimpleOrTree exp, tree func, { if (bndrng[0] == bndrng[1]) warned = (func - ? warning_at (loc, opt, + ? warning_at (&richloc, opt, (maybe ? G_("%qD specified size %E may " "exceed maximum object size %E") : G_("%qD specified size %E " "exceeds maximum object size %E")), func, bndrng[0], maxobjsize) - : warning_at (loc, opt, + : warning_at (&richloc, opt, (maybe ? G_("specified size %E may exceed " "maximum object size %E") @@ -840,14 +854,14 @@ maybe_warn_for_bound (opt_code opt, location_t loc, GimpleOrTree exp, tree func, bndrng[0], maxobjsize)); else warned = (func - ? warning_at (loc, opt, + ? warning_at (&richloc, opt, (maybe ? G_("%qD specified size between %E and %E " "may exceed maximum object size %E") : G_("%qD specified size between %E and %E " "exceeds maximum object size %E")), func, bndrng[0], bndrng[1], maxobjsize) - : warning_at (loc, opt, + : warning_at (&richloc, opt, (maybe ? G_("specified size between %E and %E " "may exceed maximum object size %E") @@ -859,14 +873,14 @@ maybe_warn_for_bound (opt_code opt, location_t loc, GimpleOrTree exp, tree func, return false; else if (tree_int_cst_equal (bndrng[0], bndrng[1])) warned = (func - ? warning_at (loc, opt, + ? warning_at (&richloc, opt, (maybe ? G_("%qD specified bound %E may exceed " "destination size %E") : G_("%qD specified bound %E exceeds " "destination size %E")), func, bndrng[0], size) - : warning_at (loc, opt, + : warning_at (&richloc, opt, (maybe ? G_("specified bound %E may exceed " "destination size %E") @@ -875,14 +889,14 @@ maybe_warn_for_bound (opt_code opt, location_t loc, GimpleOrTree exp, tree func, bndrng[0], size)); else warned = (func - ? warning_at (loc, opt, + ? warning_at (&richloc, opt, (maybe ? G_("%qD specified bound [%E, %E] may exceed " "destination size %E") : G_("%qD specified bound [%E, %E] exceeds " "destination size %E")), func, bndrng[0], bndrng[1], size) - : warning_at (loc, opt, + : warning_at (&richloc, opt, (maybe ? G_("specified bound [%E, %E] exceeds " "destination size %E") @@ -933,11 +947,13 @@ warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt, { bool warned = false; + rich_location_with_details richloc (loc, exp); + if (write && read) { if (tree_int_cst_equal (range[0], range[1])) warned = (func - ? warning_n (loc, opt, tree_to_uhwi (range[0]), + ? warning_n (&richloc, opt, tree_to_uhwi (range[0]), (maybe ? G_("%qD may access %E byte in a region " "of size %E") @@ -949,7 +965,7 @@ warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt, : G_ ("%qD accessing %E bytes in a region " "of size %E")), func, range[0], size) - : warning_n (loc, opt, tree_to_uhwi (range[0]), + : warning_n (&richloc, opt, tree_to_uhwi (range[0]), (maybe ? G_("may access %E byte in a region " "of size %E") @@ -965,14 +981,14 @@ warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt, { /* Avoid printing the upper bound if it's invalid. */ warned = (func - ? warning_at (loc, opt, + ? warning_at (&richloc, opt, (maybe ? G_("%qD may access %E or more bytes " "in a region of size %E") : G_("%qD accessing %E or more bytes " "in a region of size %E")), func, range[0], size) - : warning_at (loc, opt, + : warning_at (&richloc, opt, (maybe ? G_("may access %E or more bytes " "in a region of size %E") @@ -982,14 +998,14 @@ warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt, } else warned = (func - ? warning_at (loc, opt, + ? warning_at (&richloc, opt, (maybe ? G_("%qD may access between %E and %E " "bytes in a region of size %E") : G_("%qD accessing between %E and %E " "bytes in a region of size %E")), func, range[0], range[1], size) - : warning_at (loc, opt, + : warning_at (&richloc, opt, (maybe ? G_("may access between %E and %E bytes " "in a region of size %E") @@ -1003,7 +1019,7 @@ warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt, { if (tree_int_cst_equal (range[0], range[1])) warned = (func - ? warning_n (loc, opt, tree_to_uhwi (range[0]), + ? warning_n (&richloc, opt, tree_to_uhwi (range[0]), (maybe ? G_("%qD may write %E byte into a region " "of size %E") @@ -1015,7 +1031,7 @@ warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt, : G_("%qD writing %E bytes into a region " "of size %E overflows the destination")), func, range[0], size) - : warning_n (loc, opt, tree_to_uhwi (range[0]), + : warning_n (&richloc, opt, tree_to_uhwi (range[0]), (maybe ? G_("may write %E byte into a region " "of size %E") @@ -1031,7 +1047,7 @@ warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt, { /* Avoid printing the upper bound if it's invalid. */ warned = (func - ? warning_at (loc, opt, + ? warning_at (&richloc, opt, (maybe ? G_("%qD may write %E or more bytes " "into a region of size %E") @@ -1039,7 +1055,7 @@ warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt, "into a region of size %E overflows " "the destination")), func, range[0], size) - : warning_at (loc, opt, + : warning_at (&richloc, opt, (maybe ? G_("may write %E or more bytes into " "a region of size %E") @@ -1050,7 +1066,7 @@ warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt, } else warned = (func - ? warning_at (loc, opt, + ? warning_at (&richloc, opt, (maybe ? G_("%qD may write between %E and %E bytes " "into a region of size %E") @@ -1058,7 +1074,7 @@ warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt, "into a region of size %E overflows " "the destination")), func, range[0], range[1], size) - : warning_at (loc, opt, + : warning_at (&richloc, opt, (maybe ? G_("may write between %E and %E bytes " "into a region of size %E") @@ -1073,7 +1089,7 @@ warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt, { if (tree_int_cst_equal (range[0], range[1])) warned = (func - ? warning_n (loc, OPT_Wstringop_overread, + ? warning_n (&richloc, OPT_Wstringop_overread, tree_to_uhwi (range[0]), (maybe ? G_("%qD may read %E byte from a region " @@ -1086,7 +1102,7 @@ warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt, : G_("%qD reading %E bytes from a region " "of size %E")), func, range[0], size) - : warning_n (loc, OPT_Wstringop_overread, + : warning_n (&richloc, OPT_Wstringop_overread, tree_to_uhwi (range[0]), (maybe ? G_("may read %E byte from a region " @@ -1103,14 +1119,14 @@ warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt, { /* Avoid printing the upper bound if it's invalid. */ warned = (func - ? warning_at (loc, OPT_Wstringop_overread, + ? warning_at (&richloc, OPT_Wstringop_overread, (maybe ? G_("%qD may read %E or more bytes " "from a region of size %E") : G_("%qD reading %E or more bytes " "from a region of size %E")), func, range[0], size) - : warning_at (loc, OPT_Wstringop_overread, + : warning_at (&richloc, OPT_Wstringop_overread, (maybe ? G_("may read %E or more bytes " "from a region of size %E") @@ -1120,14 +1136,14 @@ warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt, } else warned = (func - ? warning_at (loc, OPT_Wstringop_overread, + ? warning_at (&richloc, OPT_Wstringop_overread, (maybe ? G_("%qD may read between %E and %E bytes " "from a region of size %E") : G_("%qD reading between %E and %E bytes " "from a region of size %E")), func, range[0], range[1], size) - : warning_at (loc, opt, + : warning_at (&richloc, opt, (maybe ? G_("may read between %E and %E bytes " "from a region of size %E") @@ -1144,12 +1160,12 @@ warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt, if (tree_int_cst_equal (range[0], range[1]) || tree_int_cst_sign_bit (range[1])) warned = (func - ? warning_n (loc, OPT_Wstringop_overread, + ? warning_n (&richloc, OPT_Wstringop_overread, tree_to_uhwi (range[0]), "%qD expecting %E byte in a region of size %E", "%qD expecting %E bytes in a region of size %E", func, range[0], size) - : warning_n (loc, OPT_Wstringop_overread, + : warning_n (&richloc, OPT_Wstringop_overread, tree_to_uhwi (range[0]), "expecting %E byte in a region of size %E", "expecting %E bytes in a region of size %E", @@ -1158,22 +1174,22 @@ warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt, { /* Avoid printing the upper bound if it's invalid. */ warned = (func - ? warning_at (loc, OPT_Wstringop_overread, + ? warning_at (&richloc, OPT_Wstringop_overread, "%qD expecting %E or more bytes in a region " "of size %E", func, range[0], size) - : warning_at (loc, OPT_Wstringop_overread, + : warning_at (&richloc, OPT_Wstringop_overread, "expecting %E or more bytes in a region " "of size %E", range[0], size)); } else warned = (func - ? warning_at (loc, OPT_Wstringop_overread, + ? warning_at (&richloc, OPT_Wstringop_overread, "%qD expecting between %E and %E bytes in " "a region of size %E", func, range[0], range[1], size) - : warning_at (loc, OPT_Wstringop_overread, + : warning_at (&richloc, OPT_Wstringop_overread, "expecting between %E and %E bytes in " "a region of size %E", range[0], range[1], size)); @@ -1404,6 +1420,8 @@ check_access (GimpleOrTree exp, tree dstwrite, auto_diagnostic_group d; location_t loc = get_location (exp); + rich_location_with_details richloc (loc, exp); + bool warned = false; if (dstwrite == slen && at_least_one) { @@ -1411,12 +1429,12 @@ check_access (GimpleOrTree exp, tree dstwrite, and a source of unknown length. The call will write at least one byte past the end of the destination. */ warned = (func - ? warning_at (loc, opt, + ? warning_at (&richloc, opt, "%qD writing %E or more bytes into " "a region of size %E overflows " "the destination", func, range[0], dstsize) - : warning_at (loc, opt, + : warning_at (&richloc, opt, "writing %E or more bytes into " "a region of size %E overflows " "the destination", @@ -2583,7 +2601,9 @@ pass_waccess::check_strncat (gcall *stmt) && tree_int_cst_equal (destsize, maxread)) { location_t loc = get_location (stmt); - warning_at (loc, OPT_Wstringop_overflow_, + rich_location_with_details richloc (loc, stmt); + + warning_at (&richloc, OPT_Wstringop_overflow_, "%qD specified bound %E equals destination size", get_callee_fndecl (stmt), maxread); @@ -3464,13 +3484,14 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype, && tree_int_cst_sgn (sizrng[0]) < 0 && tree_int_cst_sgn (sizrng[1]) < 0) { + rich_location_with_details richloc (loc, stmt); /* Warn about negative sizes. */ if (access.second.internal_p) { const std::string argtypestr = access.second.array_as_string (ptrtype); - if (warning_at (loc, OPT_Wstringop_overflow_, + if (warning_at (&richloc, OPT_Wstringop_overflow_, "bound argument %i value %s is " "negative for a variable length array " "argument %i of type %s", @@ -3478,7 +3499,7 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype, ptridx + 1, argtypestr.c_str ())) arg_warned = OPT_Wstringop_overflow_; } - else if (warning_at (loc, OPT_Wstringop_overflow_, + else if (warning_at (&richloc, OPT_Wstringop_overflow_, "argument %i value %s is negative", sizidx + 1, sizstr)) arg_warned = OPT_Wstringop_overflow_; diff --git a/gcc/gimple-ssa-warn-restrict.cc b/gcc/gimple-ssa-warn-restrict.cc index 47263aa4d34..a52307866cc 100644 --- a/gcc/gimple-ssa-warn-restrict.cc +++ b/gcc/gimple-ssa-warn-restrict.cc @@ -40,6 +40,7 @@ #include "tree-object-size.h" #include "calls.h" #include "cfgloop.h" +#include "move-history-rich-location.h" #include "intl.h" #include "gimple-range.h" @@ -1693,6 +1694,8 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, location_t loc = gimple_location (call); const offset_int maxobjsize = ref.maxobjsize; + rich_location_with_details richloc (loc, call); + /* Check for excessive size first and regardless of warning options since the result is used to make codegen decisions. */ if (ref.sizrange[0] > maxobjsize) @@ -1709,13 +1712,13 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, if (warn_stringop_overflow) { if (ref.sizrange[0] == ref.sizrange[1]) - warned = warning_at (loc, opt, + warned = warning_at (&richloc, opt, "%qD specified bound %wu " "exceeds maximum object size %wu", func, ref.sizrange[0].to_uhwi (), maxobjsize.to_uhwi ()); else - warned = warning_at (loc, opt, + warned = warning_at (&richloc, opt, "%qD specified bound between %wu and %wu " "exceeds maximum object size %wu", func, ref.sizrange[0].to_uhwi (), @@ -1776,7 +1779,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, && TREE_CODE (type = TREE_TYPE (ref.base)) == ARRAY_TYPE) { auto_diagnostic_group d; - if (warning_at (loc, opt, + if (warning_at (&richloc, opt, "%qD pointer overflow between offset %s " "and size %s accessing array %qD with type %qT", func, rangestr[0], rangestr[1], ref.base, type)) @@ -1786,13 +1789,13 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, warned = true; } else - warned = warning_at (loc, opt, + warned = warning_at (&richloc, opt, "%qD pointer overflow between offset %s " "and size %s", func, rangestr[0], rangestr[1]); } else - warned = warning_at (loc, opt, + warned = warning_at (&richloc, opt, "%qD pointer overflow between offset %s " "and size %s", func, rangestr[0], rangestr[1]); @@ -1808,7 +1811,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, { auto_diagnostic_group d; if ((ref.basesize < maxobjsize - && warning_at (loc, opt, + && warning_at (&richloc, opt, form ? G_("%qD forming offset %s is out of " "the bounds [0, %wu] of object %qD with " @@ -1817,7 +1820,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, "[0, %wu] of object %qD with type %qT"), func, rangestr[0], ref.basesize.to_uhwi (), ref.base, TREE_TYPE (ref.base))) - || warning_at (loc, opt, + || warning_at (&richloc, opt, form ? G_("%qD forming offset %s is out of " "the bounds of object %qD with type %qT") @@ -1832,7 +1835,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, } } else if (ref.basesize < maxobjsize) - warned = warning_at (loc, opt, + warned = warning_at (&richloc, opt, form ? G_("%qD forming offset %s is out " "of the bounds [0, %wu]") @@ -1840,7 +1843,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, "of the bounds [0, %wu]"), func, rangestr[0], ref.basesize.to_uhwi ()); else - warned = warning_at (loc, opt, + warned = warning_at (&richloc, opt, form ? G_("%qD forming offset %s is out of bounds") : G_("%qD offset %s is out of bounds"), @@ -1854,7 +1857,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, type = TREE_TYPE (type); type = TYPE_MAIN_VARIANT (type); - if (warning_at (loc, opt, + if (warning_at (&richloc, opt, "%qD offset %s from the object at %qE is out " "of the bounds of %qT", func, rangestr[0], ref.base, type)) @@ -1872,7 +1875,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, tree refop = TREE_OPERAND (ref.ref, 0); tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref)); - if (warning_at (loc, opt, + if (warning_at (&richloc, opt, "%qD offset %s from the object at %qE is out " "of the bounds of referenced subobject %qD with " "type %qT at offset %wi", diff --git a/gcc/move-history-rich-location.cc b/gcc/move-history-rich-location.cc new file mode 100644 index 00000000000..120498d165e --- /dev/null +++ b/gcc/move-history-rich-location.cc @@ -0,0 +1,56 @@ +/* A rich_location subclass that lazily populates a diagnostic_path + with move_history events, but only if the path is actually to be + used. + + Copyright (C) 2024 Free Software Foundation, Inc. + Contributed by Qing Zhao<qing.z...@oracle.com> + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#define INCLUDE_MEMORY +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "backend.h" +#include "function.h" +#include "diagnostic-move-history.h" +#include "simple-diagnostic-path.h" +#include "move-history-rich-location.h" + +/* Implemenation of the method make_inner_path of the class + lazy_move_history_path. */ + +std::unique_ptr<diagnostic_path> +lazy_move_history_path::make_inner_path () const +{ + auto path = std::make_unique<simple_diagnostic_path> + (global_dc->get_reference_printer ()); + if (!flag_diagnostics_details) + return path; + move_history_t mv_history = m_stmt ? get_move_history (m_stmt) : NULL; + for (move_history_t cur_ch = mv_history; cur_ch; + cur_ch = cur_ch->prev_move) + path->add_event (cur_ch->condition, cfun->decl, 1, + "when the condition is evaluated to %s", + cur_ch->is_true_path ? "true" : "false"); + + /* Add an end of path warning event in the end of the path. */ + if (path->num_events () > 0) + path->add_event (m_location, cfun->decl, 1, + "out of array bounds here"); + return path; +} diff --git a/gcc/move-history-rich-location.h b/gcc/move-history-rich-location.h new file mode 100644 index 00000000000..42b64037591 --- /dev/null +++ b/gcc/move-history-rich-location.h @@ -0,0 +1,65 @@ +/* A rich_location subclass that lazily populates a diagnostic_path + with move_history events, but only if the path is actually to be + used. + Copyright (C) 2024 Free Software Foundation, Inc. + Contributed by Qing Zhao<qing.z...@oracle.com> + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#ifndef GCC_MOVE_HISTORY_RICH_LOCATION_H +#define GCC_MOVE_HISTORY_RICH_LOCATION_H + +#include "gcc-rich-location.h" +#include "lazy-diagnostic-path.h" + +class lazy_move_history_path : public lazy_diagnostic_path +{ +public: + lazy_move_history_path (location_t location, gimple *stmt) + : m_location (location), m_stmt (stmt) + { + } + + std::unique_ptr<diagnostic_path> + make_inner_path () const final override; + /* This methold will be called on demand if a diagnostic is actually + emitted for this rich_location. */ + location_t m_location; + gimple *m_stmt; +}; + +class rich_location_with_details : public gcc_rich_location +{ +public: + rich_location_with_details (location_t location, gimple *stmt) + : gcc_rich_location (location), + m_lazy_move_history_path (location, stmt) + { + set_path (&m_lazy_move_history_path); + } + + rich_location_with_details (location_t location, tree exp ATTRIBUTE_UNUSED) + : gcc_rich_location (location), + m_lazy_move_history_path (location, NULL) + { + } + +private: + lazy_move_history_path m_lazy_move_history_path; +}; + +#endif // GCC_MOVE_HISTORY_RICH_LOCATION_H diff --git a/gcc/testsuite/gcc.dg/pr109071.c b/gcc/testsuite/gcc.dg/pr109071.c new file mode 100644 index 00000000000..ea647247a01 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr109071.c @@ -0,0 +1,43 @@ +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings + due to code duplication from jump threading. */ +/* { dg-options "-O2 -Wall -fdiagnostics-details" } */ +/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ +/* { dg-enable-nn-line-numbers "" } */ + +extern void warn(void); +static inline void assign(int val, int *regs, int index) +{ + if (index >= 4) + warn(); + *regs = val; +} +struct nums {int vals[4];}; + +void sparx5_set (int *ptr, struct nums *sg, int index) +{ + int *val = &sg->vals[index]; /* { dg-warning "is above array bounds" } */ + + assign(0, ptr, index); + assign(*val, ptr, index); +} +/* { dg-begin-multiline-output "" } + NN | int *val = &sg->vals[index]; + | ~~~~~~~~^~~~~~~ + 'sparx5_set': events 1-2 + NN | if (index >= 4) + | ^ + | | + | (1) when the condition is evaluated to true +...... + { dg-end-multiline-output "" } */ + +/* { dg-begin-multiline-output "" } + | ~~~~~~~~~~~~~~~ + | | + | (2) out of array bounds here + { dg-end-multiline-output "" } */ + +/* { dg-begin-multiline-output "" } + NN | struct nums {int vals[4];}; + | ^~~~ + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/pr109071_1.c b/gcc/testsuite/gcc.dg/pr109071_1.c new file mode 100644 index 00000000000..7a562941e0c --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr109071_1.c @@ -0,0 +1,36 @@ +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings + due to code duplication from jump threading. + test case is from PR88771, which is a duplication of PR109071. */ +/* { dg-options "-O2 -fdiagnostics-details" } */ +/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ +/* { dg-enable-nn-line-numbers "" } */ +typedef struct { + int a; +} * b; + +char *c, *x; +int f; + +void d() { + b e; + char a = f + 1 ?: f; + __builtin_strncpy(c, x, f); /* { dg-warning "exceeds maximum object size" } */ + if (a) + e->a = 0; +} +/* { dg-begin-multiline-output "" } + NN | __builtin_strncpy(c, x, f); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~ + 'd': events 1-2 + NN | char a = f + 1 ?: f; + | ^ + | | + | (1) when the condition is evaluated to false + { dg-end-multiline-output "" } */ + +/* { dg-begin-multiline-output "" } + NN | __builtin_strncpy(c, x, f); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~ + | | + | (2) out of array bounds here + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/pr109071_2.c b/gcc/testsuite/gcc.dg/pr109071_2.c new file mode 100644 index 00000000000..9cbac28a727 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr109071_2.c @@ -0,0 +1,50 @@ +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings + due to code duplication from jump threading. + test case is from PR85788, which is a duplication of PR109071. */ +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-details" } */ +/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ +/* { dg-enable-nn-line-numbers "" } */ +int b=10; +int *d = &b, *e; +void a(void *k, long l) { + long f = __builtin_object_size(k, 0); + __builtin___memset_chk(k, b, l, f); /* { dg-warning "is out of the bounds" } */ +} +typedef struct { + int g; + int h; + char i[8000 * 8]; +} j; +static void make_str_raster(j *k) { + int *c = d; + for (; c; c = e) + k->g = k->h = 32767; + + a(k->i, k->g / 8 * k->h); + for (; d;) + ; +} +j m; +void n() { make_str_raster(&m); } +/* { dg-begin-multiline-output "" } + NN | __builtin___memset_chk(k, b, l, f); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 'n': events 1-2 + NN | __builtin___memset_chk(k, b, l, f); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | | + | (2) out of array bounds here +...... + { dg-end-multiline-output "" } */ + +/* { dg-begin-multiline-output "" } + NN | for (; c; c = e) + | ^ + | | + | (1) when the condition is evaluated to true + { dg-end-multiline-output "" } */ + +/* { dg-begin-multiline-output "" } + NN | j m; + | ^ + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/pr109071_3.c b/gcc/testsuite/gcc.dg/pr109071_3.c new file mode 100644 index 00000000000..0461bbf5f92 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr109071_3.c @@ -0,0 +1,42 @@ +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings + due to code duplication from jump threading. + test case is from PR108770, which is a duplication of PR109071. */ +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-details" } */ +/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ +/* { dg-enable-nn-line-numbers "" } */ +extern void put(int i); +int check_idx(int i) { + if (i > 1) + put(i); + return i; +} +const char *arr[] = {"A", 0}; +void init() { + int i = 0; + while (arr[check_idx(i)] != 0) { /* { dg-warning "is above array bounds of" } */ + if (arr[check_idx(i)]) {} + i++; + } +} +/* { dg-begin-multiline-output "" } + NN | while (arr[check_idx(i)] != 0) { + | ~~~^~~~~~~~~~~~~~ + 'init': events 1-2 + NN | if (i > 1) + | ^ + | | + | (1) when the condition is evaluated to true +...... + { dg-end-multiline-output "" } */ + +/* { dg-begin-multiline-output "" } + NN | while (arr[check_idx(i)] != 0) { + | ~~~~~~~~~~~~~~~~~ + | | + | (2) out of array bounds here + { dg-end-multiline-output "" } */ + +/* { dg-begin-multiline-output "" } + NN | const char *arr[] = {"A", 0}; + | ^~~ + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/pr109071_4.c b/gcc/testsuite/gcc.dg/pr109071_4.c new file mode 100644 index 00000000000..10118104ab7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr109071_4.c @@ -0,0 +1,41 @@ +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings + due to code duplication from jump threading. + test case is from PR106762, which is a duplication of PR109071. */ +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-details" } */ +/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ +/* { dg-enable-nn-line-numbers "" } */ +typedef long unsigned int size_t; + +struct obj_t { size_t field0; size_t field1; }; +struct obj_array_t { size_t objcnt; struct obj_t* objary; }; + +extern void *memset (void *__s, int __c, size_t __n) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__nonnull__(1))); + +void bug(struct obj_array_t* ary) +{ + size_t idx = 0; + struct obj_t* obj; + if (idx < ary->objcnt) + obj = &ary->objary[idx]; + else + obj = 0; + memset(&obj->field1, 0xff, sizeof(obj->field1)); /* { dg-warning "is out of the bounds" } */ + obj->field0 = 0; +} +/* { dg-begin-multiline-output "" } + NN | memset(&obj->field1, 0xff, sizeof(obj->field1)); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 'bug': events 1-2 + NN | if (idx < ary->objcnt) + | ^ + | | + | (1) when the condition is evaluated to false +...... + { dg-end-multiline-output "" } */ + +/* { dg-begin-multiline-output "" } + NN | memset(&obj->field1, 0xff, sizeof(obj->field1)); + | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + | | + | (2) out of array bounds here + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/pr109071_5.c b/gcc/testsuite/gcc.dg/pr109071_5.c new file mode 100644 index 00000000000..bd81df22669 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr109071_5.c @@ -0,0 +1,33 @@ +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings + due to code duplication from jump threading. + test case is from PR115274, which is a duplication of PR109071. */ +/* { dg-options "-O2 -Wstringop-overread -fdiagnostics-details" } */ +/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ +/* { dg-enable-nn-line-numbers "" } */ +#include <string.h> +char *c; +void a(long); +int b(char *d) { return strlen(d); } /* { dg-warning "or more bytes from a region of size 0" } */ +void e() { + long f = 1; + f = b(c + f); + if (c == 0) + a(f); +} +/* { dg-begin-multiline-output "" } + NN | int b(char *d) { return strlen(d); } + | ^~~~~~~~~ + 'e': events 1-2 + NN | int b(char *d) { return strlen(d); } + | ~~~~~~~~~ + | | + | (2) out of array bounds here +...... + { dg-end-multiline-output "" } */ + +/* { dg-begin-multiline-output "" } + NN | if (c == 0) + | ^ + | | + | (1) when the condition is evaluated to true + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/gcc.dg/pr109071_6.c b/gcc/testsuite/gcc.dg/pr109071_6.c new file mode 100644 index 00000000000..6d0565bda3e --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr109071_6.c @@ -0,0 +1,49 @@ +/* PR tree-optimization/109071 need more context for -Warray-bounds warnings + due to code duplication from jump threading. + test case is from PR117179, which is a duplication of PR109071. */ +/* { dg-options "-O2 -Warray-bounds -fdiagnostics-details" } */ +/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */ +/* { dg-enable-nn-line-numbers "" } */ +const char* commands[] = {"a", "b"}; + +int setval_internal(int comind) +{ + if (comind > sizeof(commands)/sizeof(commands[0])) { + return 0; + } + + return 1; +} + +_Bool setval_internal_tilde(int comind, const char *com, + const char *val) +{ + int ret = setval_internal(comind); + if (commands[comind] == "b" && /* { dg-warning "is outside array bounds of" } */ + + ret) + return 1; + return 0; +} +/* { dg-begin-multiline-output "" } + NN | if (commands[comind] == "b" && + | ~~~~~~~~^~~~~~~~ + 'setval_internal_tilde': events 1-2 + NN | if (comind > sizeof(commands)/sizeof(commands[0])) { + | ^ + | | + | (1) when the condition is evaluated to true +...... + { dg-end-multiline-output "" } */ + +/* { dg-begin-multiline-output "" } + NN | if (commands[comind] == "b" && + | ~~~~~~~~~~~~~~~~ + | | + | (2) out of array bounds here + { dg-end-multiline-output "" } */ + +/* { dg-begin-multiline-output "" } + NN | const char* commands[] = {"a", "b"}; + | ^~~~~~~~ + { dg-end-multiline-output "" } */ -- 2.43.5