summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2022-02-03 13:59:39 -0700
committerMartin Sebor <msebor@redhat.com>2022-02-03 13:59:39 -0700
commit30d15b512e375dee1b288d66c398513b8cb3e2aa (patch)
treec7b61bd35b5323b8b7000761cee3270d32f82dda
parenta62b740d7b8bff2d8b5578d01d00e5fe464e5325 (diff)
downloadgcc-30d15b512e375dee1b288d66c398513b8cb3e2aa.tar.gz
Enable pointer_query caching in -Wrestrict.
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.
-rw-r--r--gcc/gimple-ssa-warn-restrict.cc126
-rw-r--r--gcc/gimple-ssa-warn-restrict.h2
2 files changed, 61 insertions, 67 deletions
diff --git a/gcc/gimple-ssa-warn-restrict.cc b/gcc/gimple-ssa-warn-restrict.cc
index d1beb01fe89..b678e806da3 100644
--- a/gcc/gimple-ssa-warn-restrict.cc
+++ b/gcc/gimple-ssa-warn-restrict.cc
@@ -62,46 +62,61 @@ 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)
- { }
-
- opt_pass *clone () { return new pass_wrestrict (m_ctxt); }
+ pass_wrestrict (gcc::context *);
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 +160,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 +168,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 +202,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 +241,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 +254,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 +273,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,9 +350,9 @@ 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))
+ if (m_ptr_qry.rvals->range_of_expr (vr, offset, stmt))
{
rng = vr.kind ();
if (!vr.undefined_p ())
@@ -345,19 +361,7 @@ builtin_memref::extend_offset_range (tree offset)
max = wi::to_wide (vr.max ());
}
}
- else
- {
- /* 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 ())
- {
- min = wi::to_wide (vr.min ());
- 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 +678,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 +770,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 +807,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 +1888,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 +1979,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 +1999,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);