]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Enable pointer_query caching in -Wrestrict.
authorMartin Sebor <msebor@redhat.com>
Thu, 3 Feb 2022 20:59:39 +0000 (13:59 -0700)
committerMartin Sebor <msebor@redhat.com>
Thu, 3 Feb 2022 20:59:39 +0000 (13:59 -0700)
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
gcc/gimple-ssa-warn-restrict.h

index d1beb01fe89bca2840c5fe0d1c6219d990b0d272..b678e806da373a109d1e24765970bb4112c5feef 100644 (file)
@@ -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.  */
index 1c60f51b5004c3f2c16646bdde50ea6ed56bce05..2bdde030023859e14b2046a1b10a8b327d54d8b3 100644 (file)
@@ -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);