The third patch in the series adds a pointer_query instance to the wrestrict pass and uses it for each invocation to check a function.
gcc/ChangeLog: * gimple-ssa-warn-restrict.cc (class pass_wrestrict): Outline ctor. (pass_wrestrict::m_ptr_qry): New member. (wrestrict_walk): Rename... (pass_wrestrict::check_block): ...to this. (pass_wrestrict::execute): Set up and tear down pointer_query and ranger. (builtin_memref::builtin_memref): Change ctor argument. Simplify. (builtin_access::builtin_access): Same. (builtin_access::m_ptr_qry): New member. (check_call): Rename... (pass_wrestrict::check_call): ...to this. (check_bounds_or_overlap): Change argument. * gimple-ssa-warn-restrict.h (check_bounds_or_overlap): Same. --- gcc/gimple-ssa-warn-restrict.cc | 126 ++++++++++++++++---------------- gcc/gimple-ssa-warn-restrict.h | 2 +- 2 files changed, 62 insertions(+), 66 deletions(-) diff --git a/gcc/gimple-ssa-warn-restrict.cc b/gcc/gimple-ssa-warn-restrict.cc index d1beb01fe89..72418398dad 100644 --- a/gcc/gimple-ssa-warn-restrict.cc +++ b/gcc/gimple-ssa-warn-restrict.cc @@ -62,46 +62,63 @@ const pass_data pass_data_wrestrict = { class pass_wrestrict : public gimple_opt_pass { public: - pass_wrestrict (gcc::context *ctxt) - : gimple_opt_pass (pass_data_wrestrict, ctxt) - { } + pass_wrestrict (gcc::context *); - opt_pass *clone () { return new pass_wrestrict (m_ctxt); } + // opt_pass *clone () { return new pass_wrestrict (m_ctxt); } virtual bool gate (function *); virtual unsigned int execute (function *); + + void check_call (gimple *); + + void check_block (basic_block); + + /* A pointer_query object to store information about pointers and + their targets in. */ + pointer_query m_ptr_qry; }; +pass_wrestrict::pass_wrestrict (gcc::context *ctxt) + : gimple_opt_pass (pass_data_wrestrict, ctxt), + m_ptr_qry () +{ } + bool pass_wrestrict::gate (function *fun ATTRIBUTE_UNUSED) { return warn_array_bounds || warn_restrict || warn_stringop_overflow; } -static void check_call (range_query *, gimple *); - -static void -wrestrict_walk (range_query *query, basic_block bb) +void +pass_wrestrict::check_block (basic_block bb) { /* Iterate over statements, looking for function calls. */ - for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si); - gsi_next (&si)) + for (auto si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si)) { gimple *stmt = gsi_stmt (si); if (!is_gimple_call (stmt)) continue; - check_call (query, stmt); + check_call (stmt); } } unsigned pass_wrestrict::execute (function *fun) { - gimple_ranger ranger; + /* Create a new ranger instance and associate it with FUN. */ + m_ptr_qry.rvals = enable_ranger (fun); + basic_block bb; FOR_EACH_BB_FN (bb, fun) - wrestrict_walk (&ranger, bb); + check_block (bb); + + m_ptr_qry.flush_cache (); + + /* Release the ranger instance and replace it with a global ranger. + Also reset the pointer since calling disable_ranger() deletes it. */ + disable_ranger (fun); + m_ptr_qry.rvals = NULL; return 0; } @@ -145,7 +162,7 @@ public: only the destination reference is. */ bool strbounded_p; - builtin_memref (range_query *, gimple *, tree, tree); + builtin_memref (pointer_query &, gimple *, tree, tree); tree offset_out_of_bounds (int, offset_int[3]) const; @@ -153,7 +170,7 @@ private: /* Call statement to the built-in. */ gimple *stmt; - range_query *query; + pointer_query &m_ptr_qry; /* Ctor helper to set or extend OFFRANGE based on argument. */ void extend_offset_range (tree); @@ -187,7 +204,8 @@ class builtin_access && detect_overlap != &builtin_access::no_overlap); } - builtin_access (range_query *, gimple *, builtin_memref &, builtin_memref &); + builtin_access (pointer_query &, gimple *, + builtin_memref &, builtin_memref &); /* Entry point to determine overlap. */ bool overlap (); @@ -225,7 +243,7 @@ class builtin_access a size SIZE in bytes. If SIZE is NULL_TREE then the size is assumed to be unknown. STMT is the statement in which expr appears in. */ -builtin_memref::builtin_memref (range_query *query, gimple *stmt, tree expr, +builtin_memref::builtin_memref (pointer_query &ptrqry, gimple *stmt, tree expr, tree size) : ptr (expr), ref (), @@ -238,7 +256,7 @@ builtin_memref::builtin_memref (range_query *query, gimple *stmt, tree expr, maxobjsize (tree_to_shwi (max_object_size ())), strbounded_p (), stmt (stmt), - query (query) + m_ptr_qry (ptrqry) { /* Unfortunately, wide_int default ctor is a no-op so array members of the type must be set individually. */ @@ -257,7 +275,7 @@ builtin_memref::builtin_memref (range_query *query, gimple *stmt, tree expr, tree range[2]; /* Determine the size range, allowing for the result to be [0, 0] for SIZE in the anti-range ~[0, N] where N >= PTRDIFF_MAX. */ - get_size_range (query, size, stmt, range, SR_ALLOW_ZERO); + get_size_range (m_ptr_qry.rvals, size, stmt, range, SR_ALLOW_ZERO); sizrange[0] = wi::to_offset (range[0]); sizrange[1] = wi::to_offset (range[1]); /* get_size_range returns SIZE_MAX for the maximum size. @@ -334,23 +352,10 @@ builtin_memref::extend_offset_range (tree offset) /* A pointer offset is represented as sizetype but treated as signed. */ wide_int min, max; - value_range_kind rng; + value_range_kind rng = VR_VARYING; value_range vr; - if (query && query->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 ()); - } - } - else + if (m_ptr_qry.rvals->range_of_expr (vr, offset, stmt)) { - /* There is a global version here because - check_bounds_or_overlap may be called from gimple - fold during gimple lowering. */ - get_range_query (cfun)->range_of_expr (vr, offset, stmt); rng = vr.kind (); if (!vr.undefined_p ()) { @@ -358,6 +363,7 @@ builtin_memref::extend_offset_range (tree offset) max = wi::to_wide (vr.max ()); } } + if (rng == VR_ANTI_RANGE && wi::lts_p (max, min)) { /* Convert an anti-range whose upper bound is less than @@ -674,7 +680,7 @@ builtin_memref::offset_out_of_bounds (int strict, offset_int ooboff[3]) const /* Create an association between the memory references DST and SRC for access by a call EXPR to a memory or string built-in funtion. */ -builtin_access::builtin_access (range_query *query, gimple *call, +builtin_access::builtin_access (pointer_query &ptrqry, gimple *call, builtin_memref &dst, builtin_memref &src) : dstref (&dst), srcref (&src), sizrange (), ovloff (), ovlsiz (), @@ -766,39 +772,28 @@ builtin_access::builtin_access (range_query *query, gimple *call, return; } - const offset_int maxobjsize = dst.maxobjsize; - /* Try to determine the size of the base object. compute_objsize expects a pointer so create one if BASE is a non-pointer object. */ - tree addr; if (dst.basesize < 0) { - addr = dst.base; - if (!POINTER_TYPE_P (TREE_TYPE (addr))) - addr = build1 (ADDR_EXPR, (TREE_TYPE (addr)), addr); - - if (tree dstsize = compute_objsize (addr, call, ostype)) - dst.basesize = wi::to_offset (dstsize); - else if (POINTER_TYPE_P (TREE_TYPE (addr))) - dst.basesize = HOST_WIDE_INT_MIN; + access_ref aref; + if (ptrqry.get_ref (dst.base, call, &aref, ostype) && aref.base0) + dst.basesize = aref.sizrng[1]; else - dst.basesize = maxobjsize; + dst.basesize = HOST_WIDE_INT_MIN; } if (src.base && src.basesize < 0) { - addr = src.base; - if (!POINTER_TYPE_P (TREE_TYPE (addr))) - addr = build1 (ADDR_EXPR, (TREE_TYPE (addr)), addr); - - if (tree srcsize = compute_objsize (addr, call, ostype)) - src.basesize = wi::to_offset (srcsize); - else if (POINTER_TYPE_P (TREE_TYPE (addr))) - src.basesize = HOST_WIDE_INT_MIN; + access_ref aref; + if (ptrqry.get_ref (src.base, call, &aref, ostype) && aref.base0) + src.basesize = aref.sizrng[1]; else - src.basesize = maxobjsize; + src.basesize = HOST_WIDE_INT_MIN; } + const offset_int maxobjsize = dst.maxobjsize; + /* Make adjustments for references to the same object by string built-in functions to reflect the constraints imposed by the function. */ @@ -814,7 +809,7 @@ builtin_access::builtin_access (range_query *query, gimple *call, tree size = gimple_call_arg (call, sizeargno); tree range[2]; - if (get_size_range (query, size, call, range, true)) + if (get_size_range (ptrqry.rvals, size, call, range, true)) { bounds[0] = wi::to_offset (range[0]); bounds[1] = wi::to_offset (range[1]); @@ -1895,8 +1890,8 @@ maybe_diag_access_bounds (gimple *call, tree func, int strict, /* Check a CALL statement for restrict-violations and issue warnings if/when appropriate. */ -static void -check_call (range_query *query, gimple *call) +void +pass_wrestrict::check_call (gimple *call) { /* Avoid checking the call if it has already been diagnosed for some reason. */ @@ -1986,7 +1981,7 @@ check_call (range_query *query, gimple *call) || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr)))) return; - opt_code opt = check_bounds_or_overlap (query, call, dst, src, dstwr, + opt_code opt = check_bounds_or_overlap (m_ptr_qry, call, dst, src, dstwr, NULL_TREE); /* Avoid diagnosing the call again. */ suppress_warning (call, opt); @@ -2006,25 +2001,26 @@ check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize, tree srcsize, bool bounds_only /* = false */, bool do_warn /* = true */) { - return check_bounds_or_overlap (/*range_query=*/NULL, + pointer_query ptrqry (get_range_query (cfun)); + return check_bounds_or_overlap (ptrqry, call, dst, src, dstsize, srcsize, bounds_only, do_warn); } opt_code -check_bounds_or_overlap (range_query *query, +check_bounds_or_overlap (pointer_query &ptrqry, gimple *call, tree dst, tree src, tree dstsize, tree srcsize, bool bounds_only /* = false */, bool do_warn /* = true */) { tree func = gimple_call_fndecl (call); - builtin_memref dstref (query, call, dst, dstsize); - builtin_memref srcref (query, call, src, srcsize); + builtin_memref dstref (ptrqry, call, dst, dstsize); + builtin_memref srcref (ptrqry, call, src, srcsize); /* Create a descriptor of the access. This may adjust both DSTREF and SRCREF based on one another and the kind of the access. */ - builtin_access acs (query, call, dstref, srcref); + builtin_access acs (ptrqry, call, dstref, srcref); /* Set STRICT to the value of the -Warray-bounds=N argument for string functions or when N > 1. */ diff --git a/gcc/gimple-ssa-warn-restrict.h b/gcc/gimple-ssa-warn-restrict.h index 1c60f51b500..2bdde030023 100644 --- a/gcc/gimple-ssa-warn-restrict.h +++ b/gcc/gimple-ssa-warn-restrict.h @@ -22,7 +22,7 @@ extern opt_code check_bounds_or_overlap (gimple *, tree, tree, tree, tree, bool = false, bool = true); -extern opt_code check_bounds_or_overlap (class range_query *, gimple *, +extern opt_code check_bounds_or_overlap (class pointer_query &, gimple *, tree, tree, tree, tree, bool = false, bool = true); -- 2.34.1