diff options
author | Thomas Koenig <tkoenig@gcc.gnu.org> | 2021-09-13 19:49:49 +0200 |
---|---|---|
committer | Thomas Koenig <tkoenig@gcc.gnu.org> | 2021-09-13 19:49:49 +0200 |
commit | b18a97e5dd0935e1c4a626c230f21457d0aad3d5 (patch) | |
tree | c1818f41af6fe780deafb6cd6a183f32085fe654 /gcc/gimple-ssa-warn-restrict.c | |
parent | e76a53644c9d70e998c0d050e9a456af388c6b61 (diff) | |
download | gcc-b18a97e5dd0935e1c4a626c230f21457d0aad3d5.zip gcc-b18a97e5dd0935e1c4a626c230f21457d0aad3d5.tar.gz gcc-b18a97e5dd0935e1c4a626c230f21457d0aad3d5.tar.bz2 |
Merged current trunk to branch.
Diffstat (limited to 'gcc/gimple-ssa-warn-restrict.c')
-rw-r--r-- | gcc/gimple-ssa-warn-restrict.c | 271 |
1 files changed, 143 insertions, 128 deletions
diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c index 3a79e72..d1df9ca 100644 --- a/gcc/gimple-ssa-warn-restrict.c +++ b/gcc/gimple-ssa-warn-restrict.c @@ -1,6 +1,6 @@ /* Pass to detect and issue warnings for violations of the restrict qualifier. - Copyright (C) 2017-2020 Free Software Foundation, Inc. + Copyright (C) 2017-2021 Free Software Foundation, Inc. Contributed by Martin Sebor <msebor@redhat.com>. This file is part of GCC. @@ -26,9 +26,10 @@ #include "tree.h" #include "gimple.h" #include "tree-pass.h" -#include "builtins.h" +#include "pointer-query.h" #include "ssa.h" #include "gimple-pretty-print.h" +#include "gimple-ssa-warn-access.h" #include "gimple-ssa-warn-restrict.h" #include "diagnostic-core.h" #include "fold-const.h" @@ -349,7 +350,13 @@ builtin_memref::extend_offset_range (tree offset) /* There is a global version here because check_bounds_or_overlap may be called from gimple fold during gimple lowering. */ - rng = get_range_info (offset, &min, &max); + get_range_query (cfun)->range_of_expr (vr, offset, stmt); + rng = vr.kind (); + if (!vr.undefined_p ()) + { + min = wi::to_wide (vr.min ()); + max = wi::to_wide (vr.max ()); + } } if (rng == VR_ANTI_RANGE && wi::lts_p (max, min)) { @@ -1425,7 +1432,7 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs) if (!acs.overlap ()) return false; - if (gimple_no_warning_p (call)) + if (warning_suppressed_p (call, OPT_Wrestrict)) return true; /* For convenience. */ @@ -1488,36 +1495,36 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs) warning_at (loc, OPT_Wrestrict, sizrange[0] == 1 ? (ovlsiz[0] == 1 - ? G_("%G%qD accessing %wu byte at offsets %s " + ? G_("%qD accessing %wu byte at offsets %s " "and %s overlaps %wu byte at offset %s") - : G_("%G%qD accessing %wu byte at offsets %s " + : G_("%qD accessing %wu byte at offsets %s " "and %s overlaps %wu bytes at offset " "%s")) : (ovlsiz[0] == 1 - ? G_("%G%qD accessing %wu bytes at offsets %s " + ? G_("%qD accessing %wu bytes at offsets %s " "and %s overlaps %wu byte at offset %s") - : G_("%G%qD accessing %wu bytes at offsets %s " + : G_("%qD accessing %wu bytes at offsets %s " "and %s overlaps %wu bytes at offset " "%s")), - call, func, sizrange[0], + func, sizrange[0], offstr[0], offstr[1], ovlsiz[0], offstr[2]); else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ()) warning_n (loc, OPT_Wrestrict, sizrange[0], - "%G%qD accessing %wu byte at offsets %s " + "%qD accessing %wu byte at offsets %s " "and %s overlaps between %wu and %wu bytes " "at offset %s", - "%G%qD accessing %wu bytes at offsets %s " + "%qD accessing %wu bytes at offsets %s " "and %s overlaps between %wu and %wu bytes " "at offset %s", - call, func, sizrange[0], offstr[0], offstr[1], + func, sizrange[0], offstr[0], offstr[1], ovlsiz[0], ovlsiz[1], offstr[2]); else warning_n (loc, OPT_Wrestrict, sizrange[0], - "%G%qD accessing %wu byte at offsets %s and " + "%qD accessing %wu byte at offsets %s and " "%s overlaps %wu or more bytes at offset %s", - "%G%qD accessing %wu bytes at offsets %s and " + "%qD accessing %wu bytes at offsets %s and " "%s overlaps %wu or more bytes at offset %s", - call, func, sizrange[0], + func, sizrange[0], offstr[0], offstr[1], ovlsiz[0], offstr[2]); return true; } @@ -1526,28 +1533,28 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs) { if (ovlsiz[0] == ovlsiz[1]) warning_n (loc, OPT_Wrestrict, ovlsiz[0], - "%G%qD accessing between %wu and %wu bytes " + "%qD accessing between %wu and %wu bytes " "at offsets %s and %s overlaps %wu byte at " "offset %s", - "%G%qD accessing between %wu and %wu bytes " + "%qD accessing between %wu and %wu bytes " "at offsets %s and %s overlaps %wu bytes " "at offset %s", - call, func, sizrange[0], sizrange[1], + func, sizrange[0], sizrange[1], offstr[0], offstr[1], ovlsiz[0], offstr[2]); else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ()) warning_at (loc, OPT_Wrestrict, - "%G%qD accessing between %wu and %wu bytes at " + "%qD accessing between %wu and %wu bytes at " "offsets %s and %s overlaps between %wu and %wu " "bytes at offset %s", - call, func, sizrange[0], sizrange[1], + func, sizrange[0], sizrange[1], offstr[0], offstr[1], ovlsiz[0], ovlsiz[1], offstr[2]); else warning_at (loc, OPT_Wrestrict, - "%G%qD accessing between %wu and %wu bytes at " + "%qD accessing between %wu and %wu bytes at " "offsets %s and %s overlaps %wu or more bytes " "at offset %s", - call, func, sizrange[0], sizrange[1], + func, sizrange[0], sizrange[1], offstr[0], offstr[1], ovlsiz[0], offstr[2]); return true; } @@ -1557,24 +1564,24 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs) if (ovlsiz[0] == ovlsiz[1]) warning_n (loc, OPT_Wrestrict, ovlsiz[0], - "%G%qD accessing %wu or more bytes at offsets " + "%qD accessing %wu or more bytes at offsets " "%s and %s overlaps %wu byte at offset %s", - "%G%qD accessing %wu or more bytes at offsets " + "%qD accessing %wu or more bytes at offsets " "%s and %s overlaps %wu bytes at offset %s", - call, func, sizrange[0], offstr[0], offstr[1], + func, sizrange[0], offstr[0], offstr[1], ovlsiz[0], offstr[2]); else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ()) warning_at (loc, OPT_Wrestrict, - "%G%qD accessing %wu or more bytes at offsets %s " + "%qD accessing %wu or more bytes at offsets %s " "and %s overlaps between %wu and %wu bytes " "at offset %s", - call, func, sizrange[0], offstr[0], offstr[1], + func, sizrange[0], offstr[0], offstr[1], ovlsiz[0], ovlsiz[1], offstr[2]); else warning_at (loc, OPT_Wrestrict, - "%G%qD accessing %wu or more bytes at offsets %s " + "%qD accessing %wu or more bytes at offsets %s " "and %s overlaps %wu or more bytes at offset %s", - call, func, sizrange[0], offstr[0], offstr[1], + func, sizrange[0], offstr[0], offstr[1], ovlsiz[0], offstr[2]); return true; } @@ -1600,36 +1607,36 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs) { if (open_range) warning_n (loc, OPT_Wrestrict, sizrange[1], - "%G%qD accessing %wu byte may overlap " + "%qD accessing %wu byte may overlap " "%wu byte", - "%G%qD accessing %wu bytes may overlap " + "%qD accessing %wu bytes may overlap " "%wu byte", - call, func, sizrange[1], ovlsiz[1]); + func, sizrange[1], ovlsiz[1]); else warning_n (loc, OPT_Wrestrict, sizrange[1], - "%G%qD accessing %wu byte at offsets %s " + "%qD accessing %wu byte at offsets %s " "and %s may overlap %wu byte at offset %s", - "%G%qD accessing %wu bytes at offsets %s " + "%qD accessing %wu bytes at offsets %s " "and %s may overlap %wu byte at offset %s", - call, func, sizrange[1], offstr[0], offstr[1], + func, sizrange[1], offstr[0], offstr[1], ovlsiz[1], offstr[2]); return true; } if (open_range) warning_n (loc, OPT_Wrestrict, sizrange[1], - "%G%qD accessing %wu byte may overlap " + "%qD accessing %wu byte may overlap " "up to %wu bytes", - "%G%qD accessing %wu bytes may overlap " + "%qD accessing %wu bytes may overlap " "up to %wu bytes", - call, func, sizrange[1], ovlsiz[1]); + func, sizrange[1], ovlsiz[1]); else warning_n (loc, OPT_Wrestrict, sizrange[1], - "%G%qD accessing %wu byte at offsets %s and " + "%qD accessing %wu byte at offsets %s and " "%s may overlap up to %wu bytes at offset %s", - "%G%qD accessing %wu bytes at offsets %s and " + "%qD accessing %wu bytes at offsets %s and " "%s may overlap up to %wu bytes at offset %s", - call, func, sizrange[1], offstr[0], offstr[1], + func, sizrange[1], offstr[0], offstr[1], ovlsiz[1], offstr[2]); return true; } @@ -1638,30 +1645,30 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs) { if (open_range) warning_n (loc, OPT_Wrestrict, ovlsiz[1], - "%G%qD accessing between %wu and %wu bytes " + "%qD accessing between %wu and %wu bytes " "may overlap %wu byte", - "%G%qD accessing between %wu and %wu bytes " + "%qD accessing between %wu and %wu bytes " "may overlap up to %wu bytes", - call, func, sizrange[0], sizrange[1], ovlsiz[1]); + func, sizrange[0], sizrange[1], ovlsiz[1]); else warning_n (loc, OPT_Wrestrict, ovlsiz[1], - "%G%qD accessing between %wu and %wu bytes " + "%qD accessing between %wu and %wu bytes " "at offsets %s and %s may overlap %wu byte " "at offset %s", - "%G%qD accessing between %wu and %wu bytes " + "%qD accessing between %wu and %wu bytes " "at offsets %s and %s may overlap up to %wu " "bytes at offset %s", - call, func, sizrange[0], sizrange[1], + func, sizrange[0], sizrange[1], offstr[0], offstr[1], ovlsiz[1], offstr[2]); return true; } warning_n (loc, OPT_Wrestrict, ovlsiz[1], - "%G%qD accessing %wu or more bytes at offsets %s " + "%qD accessing %wu or more bytes at offsets %s " "and %s may overlap %wu byte at offset %s", - "%G%qD accessing %wu or more bytes at offsets %s " + "%qD accessing %wu or more bytes at offsets %s " "and %s may overlap up to %wu bytes at offset %s", - call, func, sizrange[0], offstr[0], offstr[1], + func, sizrange[0], offstr[0], offstr[1], ovlsiz[1], offstr[2]); return true; @@ -1674,43 +1681,47 @@ maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs) be issued, false otherwise. Both initial values of the offsets and their final value computed by the function by incrementing the initial value by the size are - validated. Return true if the offsets are not valid and a diagnostic - has been issued, or would have been issued if DO_WARN had been true. */ + validated. Return the warning number if the offsets are not valid + and a diagnostic has been issued, or would have been issued if + DO_WARN had been true, otherwise an invalid warning number. */ -static bool +static opt_code maybe_diag_access_bounds (gimple *call, tree func, int strict, const builtin_memref &ref, offset_int wroff, bool do_warn) { - location_t loc = gimple_or_expr_nonartificial_location (call, ref.ptr); + location_t loc = gimple_location (call); const offset_int maxobjsize = ref.maxobjsize; /* Check for excessive size first and regardless of warning options since the result is used to make codegen decisions. */ if (ref.sizrange[0] > maxobjsize) { + const opt_code opt = OPT_Wstringop_overflow_; /* Return true without issuing a warning. */ if (!do_warn) - return true; + return opt; - if (ref.ref && TREE_NO_WARNING (ref.ref)) - return false; + if (ref.ref && warning_suppressed_p (ref.ref, OPT_Wstringop_overflow_)) + return no_warning; + bool warned = false; if (warn_stringop_overflow) { if (ref.sizrange[0] == ref.sizrange[1]) - return warning_at (loc, OPT_Wstringop_overflow_, - "%G%qD specified bound %wu " - "exceeds maximum object size %wu", - call, func, ref.sizrange[0].to_uhwi (), - maxobjsize.to_uhwi ()); - - return warning_at (loc, OPT_Wstringop_overflow_, - "%G%qD specified bound between %wu and %wu " - "exceeds maximum object size %wu", - call, func, ref.sizrange[0].to_uhwi (), - ref.sizrange[1].to_uhwi (), - maxobjsize.to_uhwi ()); + warned = warning_at (loc, 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, + "%qD specified bound between %wu and %wu " + "exceeds maximum object size %wu", + func, ref.sizrange[0].to_uhwi (), + ref.sizrange[1].to_uhwi (), + maxobjsize.to_uhwi ()); + return warned ? opt : no_warning; } } @@ -1723,18 +1734,19 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, offset_int ooboff[] = { ref.offrange[0], ref.offrange[1], wroff }; tree oobref = ref.offset_out_of_bounds (strict, ooboff); if (!oobref) - return false; + return no_warning; + const opt_code opt = OPT_Warray_bounds; /* Return true without issuing a warning. */ if (!do_warn) - return true; + return opt; if (!warn_array_bounds) - return false; + return no_warning; - if (TREE_NO_WARNING (ref.ptr) - || (ref.ref && TREE_NO_WARNING (ref.ref))) - return false; + if (warning_suppressed_p (ref.ptr, opt) + || (ref.ref && warning_suppressed_p (ref.ref, opt))) + return no_warning; char rangestr[2][64]; if (ooboff[0] == ooboff[1] @@ -1764,26 +1776,26 @@ 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_Warray_bounds, - "%G%qD pointer overflow between offset %s " + if (warning_at (loc, opt, + "%qD pointer overflow between offset %s " "and size %s accessing array %qD with type %qT", - call, func, rangestr[0], rangestr[1], ref.base, type)) + func, rangestr[0], rangestr[1], ref.base, type)) { inform (DECL_SOURCE_LOCATION (ref.base), "array %qD declared here", ref.base); warned = true; } else - warned = warning_at (loc, OPT_Warray_bounds, - "%G%qD pointer overflow between offset %s " + warned = warning_at (loc, opt, + "%qD pointer overflow between offset %s " "and size %s", - call, func, rangestr[0], rangestr[1]); + func, rangestr[0], rangestr[1]); } else - warned = warning_at (loc, OPT_Warray_bounds, - "%G%qD pointer overflow between offset %s " + warned = warning_at (loc, opt, + "%qD pointer overflow between offset %s " "and size %s", - call, func, rangestr[0], rangestr[1]); + func, rangestr[0], rangestr[1]); } else if (oobref == ref.base) { @@ -1796,22 +1808,22 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, { auto_diagnostic_group d; if ((ref.basesize < maxobjsize - && warning_at (loc, OPT_Warray_bounds, + && warning_at (loc, opt, form - ? G_("%G%qD forming offset %s is out of " + ? G_("%qD forming offset %s is out of " "the bounds [0, %wu] of object %qD with " "type %qT") - : G_("%G%qD offset %s is out of the bounds " + : G_("%qD offset %s is out of the bounds " "[0, %wu] of object %qD with type %qT"), - call, func, rangestr[0], ref.basesize.to_uhwi (), + func, rangestr[0], ref.basesize.to_uhwi (), ref.base, TREE_TYPE (ref.base))) - || warning_at (loc, OPT_Warray_bounds, + || warning_at (loc, opt, form - ? G_("%G%qD forming offset %s is out of " + ? G_("%qD forming offset %s is out of " "the bounds of object %qD with type %qT") - : G_("%G%qD offset %s is out of the bounds " + : G_("%qD offset %s is out of the bounds " "of object %qD with type %qT"), - call, func, rangestr[0], + func, rangestr[0], ref.base, TREE_TYPE (ref.base))) { inform (DECL_SOURCE_LOCATION (ref.base), @@ -1820,19 +1832,19 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, } } else if (ref.basesize < maxobjsize) - warned = warning_at (loc, OPT_Warray_bounds, + warned = warning_at (loc, opt, form - ? G_("%G%qD forming offset %s is out " + ? G_("%qD forming offset %s is out " "of the bounds [0, %wu]") - : G_("%G%qD offset %s is out " + : G_("%qD offset %s is out " "of the bounds [0, %wu]"), - call, func, rangestr[0], ref.basesize.to_uhwi ()); + func, rangestr[0], ref.basesize.to_uhwi ()); else - warned = warning_at (loc, OPT_Warray_bounds, + warned = warning_at (loc, opt, form - ? G_("%G%qD forming offset %s is out of bounds") - : G_("%G%qD offset %s is out of bounds"), - call, func, rangestr[0]); + ? G_("%qD forming offset %s is out of bounds") + : G_("%qD offset %s is out of bounds"), + func, rangestr[0]); } else if (TREE_CODE (ref.ref) == MEM_REF) { @@ -1842,10 +1854,10 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, type = TREE_TYPE (type); type = TYPE_MAIN_VARIANT (type); - if (warning_at (loc, OPT_Warray_bounds, - "%G%qD offset %s from the object at %qE is out " + if (warning_at (loc, opt, + "%qD offset %s from the object at %qE is out " "of the bounds of %qT", - call, func, rangestr[0], ref.base, type)) + func, rangestr[0], ref.base, type)) { if (TREE_CODE (ref.ref) == COMPONENT_REF) refop = TREE_OPERAND (ref.ref, 1); @@ -1860,11 +1872,11 @@ 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_Warray_bounds, - "%G%qD offset %s from the object at %qE is out " + if (warning_at (loc, opt, + "%qD offset %s from the object at %qE is out " "of the bounds of referenced subobject %qD with " "type %qT at offset %wi", - call, func, rangestr[0], ref.base, + func, rangestr[0], ref.base, TREE_OPERAND (ref.ref, 1), type, ref.refoff.to_shwi ())) { @@ -1877,7 +1889,7 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, } } - return warned; + return warned ? opt : no_warning; } /* Check a CALL statement for restrict-violations and issue warnings @@ -1888,7 +1900,7 @@ check_call (range_query *query, gimple *call) { /* Avoid checking the call if it has already been diagnosed for some reason. */ - if (gimple_no_warning_p (call)) + if (warning_suppressed_p (call, OPT_Wrestrict)) return; tree func = gimple_call_fndecl (call); @@ -1974,11 +1986,10 @@ check_call (range_query *query, gimple *call) || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr)))) return; - if (!check_bounds_or_overlap (query, call, dst, src, dstwr, NULL_TREE)) - return; - + opt_code opt = check_bounds_or_overlap (query, call, dst, src, dstwr, + NULL_TREE); /* Avoid diagnosing the call again. */ - gimple_set_no_warning (call, true); + suppress_warning (call, opt); } } /* anonymous namespace */ @@ -1990,7 +2001,7 @@ check_call (range_query *query, gimple *call) without issue a warning. Return the OPT_Wxxx constant corresponding to the warning if one has been detected and zero otherwise. */ -int +opt_code check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize, tree srcsize, bool bounds_only /* = false */, bool do_warn /* = true */) @@ -2000,7 +2011,7 @@ check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize, bounds_only, do_warn); } -int +opt_code check_bounds_or_overlap (range_query *query, gimple *call, tree dst, tree src, tree dstsize, tree srcsize, bool bounds_only /* = false */, @@ -2026,16 +2037,20 @@ check_bounds_or_overlap (range_query *query, /* Validate offsets to each reference before the access first to make sure they are within the bounds of the destination object if its size is known, or PTRDIFF_MAX otherwise. */ - if (maybe_diag_access_bounds (call, func, strict, dstref, wroff, do_warn) - || maybe_diag_access_bounds (call, func, strict, srcref, 0, do_warn)) + opt_code opt + = maybe_diag_access_bounds (call, func, strict, dstref, wroff, do_warn); + if (opt == no_warning) + opt = maybe_diag_access_bounds (call, func, strict, srcref, 0, do_warn); + + if (opt != no_warning) { if (do_warn) - gimple_set_no_warning (call, true); - return OPT_Warray_bounds; + suppress_warning (call, opt); + return opt; } if (!warn_restrict || bounds_only || !src) - return 0; + return no_warning; if (!bounds_only) { @@ -2045,39 +2060,39 @@ check_bounds_or_overlap (range_query *query, case BUILT_IN_MEMMOVE_CHK: case BUILT_IN_MEMSET: case BUILT_IN_MEMSET_CHK: - return 0; + return no_warning; default: break; } } - location_t loc = gimple_or_expr_nonartificial_location (call, dst); + location_t loc = gimple_location (call); if (operand_equal_p (dst, src, 0)) { /* Issue -Wrestrict unless the pointers are null (those do not point to objects and so do not indicate an overlap; such calls could be the result of sanitization and jump threading). */ - if (!integer_zerop (dst) && !gimple_no_warning_p (call)) + if (!integer_zerop (dst) && !warning_suppressed_p (call, OPT_Wrestrict)) { warning_at (loc, OPT_Wrestrict, - "%G%qD source argument is the same as destination", - call, func); - gimple_set_no_warning (call, true); + "%qD source argument is the same as destination", + func); + suppress_warning (call, OPT_Wrestrict); return OPT_Wrestrict; } - return 0; + return no_warning; } /* Return false when overlap has been detected. */ if (maybe_diag_overlap (loc, call, acs)) { - gimple_set_no_warning (call, true); + suppress_warning (call, OPT_Wrestrict); return OPT_Wrestrict; } - return 0; + return no_warning; } gimple_opt_pass * |