LCOV - code coverage report
Current view: top level - gcc - gimple-ssa-warn-restrict.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 90.6 % 861 780
Test Date: 2024-04-20 14:03:02 Functions: 82.1 % 28 23
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Pass to detect and issue warnings for violations of the restrict
       2                 :             :    qualifier.
       3                 :             :    Copyright (C) 2017-2024 Free Software Foundation, Inc.
       4                 :             :    Contributed by Martin Sebor <msebor@redhat.com>.
       5                 :             : 
       6                 :             :    This file is part of GCC.
       7                 :             : 
       8                 :             :    GCC is free software; you can redistribute it and/or modify it under
       9                 :             :    the terms of the GNU General Public License as published by the Free
      10                 :             :    Software Foundation; either version 3, or (at your option) any later
      11                 :             :    version.
      12                 :             : 
      13                 :             :    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      14                 :             :    WARRANTY; without even the implied warranty of MERCHANTABILITY or
      15                 :             :    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      16                 :             :    for more details.
      17                 :             : 
      18                 :             :    You should have received a copy of the GNU General Public License
      19                 :             :    along with GCC; see the file COPYING3.  If not see
      20                 :             :    <http://www.gnu.org/licenses/>.  */
      21                 :             : 
      22                 :             : #include "config.h"
      23                 :             : #include "system.h"
      24                 :             : #include "coretypes.h"
      25                 :             : #include "backend.h"
      26                 :             : #include "tree.h"
      27                 :             : #include "gimple.h"
      28                 :             : #include "tree-pass.h"
      29                 :             : #include "pointer-query.h"
      30                 :             : #include "ssa.h"
      31                 :             : #include "gimple-pretty-print.h"
      32                 :             : #include "gimple-ssa-warn-access.h"
      33                 :             : #include "gimple-ssa-warn-restrict.h"
      34                 :             : #include "diagnostic-core.h"
      35                 :             : #include "fold-const.h"
      36                 :             : #include "gimple-iterator.h"
      37                 :             : #include "tree-dfa.h"
      38                 :             : #include "tree-ssa.h"
      39                 :             : #include "tree-cfg.h"
      40                 :             : #include "tree-object-size.h"
      41                 :             : #include "calls.h"
      42                 :             : #include "cfgloop.h"
      43                 :             : #include "intl.h"
      44                 :             : #include "gimple-range.h"
      45                 :             : 
      46                 :             : namespace {
      47                 :             : 
      48                 :             : const pass_data pass_data_wrestrict = {
      49                 :             :   GIMPLE_PASS,
      50                 :             :   "wrestrict",
      51                 :             :   OPTGROUP_NONE,
      52                 :             :   TV_NONE,
      53                 :             :   PROP_cfg, /* Properties_required.  */
      54                 :             :   0,        /* properties_provided.  */
      55                 :             :   0,        /* properties_destroyed.  */
      56                 :             :   0,        /* properties_start */
      57                 :             :   0,        /* properties_finish */
      58                 :             : };
      59                 :             : 
      60                 :             : /* Pass to detect violations of strict aliasing requirements in calls
      61                 :             :    to built-in string and raw memory functions.  */
      62                 :             : class pass_wrestrict : public gimple_opt_pass
      63                 :             : {
      64                 :             :  public:
      65                 :             :   pass_wrestrict (gcc::context *);
      66                 :             : 
      67                 :             :   bool gate (function *) final override;
      68                 :             :   unsigned int execute (function *) final override;
      69                 :             : 
      70                 :             :   void check_call (gimple *);
      71                 :             : 
      72                 :             :   void check_block (basic_block);
      73                 :             : 
      74                 :             :   /* A pointer_query object to store information about pointers and
      75                 :             :      their targets in.  */
      76                 :             :   pointer_query m_ptr_qry;
      77                 :             : };
      78                 :             : 
      79                 :      281914 : pass_wrestrict::pass_wrestrict (gcc::context *ctxt)
      80                 :             :   : gimple_opt_pass (pass_data_wrestrict, ctxt),
      81                 :      281914 :     m_ptr_qry ()
      82                 :      281914 : { }
      83                 :             : 
      84                 :             : bool
      85                 :      985383 : pass_wrestrict::gate (function *fun ATTRIBUTE_UNUSED)
      86                 :             : {
      87                 :      985383 :   return warn_array_bounds || warn_restrict || warn_stringop_overflow;
      88                 :             : }
      89                 :             : 
      90                 :             : void
      91                 :     9192916 : pass_wrestrict::check_block (basic_block bb)
      92                 :             : {
      93                 :             :   /* Iterate over statements, looking for function calls.  */
      94                 :    91421180 :   for (auto si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
      95                 :             :     {
      96                 :    73035348 :       gimple *stmt = gsi_stmt (si);
      97                 :    73035348 :       if (!is_gimple_call (stmt))
      98                 :    68229916 :         continue;
      99                 :             : 
     100                 :     4805432 :       check_call (stmt);
     101                 :             :     }
     102                 :     9192916 : }
     103                 :             : 
     104                 :             : unsigned
     105                 :      985185 : pass_wrestrict::execute (function *fun)
     106                 :             : {
     107                 :             :   /* Create a new ranger instance and associate it with FUN.  */
     108                 :      985185 :   m_ptr_qry.rvals = enable_ranger (fun);
     109                 :             : 
     110                 :      985185 :   basic_block bb;
     111                 :    10178101 :   FOR_EACH_BB_FN (bb, fun)
     112                 :     9192916 :     check_block (bb);
     113                 :             : 
     114                 :      985185 :   m_ptr_qry.flush_cache ();
     115                 :             : 
     116                 :             :   /* Release the ranger instance and replace it with a global ranger.
     117                 :             :      Also reset the pointer since calling disable_ranger() deletes it.  */
     118                 :      985185 :   disable_ranger (fun);
     119                 :      985185 :   m_ptr_qry.rvals = NULL;
     120                 :             : 
     121                 :      985185 :   return 0;
     122                 :             : }
     123                 :             : 
     124                 :             : /* Description of a memory reference by a built-in function.  This
     125                 :             :    is similar to ao_ref but made especially suitable for -Wrestrict
     126                 :             :    and not for optimization.  */
     127                 :             : class builtin_memref
     128                 :             : {
     129                 :             : public:
     130                 :             :   /* The original pointer argument to the built-in function.  */
     131                 :             :   tree ptr;
     132                 :             :   /* The referenced subobject or NULL if not available, and the base
     133                 :             :      object of the memory reference or NULL.  */
     134                 :             :   tree ref;
     135                 :             :   tree base;
     136                 :             : 
     137                 :             :   /* The size of the BASE object, PTRDIFF_MAX if indeterminate,
     138                 :             :      and negative until (possibly lazily) initialized.  */
     139                 :             :   offset_int basesize;
     140                 :             :   /* Same for the subobject.  */
     141                 :             :   offset_int refsize;
     142                 :             : 
     143                 :             :   /* The non-negative offset of the referenced subobject.  Used to avoid
     144                 :             :      warnings for (apparently) possibly but not definitively overlapping
     145                 :             :      accesses to member arrays.  Negative when unknown/invalid.  */
     146                 :             :   offset_int refoff;
     147                 :             : 
     148                 :             :   /* The offset range relative to the base.  */
     149                 :             :   offset_int offrange[2];
     150                 :             :   /* The size range of the access to this reference.  */
     151                 :             :   offset_int sizrange[2];
     152                 :             : 
     153                 :             :   /* Cached result of get_max_objsize().  */
     154                 :             :   const offset_int maxobjsize;
     155                 :             : 
     156                 :             :   /* True for "bounded" string functions like strncat, and strncpy
     157                 :             :      and their variants that specify either an exact or upper bound
     158                 :             :      on the size of the accesses they perform.  For strncat both
     159                 :             :      the source and destination references are bounded.  For strncpy
     160                 :             :      only the destination reference is.  */
     161                 :             :   bool strbounded_p;
     162                 :             : 
     163                 :             :   builtin_memref (pointer_query &, gimple *, tree, tree);
     164                 :             : 
     165                 :             :   tree offset_out_of_bounds (int, offset_int[3]) const;
     166                 :             : 
     167                 :             : private:
     168                 :             :   /* Call statement to the built-in.  */
     169                 :             :   gimple *stmt;
     170                 :             : 
     171                 :             :   pointer_query &m_ptr_qry;
     172                 :             : 
     173                 :             :   /* Ctor helper to set or extend OFFRANGE based on argument.  */
     174                 :             :   void extend_offset_range (tree);
     175                 :             : 
     176                 :             :   /*  Ctor helper to determine BASE and OFFRANGE from argument.  */
     177                 :             :   void set_base_and_offset (tree);
     178                 :             : };
     179                 :             : 
     180                 :             : /* Description of a memory access by a raw memory or string built-in
     181                 :             :    function involving a pair of builtin_memref's.  */
     182                 :             : class builtin_access
     183                 :             : {
     184                 :             :  public:
     185                 :             :   /* Destination and source memory reference.  */
     186                 :             :   builtin_memref* const dstref;
     187                 :             :   builtin_memref* const srcref;
     188                 :             :   /* The size range of the access.  It's the greater of the accesses
     189                 :             :      to the two references.  */
     190                 :             :   HOST_WIDE_INT sizrange[2];
     191                 :             : 
     192                 :             :   /* The minimum and maximum offset of an overlap of the access
     193                 :             :      (if it does, in fact, overlap), and the size of the overlap.  */
     194                 :             :   HOST_WIDE_INT ovloff[2];
     195                 :             :   HOST_WIDE_INT ovlsiz[2];
     196                 :             : 
     197                 :             :   /* True to consider valid only accesses to the smallest subobject
     198                 :             :      and false for raw memory functions.  */
     199                 :      167279 :   bool strict () const
     200                 :             :   {
     201                 :      167279 :     return (detect_overlap != &builtin_access::generic_overlap
     202                 :       57430 :             && detect_overlap != &builtin_access::no_overlap);
     203                 :             :   }
     204                 :             : 
     205                 :             :   builtin_access (pointer_query &, gimple *,
     206                 :             :                   builtin_memref &, builtin_memref &);
     207                 :             : 
     208                 :             :   /* Entry point to determine overlap.  */
     209                 :             :   bool overlap ();
     210                 :             : 
     211                 :             :   offset_int write_off (tree) const;
     212                 :             : 
     213                 :             :   void dump (FILE *) const;
     214                 :             : 
     215                 :             :  private:
     216                 :             :   /* Implementation functions used to determine overlap.  */
     217                 :             :   bool generic_overlap ();
     218                 :             :   bool strcat_overlap ();
     219                 :             :   bool strcpy_overlap ();
     220                 :             : 
     221                 :           0 :   bool no_overlap ()
     222                 :             :   {
     223                 :           0 :     return false;
     224                 :             :   }
     225                 :             : 
     226                 :             :   offset_int overlap_size (const offset_int [2], const offset_int[2],
     227                 :             :                            offset_int [2]);
     228                 :             : 
     229                 :             :  private:
     230                 :             :   /* Temporaries used to compute the final result.  */
     231                 :             :   offset_int dstoff[2];
     232                 :             :   offset_int srcoff[2];
     233                 :             :   offset_int dstsiz[2];
     234                 :             :   offset_int srcsiz[2];
     235                 :             : 
     236                 :             :   /* Pointer to a member function to call to determine overlap.  */
     237                 :             :   bool (builtin_access::*detect_overlap) ();
     238                 :             : };
     239                 :             : 
     240                 :             : /* Initialize a memory reference representation from a pointer EXPR and
     241                 :             :    a size SIZE in bytes.  If SIZE is NULL_TREE then the size is assumed
     242                 :             :    to be unknown.  STMT is the statement in which expr appears in.  */
     243                 :             : 
     244                 :      334558 : builtin_memref::builtin_memref (pointer_query &ptrqry, gimple *stmt, tree expr,
     245                 :      334558 :                                 tree size)
     246                 :      334558 : : ptr (expr),
     247                 :      334558 :   ref (),
     248                 :      334558 :   base (),
     249                 :      334558 :   basesize (-1),
     250                 :      334558 :   refsize (-1),
     251                 :      334558 :   refoff (HOST_WIDE_INT_MIN),
     252                 :      334558 :   offrange (),
     253                 :      334558 :   sizrange (),
     254                 :      334558 :   maxobjsize (tree_to_shwi (max_object_size ())),
     255                 :      334558 :   strbounded_p (),
     256                 :      334558 :   stmt (stmt),
     257                 :      334558 :   m_ptr_qry (ptrqry)
     258                 :             : {
     259                 :             :   /* Unfortunately, wide_int default ctor is a no-op so array members
     260                 :             :      of the type must be set individually.  */
     261                 :      334558 :   offrange[0] = offrange[1] = 0;
     262                 :      334558 :   sizrange[0] = sizrange[1] = 0;
     263                 :             : 
     264                 :      334558 :   if (!expr)
     265                 :      213404 :     return;
     266                 :             : 
     267                 :             :   /* Find the BASE object or pointer referenced by EXPR and set
     268                 :             :      the offset range OFFRANGE in the process.  */
     269                 :      305130 :   set_base_and_offset (expr);
     270                 :             : 
     271                 :      305130 :   if (size)
     272                 :             :     {
     273                 :      206709 :       tree range[2];
     274                 :             :       /* Determine the size range, allowing for the result to be [0, 0]
     275                 :             :          for SIZE in the anti-range ~[0, N] where N >= PTRDIFF_MAX.  */
     276                 :      206709 :       get_size_range (m_ptr_qry.rvals, size, stmt, range, SR_ALLOW_ZERO);
     277                 :      206709 :       sizrange[0] = wi::to_offset (range[0]);
     278                 :      206709 :       sizrange[1] = wi::to_offset (range[1]);
     279                 :             :       /* get_size_range returns SIZE_MAX for the maximum size.
     280                 :             :          Constrain it to the real maximum of PTRDIFF_MAX.  */
     281                 :      206709 :       if (sizrange[0] <= maxobjsize && sizrange[1] > maxobjsize)
     282                 :       22643 :         sizrange[1] = maxobjsize;
     283                 :             :     }
     284                 :             :   else
     285                 :       98421 :     sizrange[1] = maxobjsize;
     286                 :             : 
     287                 :      305130 :   if (!DECL_P (base))
     288                 :             :     return;
     289                 :             : 
     290                 :             :   /* If the offset could be in the range of the referenced object
     291                 :             :      constrain its bounds so neither exceeds those of the object.  */
     292                 :      121154 :   if (offrange[0] < 0 && offrange[1] > 0)
     293                 :        1552 :     offrange[0] = 0;
     294                 :             : 
     295                 :      121154 :   offset_int maxoff = maxobjsize;
     296                 :      121154 :   tree basetype = TREE_TYPE (base);
     297                 :      121154 :   if (TREE_CODE (basetype) == ARRAY_TYPE)
     298                 :             :     {
     299                 :       71124 :       if (ref && array_ref_flexible_size_p (ref))
     300                 :             :         ;   /* Use the maximum possible offset for an array that might
     301                 :             :                have flexible size.  */
     302                 :       70663 :       else if (tree basesize = TYPE_SIZE_UNIT (basetype))
     303                 :       68964 :         if (TREE_CODE (basesize) == INTEGER_CST)
     304                 :             :           /* Size could be non-constant for a variable-length type such
     305                 :             :              as a struct with a VLA member (a GCC extension).  */
     306                 :       68964 :           maxoff = wi::to_offset (basesize);
     307                 :             :     }
     308                 :             : 
     309                 :      121154 :   if (offrange[0] >= 0)
     310                 :             :     {
     311                 :      121000 :       if (offrange[1] < 0)
     312                 :         436 :         offrange[1] = offrange[0] <= maxoff ? maxoff : maxobjsize;
     313                 :      120564 :       else if (offrange[0] <= maxoff && offrange[1] > maxoff)
     314                 :        1506 :         offrange[1] = maxoff;
     315                 :             :     }
     316                 :             : }
     317                 :             : 
     318                 :             : /* Based on the initial length of the destination STARTLEN, returns
     319                 :             :    the offset of the first write access from the beginning of
     320                 :             :    the destination.  Nonzero only for strcat-type of calls.  */
     321                 :             : 
     322                 :      167279 : offset_int builtin_access::write_off (tree startlen) const
     323                 :             : {
     324                 :      167279 :   if (detect_overlap != &builtin_access::strcat_overlap
     325                 :        2630 :       || !startlen || TREE_CODE (startlen) != INTEGER_CST)
     326                 :      166196 :     return 0;
     327                 :             : 
     328                 :        1083 :   return wi::to_offset (startlen);
     329                 :             : }
     330                 :             : 
     331                 :             : /* Ctor helper to set or extend OFFRANGE based on the OFFSET argument.
     332                 :             :    Pointer offsets are represented as unsigned sizetype but must be
     333                 :             :    treated as signed.  */
     334                 :             : 
     335                 :             : void
     336                 :       39840 : builtin_memref::extend_offset_range (tree offset)
     337                 :             : {
     338                 :       39840 :   if (TREE_CODE (offset) == INTEGER_CST)
     339                 :             :     {
     340                 :       15729 :       offset_int off = int_cst_value (offset);
     341                 :       15729 :       if (off != 0)
     342                 :             :         {
     343                 :        8499 :           offrange[0] += off;
     344                 :        8499 :           offrange[1] += off;
     345                 :             :         }
     346                 :       15729 :       return;
     347                 :             :     }
     348                 :             : 
     349                 :       24111 :   if (TREE_CODE (offset) == SSA_NAME)
     350                 :             :     {
     351                 :             :       /* A pointer offset is represented as sizetype but treated
     352                 :             :          as signed.  */
     353                 :       24037 :       wide_int min, max;
     354                 :       24037 :       value_range_kind rng = VR_VARYING;
     355                 :       24037 :       value_range vr;
     356                 :       24037 :       if (m_ptr_qry.rvals->range_of_expr (vr, offset, stmt))
     357                 :             :         {
     358                 :       24037 :           tree vr_min, vr_max;
     359                 :       24037 :           rng = get_legacy_range (vr, vr_min, vr_max);
     360                 :       24037 :           if (!vr.undefined_p ())
     361                 :             :             {
     362                 :       24037 :               min = wi::to_wide (vr_min);
     363                 :       24037 :               max = wi::to_wide (vr_max);
     364                 :             :             }
     365                 :             :         }
     366                 :             : 
     367                 :       24037 :       if (rng == VR_ANTI_RANGE && wi::lts_p (max, min))
     368                 :             :         {
     369                 :             :           /* Convert an anti-range whose upper bound is less than
     370                 :             :              its lower bound to a signed range.  */
     371                 :        1018 :           offrange[0] += offset_int::from (max + 1, SIGNED);
     372                 :        1018 :           offrange[1] += offset_int::from (min - 1, SIGNED);
     373                 :        1018 :           return;
     374                 :             :         }
     375                 :             : 
     376                 :       23019 :       if (rng == VR_RANGE
     377                 :       23019 :           && (DECL_P (base) || wi::lts_p (min, max)))
     378                 :             :         {
     379                 :             :           /* Preserve the bounds of the range for an offset into
     380                 :             :              a known object (it may be adjusted later relative to
     381                 :             :              a constant offset from its beginning).  Otherwise use
     382                 :             :              the bounds only when they are ascending when treated
     383                 :             :              as signed.  */
     384                 :        6705 :           offrange[0] += offset_int::from (min, SIGNED);
     385                 :        6705 :           offrange[1] += offset_int::from (max, SIGNED);
     386                 :        6705 :           return;
     387                 :             :         }
     388                 :             : 
     389                 :             :       /* Handle an anti-range the same as no range at all.  */
     390                 :       16314 :       gimple *stmt = SSA_NAME_DEF_STMT (offset);
     391                 :       16314 :       tree type;
     392                 :       16314 :       if (is_gimple_assign (stmt)
     393                 :       11705 :           && (type = TREE_TYPE (gimple_assign_rhs1 (stmt)))
     394                 :       11705 :           && INTEGRAL_TYPE_P (type)
     395                 :       28019 :           && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (offset)))
     396                 :             :         {
     397                 :       11704 :           tree_code code = gimple_assign_rhs_code (stmt);
     398                 :       11704 :           if (code == NOP_EXPR)
     399                 :             :             {
     400                 :             :               /* Use the bounds of the type of the NOP_EXPR operand
     401                 :             :                  even if it's signed.  The result doesn't trigger
     402                 :             :                  warnings but makes their output more readable.  */
     403                 :        4130 :               offrange[0] += wi::to_offset (TYPE_MIN_VALUE (type));
     404                 :        4130 :               offrange[1] += wi::to_offset (TYPE_MAX_VALUE (type));
     405                 :        4130 :               return;
     406                 :             :             }
     407                 :             :         }
     408                 :       24037 :     }
     409                 :             : 
     410                 :       12258 :   const offset_int maxoff = tree_to_shwi (max_object_size ()) >> 1;
     411                 :       12258 :   const offset_int minoff = -maxoff - 1;
     412                 :             : 
     413                 :       12258 :   offrange[0] += minoff;
     414                 :       12258 :   offrange[1] += maxoff;
     415                 :             : }
     416                 :             : 
     417                 :             : /* Determines the base object or pointer of the reference EXPR
     418                 :             :    and the offset range from the beginning of the base.  */
     419                 :             : 
     420                 :             : void
     421                 :      338065 : builtin_memref::set_base_and_offset (tree expr)
     422                 :             : {
     423                 :      338065 :   tree offset = NULL_TREE;
     424                 :             : 
     425                 :      338065 :   if (TREE_CODE (expr) == SSA_NAME)
     426                 :             :     {
     427                 :             :       /* Try to tease the offset out of the pointer.  */
     428                 :      188450 :       gimple *stmt = SSA_NAME_DEF_STMT (expr);
     429                 :      188450 :       if (!base
     430                 :      155515 :           && gimple_assign_single_p (stmt)
     431                 :      232586 :           && gimple_assign_rhs_code (stmt) == ADDR_EXPR)
     432                 :        9597 :         expr = gimple_assign_rhs1 (stmt);
     433                 :      178853 :       else if (is_gimple_assign (stmt))
     434                 :             :         {
     435                 :       89012 :           tree_code code = gimple_assign_rhs_code (stmt);
     436                 :       89012 :           if (CONVERT_EXPR_CODE_P (code))
     437                 :             :             {
     438                 :       12658 :               tree rhs = gimple_assign_rhs1 (stmt);
     439                 :       12658 :               if (POINTER_TYPE_P (TREE_TYPE (rhs)))
     440                 :             :                 expr = gimple_assign_rhs1 (stmt);
     441                 :             :               else
     442                 :             :                 {
     443                 :       12658 :                   base = expr;
     444                 :      147981 :                   return;
     445                 :             :                 }
     446                 :             :             }
     447                 :       76354 :           else if (code == POINTER_PLUS_EXPR)
     448                 :             :             {
     449                 :       30872 :               expr = gimple_assign_rhs1 (stmt);
     450                 :       30872 :               offset = gimple_assign_rhs2 (stmt);
     451                 :             :             }
     452                 :             :           else
     453                 :             :             {
     454                 :       45482 :               base = expr;
     455                 :       45482 :               return;
     456                 :             :             }
     457                 :             :         }
     458                 :             :       else
     459                 :             :         {
     460                 :             :           /* FIXME: Handle PHI nodes in case like:
     461                 :             :              _12 = &MEM[(void *)&a + 2B] + _10;
     462                 :             : 
     463                 :             :              <bb> [local count: 1073741824]:
     464                 :             :              # prephitmp_13 = PHI <_12, &MEM[(void *)&a + 2B]>
     465                 :             :              memcpy (prephitmp_13, p_7(D), 6);  */
     466                 :       89841 :           base = expr;
     467                 :       89841 :           return;
     468                 :             :         }
     469                 :             :     }
     470                 :             : 
     471                 :      190084 :   if (TREE_CODE (expr) == ADDR_EXPR)
     472                 :      153056 :     expr = TREE_OPERAND (expr, 0);
     473                 :             : 
     474                 :             :   /* Stash the reference for offset validation.  */
     475                 :      190084 :   ref = expr;
     476                 :             : 
     477                 :      190084 :   poly_int64 bitsize, bitpos;
     478                 :      190084 :   tree var_off;
     479                 :      190084 :   machine_mode mode;
     480                 :      190084 :   int sign, reverse, vol;
     481                 :             : 
     482                 :             :   /* Determine the base object or pointer of the reference and
     483                 :             :      the constant bit offset from the beginning of the base.
     484                 :             :      If the offset has a non-constant component, it will be in
     485                 :             :      VAR_OFF.  MODE, SIGN, REVERSE, and VOL are write only and
     486                 :             :      unused here.  */
     487                 :      190084 :   base = get_inner_reference (expr, &bitsize, &bitpos, &var_off,
     488                 :             :                               &mode, &sign, &reverse, &vol);
     489                 :             : 
     490                 :             :   /* get_inner_reference is not expected to return null.  */
     491                 :      190084 :   gcc_assert (base != NULL);
     492                 :             : 
     493                 :      190084 :   if (offset)
     494                 :       30872 :     extend_offset_range (offset);
     495                 :             : 
     496                 :      190084 :   poly_int64 bytepos = exact_div (bitpos, BITS_PER_UNIT);
     497                 :             : 
     498                 :             :   /* Convert the poly_int64 offset to offset_int.  The offset
     499                 :             :      should be constant but be prepared for it not to be just in
     500                 :             :      case.  */
     501                 :      190084 :   offset_int cstoff;
     502                 :      190084 :   if (bytepos.is_constant (&cstoff))
     503                 :             :     {
     504                 :      190084 :       offrange[0] += cstoff;
     505                 :      190084 :       offrange[1] += cstoff;
     506                 :             : 
     507                 :             :       /* Besides the reference saved above, also stash the offset
     508                 :             :          for validation.  */
     509                 :      190084 :       if (TREE_CODE (expr) == COMPONENT_REF)
     510                 :       25016 :         refoff = cstoff;
     511                 :             :     }
     512                 :             :   else
     513                 :             :     offrange[1] += maxobjsize;
     514                 :             : 
     515                 :      190084 :   if (var_off)
     516                 :             :     {
     517                 :        1709 :       if (TREE_CODE (var_off) == INTEGER_CST)
     518                 :             :         {
     519                 :          22 :           cstoff = wi::to_offset (var_off);
     520                 :          22 :           offrange[0] += cstoff;
     521                 :          22 :           offrange[1] += cstoff;
     522                 :             :         }
     523                 :             :       else
     524                 :        1687 :         offrange[1] += maxobjsize;
     525                 :             :     }
     526                 :             : 
     527                 :      190084 :   if (TREE_CODE (base) == MEM_REF)
     528                 :             :     {
     529                 :        8968 :       tree memrefoff = fold_convert (ptrdiff_type_node, TREE_OPERAND (base, 1));
     530                 :        8968 :       extend_offset_range (memrefoff);
     531                 :             : 
     532                 :       12286 :       if (refoff != HOST_WIDE_INT_MIN
     533                 :        8968 :           && TREE_CODE (expr) == COMPONENT_REF)
     534                 :             :         {
     535                 :             :           /* Bump up the offset of the referenced subobject to reflect
     536                 :             :              the offset to the enclosing object.  For example, so that
     537                 :             :              in
     538                 :             :                struct S { char a, b[3]; } s[2];
     539                 :             :                strcpy (s[1].b, "1234");
     540                 :             :              REFOFF is set to s[1].b - (char*)s.  */
     541                 :        5650 :           offset_int off = tree_to_shwi (memrefoff);
     542                 :        5650 :           refoff += off;
     543                 :             : 
     544                 :        5650 :           if (!integer_zerop (memrefoff)
     545                 :        1344 :               && !COMPLETE_TYPE_P (TREE_TYPE (expr))
     546                 :        5657 :               && multiple_of_p (sizetype, memrefoff,
     547                 :           7 :                                 TYPE_SIZE_UNIT (TREE_TYPE (base)), true))
     548                 :             :             /* A non-zero offset into an array of struct with flexible array
     549                 :             :                members implies that the array is empty because there is no
     550                 :             :                way to initialize such a member when it belongs to an array.
     551                 :             :                This must be some sort of a bug.  */
     552                 :           7 :             refsize = 0;
     553                 :             :         }
     554                 :             : 
     555                 :        8968 :       base = TREE_OPERAND (base, 0);
     556                 :             :     }
     557                 :             : 
     558                 :      190084 :   if (TREE_CODE (ref) == COMPONENT_REF)
     559                 :       25016 :     if (tree size = component_ref_size (ref))
     560                 :       24809 :       if (TREE_CODE (size) == INTEGER_CST)
     561                 :       24791 :         refsize = wi::to_offset (size);
     562                 :             : 
     563                 :      190084 :   if (TREE_CODE (base) == SSA_NAME)
     564                 :       32935 :     set_base_and_offset (base);
     565                 :             : }
     566                 :             : 
     567                 :             : /* Return error_mark_node if the signed offset exceeds the bounds
     568                 :             :    of the address space (PTRDIFF_MAX).  Otherwise, return either BASE
     569                 :             :    or REF when the offset exceeds the bounds of the BASE or REF object,
     570                 :             :    and set OOBOFF to the past-the-end offset formed by the reference,
     571                 :             :    including its size.  OOBOFF is initially setto the range of offsets,
     572                 :             :    and OOBOFF[2] to the offset of the first write access (nonzero for
     573                 :             :    the strcat family).  When STRICT is nonzero use REF size, when
     574                 :             :    available, otherwise use BASE size.  When STRICT is greater than 1,
     575                 :             :    use the size of the last array member as the bound, otherwise treat
     576                 :             :    such a member as a flexible array member.  Return NULL when the offset
     577                 :             :    is in bounds.  */
     578                 :             : 
     579                 :             : tree
     580                 :      333462 : builtin_memref::offset_out_of_bounds (int strict, offset_int ooboff[3]) const
     581                 :             : {
     582                 :      333462 :   if (!ptr)
     583                 :             :     return NULL_TREE;
     584                 :             : 
     585                 :             :   /* The offset of the first write access or zero.  */
     586                 :      304084 :   offset_int wroff = ooboff[2];
     587                 :             : 
     588                 :             :   /* A temporary, possibly adjusted, copy of the offset range.  */
     589                 :      304084 :   offset_int offrng[2] = { ooboff[0], ooboff[1] };
     590                 :             : 
     591                 :      304084 :   if (DECL_P (base) && TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE)
     592                 :             :     {
     593                 :             :       /* Check for offset in an anti-range with a negative lower bound.
     594                 :             :          For such a range, consider only the non-negative subrange.  */
     595                 :       70843 :       if (offrng[1] < offrng[0] && offrng[1] < 0)
     596                 :           0 :         offrng[1] = maxobjsize;
     597                 :             :     }
     598                 :             : 
     599                 :             :   /* Conservative offset of the last byte of the referenced object.  */
     600                 :      304084 :   offset_int endoff;
     601                 :             : 
     602                 :             :   /* The bounds need not be ordered.  Set HIB to use as the index
     603                 :             :      of the larger of the bounds and LOB as the opposite.  */
     604                 :      304084 :   bool hib = wi::les_p (offrng[0], offrng[1]);
     605                 :      304084 :   bool lob = !hib;
     606                 :             : 
     607                 :             :   /* Set to the size remaining in the object after subtracting
     608                 :             :      REFOFF.  It may become negative as a result of negative indices
     609                 :             :      into the enclosing object, such as in:
     610                 :             :        extern struct S { char a[4], b[3], c[1]; } *p;
     611                 :             :        strcpy (p[-3].b, "123");  */
     612                 :      304084 :   offset_int size = basesize;
     613                 :      304084 :   tree obj = base;
     614                 :             : 
     615                 :      304084 :   const bool decl_p = DECL_P (obj);
     616                 :             : 
     617                 :      304084 :   if (basesize < 0)
     618                 :             :     {
     619                 :      147362 :       endoff = offrng[lob] + (sizrange[0] - wroff);
     620                 :             : 
     621                 :             :       /* For a reference through a pointer to an object of unknown size
     622                 :             :          all initial offsets are considered valid, positive as well as
     623                 :             :          negative, since the pointer itself can point past the beginning
     624                 :             :          of the object.  However, the sum of the lower bound of the offset
     625                 :             :          and that of the size must be less than or equal than PTRDIFF_MAX.  */
     626                 :      147362 :       if (endoff > maxobjsize)
     627                 :          88 :         return error_mark_node;
     628                 :             : 
     629                 :             :       /* When the referenced subobject is known, the end offset must be
     630                 :             :          within its bounds.  Otherwise there is nothing to do.  */
     631                 :      147274 :       if (strict
     632                 :      147274 :           && !decl_p
     633                 :        1631 :           && ref
     634                 :         800 :           && refsize >= 0
     635                 :      147992 :           && TREE_CODE (ref) == COMPONENT_REF)
     636                 :             :         {
     637                 :             :           /* If REFOFF is negative, SIZE will become negative here.  */
     638                 :         664 :           size = refoff + refsize;
     639                 :         664 :           obj = ref;
     640                 :             :         }
     641                 :             :       else
     642                 :      146610 :         return NULL_TREE;
     643                 :             :     }
     644                 :             : 
     645                 :             :   /* A reference to an object of known size must be within the bounds
     646                 :             :      of either the base object or the subobject (see above for when
     647                 :             :      a subobject can be used).  */
     648                 :      157386 :   if ((decl_p && offrng[hib] < 0) || offrng[lob] > size)
     649                 :         279 :     return obj;
     650                 :             : 
     651                 :             :   /* The extent of the reference must also be within the bounds of
     652                 :             :      the base object (if known) or the subobject or the maximum object
     653                 :             :      size otherwise.  */
     654                 :      157107 :   endoff = offrng[lob] + sizrange[0];
     655                 :      157107 :   if (endoff > maxobjsize)
     656                 :          23 :     return error_mark_node;
     657                 :             : 
     658                 :      157084 :   if (strict
     659                 :      157084 :       && decl_p
     660                 :        3463 :       && ref
     661                 :      157110 :       && refsize >= 0
     662                 :      157741 :       && TREE_CODE (ref) == COMPONENT_REF)
     663                 :             :     {
     664                 :             :       /* If the reference is to a member subobject of a declared object,
     665                 :             :          the offset must be within the bounds of the subobject.  */
     666                 :         631 :       size = refoff + refsize;
     667                 :         631 :       obj = ref;
     668                 :             :     }
     669                 :             : 
     670                 :      157084 :   if (endoff <= size)
     671                 :             :     return NULL_TREE;
     672                 :             : 
     673                 :             :   /* Set the out-of-bounds offset range to be one greater than
     674                 :             :      that delimited by the reference including its size.  */
     675                 :        2341 :   ooboff[lob] = size;
     676                 :             : 
     677                 :        2341 :   if (endoff > ooboff[lob])
     678                 :        2341 :     ooboff[hib] = endoff - 1;
     679                 :             :   else
     680                 :           0 :     ooboff[hib] = offrng[lob] + sizrange[1];
     681                 :             : 
     682                 :             :   return obj;
     683                 :             : }
     684                 :             : 
     685                 :             : /* Create an association between the memory references DST and SRC
     686                 :             :    for access by a call EXPR to a memory or string built-in funtion.  */
     687                 :             : 
     688                 :      167279 : builtin_access::builtin_access (pointer_query &ptrqry, gimple *call,
     689                 :             :                                 builtin_memref &dst,
     690                 :      167279 :                                 builtin_memref &src)
     691                 :     1170953 : : dstref (&dst), srcref (&src), sizrange (), ovloff (), ovlsiz (),
     692                 :      167279 :   dstoff (), srcoff (), dstsiz (), srcsiz ()
     693                 :             : {
     694                 :      167279 :   dstoff[0] = dst.offrange[0];
     695                 :      167279 :   dstoff[1] = dst.offrange[1];
     696                 :             : 
     697                 :             :   /* Zero out since the offset_int ctors invoked above are no-op.  */
     698                 :      167279 :   srcoff[0] = srcoff[1] = 0;
     699                 :      167279 :   dstsiz[0] = dstsiz[1] = 0;
     700                 :      167279 :   srcsiz[0] = srcsiz[1] = 0;
     701                 :             : 
     702                 :             :   /* Object Size Type to use to determine the size of the destination
     703                 :             :      and source objects.  Overridden below for raw memory functions.  */
     704                 :      167279 :   int ostype = 1;
     705                 :             : 
     706                 :             :   /* True when the size of one reference depends on the offset of
     707                 :             :      itself or the other.  */
     708                 :      167279 :   bool depends_p = true;
     709                 :             : 
     710                 :             :   /* True when the size of the destination reference DSTREF has been
     711                 :             :      determined from SRCREF and so needs to be adjusted by the latter's
     712                 :             :      offset.  Only meaningful for bounded string functions like strncpy.  */
     713                 :      167279 :   bool dstadjust_p = false;
     714                 :             : 
     715                 :             :   /* The size argument number (depends on the built-in).  */
     716                 :      167279 :   unsigned sizeargno = 2;
     717                 :             : 
     718                 :      167279 :   tree func = gimple_call_fndecl (call);
     719                 :      167279 :   switch (DECL_FUNCTION_CODE (func))
     720                 :             :     {
     721                 :      109849 :     case BUILT_IN_MEMCPY:
     722                 :      109849 :     case BUILT_IN_MEMCPY_CHK:
     723                 :      109849 :     case BUILT_IN_MEMPCPY:
     724                 :      109849 :     case BUILT_IN_MEMPCPY_CHK:
     725                 :      109849 :       ostype = 0;
     726                 :      109849 :       depends_p = false;
     727                 :      109849 :       detect_overlap = &builtin_access::generic_overlap;
     728                 :      109849 :       break;
     729                 :             : 
     730                 :       17043 :     case BUILT_IN_MEMMOVE:
     731                 :       17043 :     case BUILT_IN_MEMMOVE_CHK:
     732                 :             :       /* For memmove there is never any overlap to check for.  */
     733                 :       17043 :       ostype = 0;
     734                 :       17043 :       depends_p = false;
     735                 :       17043 :       detect_overlap = &builtin_access::no_overlap;
     736                 :       17043 :       break;
     737                 :             : 
     738                 :       29421 :     case BUILT_IN_MEMSET:
     739                 :       29421 :     case BUILT_IN_MEMSET_CHK:
     740                 :             :       /* For memset there is never any overlap to check for.  */
     741                 :       29421 :       ostype = 0;
     742                 :       29421 :       depends_p = false;
     743                 :       29421 :       detect_overlap = &builtin_access::no_overlap;
     744                 :       29421 :       break;
     745                 :             : 
     746                 :        4366 :     case BUILT_IN_STPNCPY:
     747                 :        4366 :     case BUILT_IN_STPNCPY_CHK:
     748                 :        4366 :     case BUILT_IN_STRNCPY:
     749                 :        4366 :     case BUILT_IN_STRNCPY_CHK:
     750                 :        4366 :       dstref->strbounded_p = true;
     751                 :        4366 :       detect_overlap = &builtin_access::strcpy_overlap;
     752                 :        4366 :       break;
     753                 :             : 
     754                 :        3970 :     case BUILT_IN_STPCPY:
     755                 :        3970 :     case BUILT_IN_STPCPY_CHK:
     756                 :        3970 :     case BUILT_IN_STRCPY:
     757                 :        3970 :     case BUILT_IN_STRCPY_CHK:
     758                 :        3970 :       detect_overlap = &builtin_access::strcpy_overlap;
     759                 :        3970 :       break;
     760                 :             : 
     761                 :        1340 :     case BUILT_IN_STRCAT:
     762                 :        1340 :     case BUILT_IN_STRCAT_CHK:
     763                 :        1340 :       detect_overlap = &builtin_access::strcat_overlap;
     764                 :        1340 :       break;
     765                 :             : 
     766                 :        1290 :     case BUILT_IN_STRNCAT:
     767                 :        1290 :     case BUILT_IN_STRNCAT_CHK:
     768                 :        1290 :       dstref->strbounded_p = true;
     769                 :        1290 :       srcref->strbounded_p = true;
     770                 :        1290 :       detect_overlap = &builtin_access::strcat_overlap;
     771                 :        1290 :       break;
     772                 :             : 
     773                 :             :     default:
     774                 :             :       /* Handle other string functions here whose access may need
     775                 :             :          to be validated for in-bounds offsets and non-overlapping
     776                 :             :          copies.  */
     777                 :           4 :       return;
     778                 :             :     }
     779                 :             : 
     780                 :             :   /* Try to determine the size of the base object.  compute_objsize
     781                 :             :      expects a pointer so create one if BASE is a non-pointer object.  */
     782                 :      167279 :   if (dst.basesize < 0)
     783                 :             :     {
     784                 :      167279 :       access_ref aref;
     785                 :      167279 :       if (ptrqry.get_ref (dst.base, call, &aref, ostype) && aref.base0)
     786                 :       83813 :         dst.basesize = aref.sizrng[1];
     787                 :             :       else
     788                 :       83466 :         dst.basesize = HOST_WIDE_INT_MIN;
     789                 :             :     }
     790                 :             : 
     791                 :      167279 :   if (src.base && src.basesize < 0)
     792                 :             :     {
     793                 :      137851 :       access_ref aref;
     794                 :      137851 :       if (ptrqry.get_ref (src.base, call, &aref, ostype) && aref.base0)
     795                 :       73345 :         src.basesize = aref.sizrng[1];
     796                 :             :       else
     797                 :       64506 :         src.basesize = HOST_WIDE_INT_MIN;
     798                 :             :     }
     799                 :             : 
     800                 :      167279 :   const offset_int maxobjsize = dst.maxobjsize;
     801                 :             : 
     802                 :             :   /* Make adjustments for references to the same object by string
     803                 :             :      built-in functions to reflect the constraints imposed by
     804                 :             :      the function.  */
     805                 :             : 
     806                 :             :   /* For bounded string functions determine the range of the bound
     807                 :             :      on the access.  For others, the range stays unbounded.  */
     808                 :      167279 :   offset_int bounds[2] = { maxobjsize, maxobjsize };
     809                 :      167279 :   if (dstref->strbounded_p)
     810                 :             :     {
     811                 :        5656 :       unsigned nargs = gimple_call_num_args (call);
     812                 :        5656 :       if (nargs <= sizeargno)
     813                 :           4 :         return;
     814                 :             : 
     815                 :        5652 :       tree size = gimple_call_arg (call, sizeargno);
     816                 :        5652 :       tree range[2];
     817                 :        5652 :       if (get_size_range (ptrqry.rvals, size, call, range, true))
     818                 :             :         {
     819                 :        5652 :           bounds[0] = wi::to_offset (range[0]);
     820                 :        5652 :           bounds[1] = wi::to_offset (range[1]);
     821                 :             :         }
     822                 :             : 
     823                 :             :       /* If both references' size ranges are indeterminate use the last
     824                 :             :          (size) argument from the function call as a substitute.  This
     825                 :             :          may only be necessary for strncpy (but not for memcpy where
     826                 :             :          the size range would have been already determined this way).  */
     827                 :        9634 :       if (dstref->sizrange[0] == 0 && dstref->sizrange[1] == maxobjsize
     828                 :        9634 :           && srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize)
     829                 :             :         {
     830                 :        3138 :           dstref->sizrange[0] = bounds[0];
     831                 :        3138 :           dstref->sizrange[1] = bounds[1];
     832                 :             :         }
     833                 :             :     }
     834                 :             : 
     835                 :      167275 :   bool dstsize_set = false;
     836                 :             :   /* The size range of one reference involving the same base object
     837                 :             :      can be determined from the size range of the other reference.
     838                 :             :      This makes it possible to compute accurate offsets for warnings
     839                 :             :      involving functions like strcpy where the length of just one of
     840                 :             :      the two arguments is known (determined by tree-ssa-strlen).  */
     841                 :      167275 :   if (dstref->sizrange[0] == 0 && dstref->sizrange[1] == maxobjsize)
     842                 :             :     {
     843                 :             :       /* When the destination size is unknown set it to the size of
     844                 :             :          the source.  */
     845                 :       12759 :       dstref->sizrange[0] = srcref->sizrange[0];
     846                 :       12759 :       dstref->sizrange[1] = srcref->sizrange[1];
     847                 :       12759 :       dstsize_set = true;
     848                 :             :     }
     849                 :      154516 :   else if (srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize)
     850                 :             :     {
     851                 :             :       /* When the size of the source access is unknown set it to the size
     852                 :             :          of the destination first and adjust it later if necessary.  */
     853                 :       84315 :       srcref->sizrange[0] = dstref->sizrange[0];
     854                 :       84315 :       srcref->sizrange[1] = dstref->sizrange[1];
     855                 :             : 
     856                 :       84315 :       if (depends_p)
     857                 :             :         {
     858                 :        8453 :           if (dstref->strbounded_p)
     859                 :             :             {
     860                 :             :               /* Read access by strncpy is constrained by the third
     861                 :             :                  argument but except for a zero bound is at least one.  */
     862                 :        5335 :               srcref->sizrange[0] = bounds[1] > 0 ? 1 : 0;
     863                 :        5285 :               offset_int bound = wi::umin (srcref->basesize, bounds[1]);
     864                 :        5285 :               if (bound < srcref->sizrange[1])
     865                 :        1132 :                 srcref->sizrange[1] = bound;
     866                 :             :             }
     867                 :             :           /* For string functions, adjust the size range of the source
     868                 :             :              reference by the inverse boundaries of the offset (because
     869                 :             :              the higher the offset into the string the shorter its
     870                 :             :              length).  */
     871                 :        8453 :           if (srcref->offrange[1] >= 0
     872                 :        8453 :               && srcref->offrange[1] < srcref->sizrange[0])
     873                 :        6199 :             srcref->sizrange[0] -= srcref->offrange[1];
     874                 :             :           else
     875                 :        2254 :             srcref->sizrange[0] = 1;
     876                 :             : 
     877                 :        8453 :           if (srcref->offrange[0] > 0)
     878                 :             :             {
     879                 :        1939 :               if (srcref->offrange[0] < srcref->sizrange[1])
     880                 :         507 :                 srcref->sizrange[1] -= srcref->offrange[0];
     881                 :             :               else
     882                 :        1432 :                 srcref->sizrange[1] = 0;
     883                 :             :             }
     884                 :             : 
     885                 :             :           dstadjust_p = true;
     886                 :             :         }
     887                 :             :     }
     888                 :             : 
     889                 :      167275 :   if (detect_overlap == &builtin_access::generic_overlap)
     890                 :             :     {
     891                 :      109849 :       if (dstref->strbounded_p)
     892                 :             :         {
     893                 :           0 :           dstref->sizrange[0] = bounds[0];
     894                 :           0 :           dstref->sizrange[1] = bounds[1];
     895                 :             : 
     896                 :           0 :           if (dstref->sizrange[0] < srcref->sizrange[0])
     897                 :           0 :             srcref->sizrange[0] = dstref->sizrange[0];
     898                 :             : 
     899                 :           0 :           if (dstref->sizrange[1] < srcref->sizrange[1])
     900                 :           0 :             srcref->sizrange[1] = dstref->sizrange[1];
     901                 :             :         }
     902                 :             :     }
     903                 :       57426 :   else if (detect_overlap == &builtin_access::strcpy_overlap)
     904                 :             :     {
     905                 :        8334 :       if (!dstref->strbounded_p)
     906                 :             :         {
     907                 :             :           /* For strcpy, adjust the destination size range to match that
     908                 :             :              of the source computed above.  */
     909                 :        3970 :           if (depends_p && dstadjust_p)
     910                 :             :             {
     911                 :        2487 :               dstref->sizrange[0] = srcref->sizrange[0];
     912                 :        2487 :               dstref->sizrange[1] = srcref->sizrange[1];
     913                 :             :             }
     914                 :             :         }
     915                 :             :     }
     916                 :       49092 :   else if (!dstsize_set && detect_overlap == &builtin_access::strcat_overlap)
     917                 :             :     {
     918                 :        2076 :       dstref->sizrange[0] += srcref->sizrange[0] - 1;
     919                 :        2076 :       dstref->sizrange[1] += srcref->sizrange[1] - 1;
     920                 :             :     }
     921                 :             : 
     922                 :      167275 :   if (dstref->strbounded_p)
     923                 :             :     {
     924                 :             :       /* For strncpy, adjust the destination size range to match that
     925                 :             :          of the source computed above.  */
     926                 :        5652 :       dstref->sizrange[0] = bounds[0];
     927                 :        5652 :       dstref->sizrange[1] = bounds[1];
     928                 :             : 
     929                 :        5652 :       if (bounds[0] < srcref->sizrange[0])
     930                 :        2450 :         srcref->sizrange[0] = bounds[0];
     931                 :             : 
     932                 :        5652 :       if (bounds[1] < srcref->sizrange[1])
     933                 :         211 :         srcref->sizrange[1] = bounds[1];
     934                 :             :     }
     935                 :             : }
     936                 :             : 
     937                 :             : offset_int
     938                 :        7850 : builtin_access::overlap_size (const offset_int a[2], const offset_int b[2],
     939                 :             :                               offset_int *off)
     940                 :             : {
     941                 :        7850 :   const offset_int *p = a;
     942                 :        7850 :   const offset_int *q = b;
     943                 :             : 
     944                 :             :   /* Point P at the bigger of the two ranges and Q at the smaller.  */
     945                 :        7850 :   if (wi::lts_p (a[1] - a[0], b[1] - b[0]))
     946                 :             :     {
     947                 :         408 :       p = b;
     948                 :         408 :       q = a;
     949                 :             :     }
     950                 :             : 
     951                 :        7850 :   if (p[0] < q[0])
     952                 :             :     {
     953                 :        4714 :       if (p[1] < q[0])
     954                 :         309 :         return 0;
     955                 :             : 
     956                 :        4405 :       *off = q[0];
     957                 :        4405 :       return wi::smin (p[1], q[1]) - q[0];
     958                 :             :     }
     959                 :             : 
     960                 :        3136 :   if (q[1] < p[0])
     961                 :          16 :     return 0;
     962                 :             : 
     963                 :        3120 :   off[0] = p[0];
     964                 :        3120 :   return q[1] - p[0];
     965                 :             : }
     966                 :             : 
     967                 :             : /* Return true if the bounded mempry (memcpy amd similar) or string function
     968                 :             :    access (strncpy and similar) ACS overlaps.  */
     969                 :             : 
     970                 :             : bool
     971                 :        2332 : builtin_access::generic_overlap ()
     972                 :             : {
     973                 :        2332 :   builtin_access &acs = *this;
     974                 :        2332 :   const builtin_memref *dstref = acs.dstref;
     975                 :        2332 :   const builtin_memref *srcref = acs.srcref;
     976                 :             : 
     977                 :        2332 :   gcc_assert (dstref->base == srcref->base);
     978                 :             : 
     979                 :        2332 :   const offset_int maxobjsize = acs.dstref->maxobjsize;
     980                 :             : 
     981                 :        2332 :   offset_int maxsize = dstref->basesize < 0 ? maxobjsize : dstref->basesize;
     982                 :             : 
     983                 :             :   /* Adjust the larger bounds of the offsets (which may be the first
     984                 :             :      element if the lower bound is larger than the upper bound) to
     985                 :             :      make them valid for the smallest access (if possible) but no smaller
     986                 :             :      than the smaller bounds.  */
     987                 :        2332 :   gcc_assert (wi::les_p (acs.dstoff[0], acs.dstoff[1]));
     988                 :             : 
     989                 :        2332 :   if (maxsize < acs.dstoff[1] + acs.dstsiz[0])
     990                 :         363 :     acs.dstoff[1] = maxsize - acs.dstsiz[0];
     991                 :        2332 :   if (acs.dstoff[1] < acs.dstoff[0])
     992                 :          13 :     acs.dstoff[1] = acs.dstoff[0];
     993                 :             : 
     994                 :        2332 :   gcc_assert (wi::les_p (acs.srcoff[0], acs.srcoff[1]));
     995                 :             : 
     996                 :        2332 :   if (maxsize < acs.srcoff[1] + acs.srcsiz[0])
     997                 :         199 :     acs.srcoff[1] = maxsize - acs.srcsiz[0];
     998                 :        2332 :   if (acs.srcoff[1] < acs.srcoff[0])
     999                 :          13 :     acs.srcoff[1] = acs.srcoff[0];
    1000                 :             : 
    1001                 :             :   /* Determine the minimum and maximum space for the access given
    1002                 :             :      the offsets.  */
    1003                 :        2332 :   offset_int space[2];
    1004                 :        2332 :   space[0] = wi::abs (acs.dstoff[0] - acs.srcoff[0]);
    1005                 :        2332 :   space[1] = space[0];
    1006                 :             : 
    1007                 :        2332 :   offset_int d = wi::abs (acs.dstoff[0] - acs.srcoff[1]);
    1008                 :        2332 :   if (acs.srcsiz[0] > 0)
    1009                 :             :     {
    1010                 :        2241 :       if (d < space[0])
    1011                 :         115 :         space[0] = d;
    1012                 :             : 
    1013                 :        2241 :       if (space[1] < d)
    1014                 :         448 :         space[1] = d;
    1015                 :             :     }
    1016                 :             :   else
    1017                 :          91 :     space[1] = acs.dstsiz[1];
    1018                 :             : 
    1019                 :        2332 :   d = wi::abs (acs.dstoff[1] - acs.srcoff[0]);
    1020                 :        2332 :   if (d < space[0])
    1021                 :          72 :     space[0] = d;
    1022                 :             : 
    1023                 :        2332 :   if (space[1] < d)
    1024                 :         369 :     space[1] = d;
    1025                 :             : 
    1026                 :             :   /* Treat raw memory functions both of whose references are bounded
    1027                 :             :      as special and permit uncertain overlaps to go undetected.  For
    1028                 :             :      all kinds of constant offset and constant size accesses, if
    1029                 :             :      overlap isn't certain it is not possible.  */
    1030                 :        2332 :   bool overlap_possible = space[0] < acs.dstsiz[1];
    1031                 :        2332 :   if (!overlap_possible)
    1032                 :             :     return false;
    1033                 :             : 
    1034                 :         950 :   bool overlap_certain = space[1] < acs.dstsiz[0];
    1035                 :             : 
    1036                 :             :   /* True when the size of one reference depends on the offset of
    1037                 :             :      the other.  */
    1038                 :         950 :   bool depends_p = detect_overlap != &builtin_access::generic_overlap;
    1039                 :             : 
    1040                 :         950 :   if (!overlap_certain)
    1041                 :             :     {
    1042                 :         474 :       if (!dstref->strbounded_p && !depends_p)
    1043                 :             :         /* Memcpy only considers certain overlap.  */
    1044                 :             :         return false;
    1045                 :             : 
    1046                 :             :       /* There's no way to distinguish an access to the same member
    1047                 :             :          of a structure from one to two distinct members of the same
    1048                 :             :          structure.  Give up to avoid excessive false positives.  */
    1049                 :         175 :       tree basetype = TREE_TYPE (dstref->base);
    1050                 :             : 
    1051                 :         175 :       if (POINTER_TYPE_P (basetype))
    1052                 :          17 :         basetype = TREE_TYPE (basetype);
    1053                 :             :       else
    1054                 :         324 :         while (TREE_CODE (basetype) == ARRAY_TYPE)
    1055                 :         166 :           basetype = TREE_TYPE (basetype);
    1056                 :             : 
    1057                 :         175 :       if (RECORD_OR_UNION_TYPE_P (basetype))
    1058                 :             :         return false;
    1059                 :             :     }
    1060                 :             : 
    1061                 :             :   /* True for stpcpy and strcpy.  */
    1062                 :        1218 :   bool stxcpy_p = (!dstref->strbounded_p
    1063                 :         609 :                    && detect_overlap == &builtin_access::strcpy_overlap);
    1064                 :             : 
    1065                 :         609 :   if (dstref->refoff >= 0
    1066                 :          14 :       && srcref->refoff >= 0
    1067                 :           5 :       && dstref->refoff != srcref->refoff
    1068                 :         611 :       && (stxcpy_p || dstref->strbounded_p || srcref->strbounded_p))
    1069                 :           2 :     return false;
    1070                 :             : 
    1071                 :         607 :   offset_int siz[2] = { maxobjsize + 1, 0 };
    1072                 :             : 
    1073                 :         607 :   ovloff[0] = HOST_WIDE_INT_MAX;
    1074                 :         607 :   ovloff[1] = HOST_WIDE_INT_MIN;
    1075                 :             : 
    1076                 :         607 :   if (stxcpy_p)
    1077                 :             :     {
    1078                 :             :       /* Iterate over the extreme locations (on the horizontal axis formed
    1079                 :             :          by their offsets) and sizes of two regions and find their smallest
    1080                 :             :          and largest overlap and the corresponding offsets.  */
    1081                 :         399 :       for (unsigned i = 0; i != 2; ++i)
    1082                 :             :         {
    1083                 :         266 :           const offset_int a[2] = {
    1084                 :         532 :             acs.dstoff[i], acs.dstoff[i] + acs.dstsiz[!i]
    1085                 :         266 :           };
    1086                 :             : 
    1087                 :         266 :           const offset_int b[2] = {
    1088                 :         532 :             acs.srcoff[i], acs.srcoff[i] + acs.srcsiz[!i]
    1089                 :         266 :           };
    1090                 :             : 
    1091                 :         266 :           offset_int off;
    1092                 :         266 :           offset_int sz = overlap_size (a, b, &off);
    1093                 :         266 :           if (sz < siz[0])
    1094                 :         225 :             siz[0] = sz;
    1095                 :             : 
    1096                 :         266 :           if (siz[1] <= sz)
    1097                 :         174 :             siz[1] = sz;
    1098                 :             : 
    1099                 :         266 :           if (sz != 0)
    1100                 :             :             {
    1101                 :         199 :               if (wi::lts_p (off, ovloff[0]))
    1102                 :         133 :                 ovloff[0] = off.to_shwi ();
    1103                 :         199 :               if (wi::lts_p (ovloff[1], off))
    1104                 :         158 :                 ovloff[1] = off.to_shwi ();
    1105                 :             :             }
    1106                 :             :         }
    1107                 :             :     }
    1108                 :             :   else
    1109                 :             :     {
    1110                 :             :       /* Iterate over the extreme locations (on the horizontal axis
    1111                 :             :          formed by their offsets) and sizes of the two regions and
    1112                 :             :          find their smallest and largest overlap and the corresponding
    1113                 :             :          offsets.  */
    1114                 :             : 
    1115                 :        1422 :       for (unsigned io = 0; io != 2; ++io)
    1116                 :        2844 :         for (unsigned is = 0; is != 2; ++is)
    1117                 :             :           {
    1118                 :        1896 :             const offset_int a[2] = {
    1119                 :        1896 :               acs.dstoff[io], acs.dstoff[io] + acs.dstsiz[is]
    1120                 :        1896 :             };
    1121                 :             : 
    1122                 :        5688 :             for (unsigned jo = 0; jo != 2; ++jo)
    1123                 :       11376 :               for (unsigned js = 0; js != 2; ++js)
    1124                 :             :                 {
    1125                 :        7584 :                   const offset_int b[2] = {
    1126                 :       15168 :                     acs.srcoff[jo], acs.srcoff[jo] + acs.srcsiz[js]
    1127                 :        7584 :                   };
    1128                 :             : 
    1129                 :        7584 :                   offset_int off;
    1130                 :        7584 :                   offset_int sz = overlap_size (a, b, &off);
    1131                 :        7584 :                   if (sz < siz[0])
    1132                 :         626 :                     siz[0] = sz;
    1133                 :             : 
    1134                 :        7584 :                   if (siz[1] <= sz)
    1135                 :        5467 :                     siz[1] = sz;
    1136                 :             : 
    1137                 :        7584 :                   if (sz != 0)
    1138                 :             :                     {
    1139                 :        7016 :                       if (wi::lts_p (off, ovloff[0]))
    1140                 :         474 :                         ovloff[0] = off.to_shwi ();
    1141                 :        7016 :                       if (wi::lts_p (ovloff[1], off))
    1142                 :         607 :                         ovloff[1] = off.to_shwi ();
    1143                 :             :                     }
    1144                 :             :                 }
    1145                 :             :           }
    1146                 :             :     }
    1147                 :             : 
    1148                 :         607 :   ovlsiz[0] = siz[0].to_shwi ();
    1149                 :         607 :   ovlsiz[1] = siz[1].to_shwi ();
    1150                 :             : 
    1151                 :             :   /* Adjust the overlap offset range to reflect the overlap size range.  */
    1152                 :         607 :   if (ovlsiz[0] == 0 && ovlsiz[1] > 1)
    1153                 :          77 :     ovloff[1] = ovloff[0] + ovlsiz[1] - 1;
    1154                 :             : 
    1155                 :             :   return true;
    1156                 :             : }
    1157                 :             : 
    1158                 :             : /* Return true if the strcat-like access overlaps.  */
    1159                 :             : 
    1160                 :             : bool
    1161                 :         160 : builtin_access::strcat_overlap ()
    1162                 :             : {
    1163                 :         160 :   builtin_access &acs = *this;
    1164                 :         160 :   const builtin_memref *dstref = acs.dstref;
    1165                 :         160 :   const builtin_memref *srcref = acs.srcref;
    1166                 :             : 
    1167                 :         160 :   gcc_assert (dstref->base == srcref->base);
    1168                 :             : 
    1169                 :         160 :   const offset_int maxobjsize = acs.dstref->maxobjsize;
    1170                 :             : 
    1171                 :         160 :   gcc_assert (dstref->base && dstref->base == srcref->base);
    1172                 :             : 
    1173                 :             :   /* Adjust for strcat-like accesses.  */
    1174                 :             : 
    1175                 :             :   /* As a special case for strcat, set the DSTREF offsets to the length
    1176                 :             :      of the destination string since the function starts writing over
    1177                 :             :      its terminating nul, and set the destination size to 1 for the length
    1178                 :             :      of the nul.  */
    1179                 :         160 :   acs.dstoff[0] += dstsiz[0] - srcref->sizrange[0];
    1180                 :         160 :   acs.dstoff[1] += dstsiz[1] - srcref->sizrange[1];
    1181                 :             : 
    1182                 :         160 :   bool strfunc_unknown_args = acs.dstsiz[0] == 0 && acs.dstsiz[1] != 0;
    1183                 :             : 
    1184                 :             :   /* The lower bound is zero when the size is unknown because then
    1185                 :             :      overlap is not certain.  */
    1186                 :         160 :   acs.dstsiz[0] = strfunc_unknown_args ? 0 : 1;
    1187                 :         160 :   acs.dstsiz[1] = 1;
    1188                 :             : 
    1189                 :         160 :   offset_int maxsize = dstref->basesize < 0 ? maxobjsize : dstref->basesize;
    1190                 :             : 
    1191                 :             :   /* For references to the same base object, determine if there's a pair
    1192                 :             :      of valid offsets into the two references such that access between
    1193                 :             :      them doesn't overlap.  Adjust both upper bounds to be valid for
    1194                 :             :      the smaller size (i.e., at most MAXSIZE - SIZE).  */
    1195                 :             : 
    1196                 :         160 :   if (maxsize < acs.dstoff[1] + acs.dstsiz[0])
    1197                 :           5 :     acs.dstoff[1] = maxsize - acs.dstsiz[0];
    1198                 :             : 
    1199                 :         160 :   if (maxsize < acs.srcoff[1] + acs.srcsiz[0])
    1200                 :           2 :     acs.srcoff[1] = maxsize - acs.srcsiz[0];
    1201                 :             : 
    1202                 :             :   /* Check to see if there's enough space for both accesses without
    1203                 :             :      overlap.  Determine the optimistic (maximum) amount of available
    1204                 :             :      space.  */
    1205                 :         160 :   offset_int space;
    1206                 :         160 :   if (acs.dstoff[0] <= acs.srcoff[0])
    1207                 :             :     {
    1208                 :          63 :       if (acs.dstoff[1] < acs.srcoff[1])
    1209                 :          48 :         space = acs.srcoff[1] + acs.srcsiz[0] - acs.dstoff[0];
    1210                 :             :       else
    1211                 :          15 :         space = acs.dstoff[1] + acs.dstsiz[0] - acs.srcoff[0];
    1212                 :             :     }
    1213                 :             :   else
    1214                 :          97 :     space = acs.dstoff[1] + acs.dstsiz[0] - acs.srcoff[0];
    1215                 :             : 
    1216                 :             :   /* Overlap is certain if the distance between the farthest offsets
    1217                 :             :      of the opposite accesses is less than the sum of the lower bounds
    1218                 :             :      of the sizes of the two accesses.  */
    1219                 :         160 :   bool overlap_certain = space < acs.dstsiz[0] + acs.srcsiz[0];
    1220                 :             : 
    1221                 :             :   /* For a constant-offset, constant size access, consider the largest
    1222                 :             :      distance between the offset bounds and the lower bound of the access
    1223                 :             :      size.  If the overlap isn't certain return success.  */
    1224                 :         160 :   if (!overlap_certain
    1225                 :         115 :       && acs.dstoff[0] == acs.dstoff[1]
    1226                 :         104 :       && acs.srcoff[0] == acs.srcoff[1]
    1227                 :          94 :       && acs.dstsiz[0] == acs.dstsiz[1]
    1228                 :         225 :       && acs.srcsiz[0] == acs.srcsiz[1])
    1229                 :             :     return false;
    1230                 :             : 
    1231                 :             :   /* Overlap is not certain but may be possible.  */
    1232                 :             : 
    1233                 :          95 :   offset_int access_min = acs.dstsiz[0] + acs.srcsiz[0];
    1234                 :             : 
    1235                 :             :   /* Determine the conservative (minimum) amount of space.  */
    1236                 :          95 :   space = wi::abs (acs.dstoff[0] - acs.srcoff[0]);
    1237                 :          95 :   offset_int d = wi::abs (acs.dstoff[0] - acs.srcoff[1]);
    1238                 :          95 :   if (d < space)
    1239                 :           7 :     space = d;
    1240                 :          95 :   d = wi::abs (acs.dstoff[1] - acs.srcoff[0]);
    1241                 :          95 :   if (d < space)
    1242                 :           2 :     space = d;
    1243                 :             : 
    1244                 :             :   /* For a strict test (used for strcpy and similar with unknown or
    1245                 :             :      variable bounds or sizes), consider the smallest distance between
    1246                 :             :      the offset bounds and either the upper bound of the access size
    1247                 :             :      if known, or the lower bound otherwise.  */
    1248                 :          95 :   if (access_min <= space && (access_min != 0 || !strfunc_unknown_args))
    1249                 :           0 :     return false;
    1250                 :             : 
    1251                 :             :   /* When strcat overlap is certain it is always a single byte:
    1252                 :             :      the terminating NUL, regardless of offsets and sizes.  When
    1253                 :             :      overlap is only possible its range is [0, 1].  */
    1254                 :          95 :   acs.ovlsiz[0] = dstref->sizrange[0] == dstref->sizrange[1] ? 1 : 0;
    1255                 :          95 :   acs.ovlsiz[1] = 1;
    1256                 :             : 
    1257                 :          95 :   offset_int endoff
    1258                 :          95 :     = dstref->offrange[0] + (dstref->sizrange[0] - srcref->sizrange[0]);
    1259                 :          95 :   if (endoff <= srcref->offrange[0])
    1260                 :          38 :     acs.ovloff[0] = wi::smin (maxobjsize, srcref->offrange[0]).to_shwi ();
    1261                 :             :   else
    1262                 :          57 :     acs.ovloff[0] = wi::smin (maxobjsize, endoff).to_shwi ();
    1263                 :             : 
    1264                 :          95 :   acs.sizrange[0] = wi::smax (wi::abs (endoff - srcref->offrange[0]) + 1,
    1265                 :          95 :                               srcref->sizrange[0]).to_shwi ();
    1266                 :          95 :   if (dstref->offrange[0] == dstref->offrange[1])
    1267                 :             :     {
    1268                 :          87 :       if (srcref->offrange[0] == srcref->offrange[1])
    1269                 :          76 :         acs.ovloff[1] = acs.ovloff[0];
    1270                 :             :       else
    1271                 :          11 :         acs.ovloff[1]
    1272                 :          11 :           = wi::smin (maxobjsize,
    1273                 :          11 :                       srcref->offrange[1] + srcref->sizrange[1]).to_shwi ();
    1274                 :             :     }
    1275                 :             :   else
    1276                 :           8 :     acs.ovloff[1]
    1277                 :           8 :       = wi::smin (maxobjsize,
    1278                 :           8 :                   dstref->offrange[1] + dstref->sizrange[1]).to_shwi ();
    1279                 :             : 
    1280                 :          95 :   if (acs.sizrange[0] == 0)
    1281                 :           0 :     acs.sizrange[0] = 1;
    1282                 :          95 :   acs.sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi ();
    1283                 :          95 :   return true;
    1284                 :             : }
    1285                 :             : 
    1286                 :             : /* Return true if the strcpy-like access overlaps.  */
    1287                 :             : 
    1288                 :             : bool
    1289                 :        1435 : builtin_access::strcpy_overlap ()
    1290                 :             : {
    1291                 :        1435 :   return generic_overlap ();
    1292                 :             : }
    1293                 :             : 
    1294                 :             : /* For a BASE of array type, clamp REFOFF to at most [0, BASE_SIZE]
    1295                 :             :    if known, or [0, MAXOBJSIZE] otherwise.  */
    1296                 :             : 
    1297                 :             : static void
    1298                 :       24510 : clamp_offset (tree base, offset_int refoff[2], offset_int maxobjsize)
    1299                 :             : {
    1300                 :       24510 :   if (!base || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE)
    1301                 :             :     return;
    1302                 :             : 
    1303                 :       10393 :   if (refoff[0] < 0 && refoff[1] >= 0)
    1304                 :           0 :     refoff[0] = 0;
    1305                 :             : 
    1306                 :       10393 :   if (refoff[1] < refoff[0])
    1307                 :             :     {
    1308                 :           5 :       offset_int maxsize =  maxobjsize;
    1309                 :           5 :       if (tree size = TYPE_SIZE_UNIT (TREE_TYPE (base)))
    1310                 :           5 :         maxsize = wi::to_offset (size);
    1311                 :             : 
    1312                 :           5 :       refoff[1] = wi::umin (refoff[1], maxsize);
    1313                 :             :     }
    1314                 :             : }
    1315                 :             : 
    1316                 :             : /* Return true if DSTREF and SRCREF describe accesses that either overlap
    1317                 :             :    one another or that, in order not to overlap, would imply that the size
    1318                 :             :    of the referenced object(s) exceeds the maximum size of an object.  Set
    1319                 :             :    Otherwise, if DSTREF and SRCREF do not definitely overlap (even though
    1320                 :             :    they may overlap in a way that's not apparent from the available data),
    1321                 :             :    return false.  */
    1322                 :             : 
    1323                 :             : bool
    1324                 :       12290 : builtin_access::overlap ()
    1325                 :             : {
    1326                 :       12290 :   builtin_access &acs = *this;
    1327                 :             : 
    1328                 :       12290 :   const offset_int maxobjsize = dstref->maxobjsize;
    1329                 :             : 
    1330                 :       12290 :   acs.sizrange[0] = wi::smax (dstref->sizrange[0],
    1331                 :       12290 :                               srcref->sizrange[0]).to_shwi ();
    1332                 :       12290 :   acs.sizrange[1] = wi::smax (dstref->sizrange[1],
    1333                 :       12290 :                               srcref->sizrange[1]).to_shwi ();
    1334                 :             : 
    1335                 :             :   /* Check to see if the two references refer to regions that are
    1336                 :             :      too large not to overlap in the address space (whose maximum
    1337                 :             :      size is PTRDIFF_MAX).  */
    1338                 :       12290 :   offset_int size = dstref->sizrange[0] + srcref->sizrange[0];
    1339                 :       12290 :   if (maxobjsize < size)
    1340                 :             :     {
    1341                 :          35 :       acs.ovloff[0] = (maxobjsize - dstref->sizrange[0]).to_shwi ();
    1342                 :          35 :       acs.ovlsiz[0] = (size - maxobjsize).to_shwi ();
    1343                 :          35 :       return true;
    1344                 :             :     }
    1345                 :             : 
    1346                 :             :   /* If both base objects aren't known return the maximum possible
    1347                 :             :      offset that would make them not overlap.  */
    1348                 :       12255 :   if (!dstref->base || !srcref->base)
    1349                 :             :     return false;
    1350                 :             : 
    1351                 :             :   /* If the base object is an array adjust the bounds of the offset
    1352                 :             :      to be non-negative and within the bounds of the array if possible.  */
    1353                 :       12255 :   clamp_offset (dstref->base, acs.dstoff, maxobjsize);
    1354                 :             : 
    1355                 :       12255 :   acs.srcoff[0] = srcref->offrange[0];
    1356                 :       12255 :   acs.srcoff[1] = srcref->offrange[1];
    1357                 :             : 
    1358                 :       12255 :   clamp_offset (srcref->base, acs.srcoff, maxobjsize);
    1359                 :             : 
    1360                 :             :   /* When the upper bound of the offset is less than the lower bound
    1361                 :             :      the former is the result of a negative offset being represented
    1362                 :             :      as a large positive value or vice versa.  The resulting range is
    1363                 :             :      a union of two subranges: [MIN, UB] and [LB, MAX].  Since such
    1364                 :             :      a union is not representable using the current data structure
    1365                 :             :      replace it with the full range of offsets.  */
    1366                 :       12255 :   if (acs.dstoff[1] < acs.dstoff[0])
    1367                 :             :     {
    1368                 :           5 :       acs.dstoff[0] = -maxobjsize - 1;
    1369                 :           5 :       acs.dstoff[1] = maxobjsize;
    1370                 :             :     }
    1371                 :             : 
    1372                 :             :   /* Validate the offset and size of each reference on its own first.
    1373                 :             :      This is independent of whether or not the base objects are the
    1374                 :             :      same.  Normally, this would have already been detected and
    1375                 :             :      diagnosed by -Warray-bounds, unless it has been disabled.  */
    1376                 :       12255 :   offset_int maxoff = acs.dstoff[0] + dstref->sizrange[0];
    1377                 :       12255 :   if (maxobjsize < maxoff)
    1378                 :             :     {
    1379                 :          36 :       acs.ovlsiz[0] = (maxoff - maxobjsize).to_shwi ();
    1380                 :          36 :       acs.ovloff[0] = acs.dstoff[0].to_shwi () - acs.ovlsiz[0];
    1381                 :          36 :       return true;
    1382                 :             :     }
    1383                 :             : 
    1384                 :             :   /* Repeat the same as above but for the source offsets.  */
    1385                 :       12219 :   if (acs.srcoff[1] < acs.srcoff[0])
    1386                 :             :     {
    1387                 :           0 :       acs.srcoff[0] = -maxobjsize - 1;
    1388                 :           0 :       acs.srcoff[1] = maxobjsize;
    1389                 :             :     }
    1390                 :             : 
    1391                 :       12219 :   maxoff = acs.srcoff[0] + srcref->sizrange[0];
    1392                 :       12219 :   if (maxobjsize < maxoff)
    1393                 :             :     {
    1394                 :          35 :       acs.ovlsiz[0] = (maxoff - maxobjsize).to_shwi ();
    1395                 :          35 :       acs.ovlsiz[1] = (acs.srcoff[0] + srcref->sizrange[1]
    1396                 :          35 :                        - maxobjsize).to_shwi ();
    1397                 :          35 :       acs.ovloff[0] = acs.srcoff[0].to_shwi () - acs.ovlsiz[0];
    1398                 :          35 :       return true;
    1399                 :             :     }
    1400                 :             : 
    1401                 :       12184 :   if (dstref->base != srcref->base)
    1402                 :             :     return false;
    1403                 :             : 
    1404                 :        2492 :   acs.dstsiz[0] = dstref->sizrange[0];
    1405                 :        2492 :   acs.dstsiz[1] = dstref->sizrange[1];
    1406                 :             : 
    1407                 :        2492 :   acs.srcsiz[0] = srcref->sizrange[0];
    1408                 :        2492 :   acs.srcsiz[1] = srcref->sizrange[1];
    1409                 :             : 
    1410                 :             :   /* Call the appropriate function to determine the overlap.  */
    1411                 :        2492 :   if ((this->*detect_overlap) ())
    1412                 :             :     {
    1413                 :         702 :       if (!sizrange[1])
    1414                 :             :         {
    1415                 :             :           /* Unless the access size range has already been set, do so here.  */
    1416                 :           0 :           sizrange[0] = wi::smax (acs.dstsiz[0], srcref->sizrange[0]).to_shwi ();
    1417                 :           0 :           sizrange[1] = wi::smax (acs.dstsiz[1], srcref->sizrange[1]).to_shwi ();
    1418                 :             :         }
    1419                 :         702 :       return true;
    1420                 :             :     }
    1421                 :             : 
    1422                 :             :   return false;
    1423                 :             : }
    1424                 :             : 
    1425                 :             : /* Attempt to detect and diagnose an overlapping copy in a call expression
    1426                 :             :    EXPR involving an access ACS to a built-in memory or string function.
    1427                 :             :    Return true when one has been detected, false otherwise.  */
    1428                 :             : 
    1429                 :             : static bool
    1430                 :       12290 : maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
    1431                 :             : {
    1432                 :       12290 :   if (!acs.overlap ())
    1433                 :             :     return false;
    1434                 :             : 
    1435                 :         808 :   if (warning_suppressed_p (call, OPT_Wrestrict))
    1436                 :             :     return true;
    1437                 :             : 
    1438                 :             :   /* For convenience.  */
    1439                 :         753 :   const builtin_memref &dstref = *acs.dstref;
    1440                 :         753 :   const builtin_memref &srcref = *acs.srcref;
    1441                 :             : 
    1442                 :             :   /* Determine the range of offsets and sizes of the overlap if it
    1443                 :             :      exists and issue diagnostics.  */
    1444                 :         753 :   HOST_WIDE_INT *ovloff = acs.ovloff;
    1445                 :         753 :   HOST_WIDE_INT *ovlsiz = acs.ovlsiz;
    1446                 :         753 :   HOST_WIDE_INT *sizrange = acs.sizrange;
    1447                 :             : 
    1448                 :         753 :   tree func = gimple_call_fndecl (call);
    1449                 :             : 
    1450                 :             :   /* To avoid a combinatorial explosion of diagnostics format the offsets
    1451                 :             :      or their ranges as strings and use them in the warning calls below.  */
    1452                 :         753 :   char offstr[3][64];
    1453                 :             : 
    1454                 :         753 :   if (dstref.offrange[0] == dstref.offrange[1]
    1455                 :         753 :       || dstref.offrange[1] > HOST_WIDE_INT_MAX)
    1456                 :         555 :     sprintf (offstr[0], HOST_WIDE_INT_PRINT_DEC,
    1457                 :             :              dstref.offrange[0].to_shwi ());
    1458                 :             :   else
    1459                 :         198 :     sprintf (offstr[0],
    1460                 :             :              "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
    1461                 :             :              dstref.offrange[0].to_shwi (),
    1462                 :             :              dstref.offrange[1].to_shwi ());
    1463                 :             : 
    1464                 :         753 :   if (srcref.offrange[0] == srcref.offrange[1]
    1465                 :         753 :       || srcref.offrange[1] > HOST_WIDE_INT_MAX)
    1466                 :         486 :     sprintf (offstr[1],
    1467                 :             :              HOST_WIDE_INT_PRINT_DEC,
    1468                 :             :              srcref.offrange[0].to_shwi ());
    1469                 :             :   else
    1470                 :         267 :     sprintf (offstr[1],
    1471                 :             :              "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
    1472                 :             :              srcref.offrange[0].to_shwi (),
    1473                 :             :              srcref.offrange[1].to_shwi ());
    1474                 :             : 
    1475                 :         753 :   if (ovloff[0] == ovloff[1] || !ovloff[1])
    1476                 :         514 :     sprintf (offstr[2], HOST_WIDE_INT_PRINT_DEC, ovloff[0]);
    1477                 :             :   else
    1478                 :         239 :     sprintf (offstr[2],
    1479                 :             :              "[" HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC "]",
    1480                 :             :              ovloff[0], ovloff[1]);
    1481                 :             : 
    1482                 :         753 :   const offset_int maxobjsize = dstref.maxobjsize;
    1483                 :         753 :   bool must_overlap = ovlsiz[0] > 0;
    1484                 :             : 
    1485                 :         753 :   if (ovlsiz[1] == 0)
    1486                 :          66 :     ovlsiz[1] = ovlsiz[0];
    1487                 :             : 
    1488                 :         753 :   if (must_overlap)
    1489                 :             :     {
    1490                 :             :       /* Issue definitive "overlaps" diagnostic in this block.  */
    1491                 :             : 
    1492                 :         565 :       if (sizrange[0] == sizrange[1])
    1493                 :             :         {
    1494                 :         448 :           if (ovlsiz[0] == ovlsiz[1])
    1495                 :         710 :             warning_at (loc, OPT_Wrestrict,
    1496                 :             :                         sizrange[0] == 1
    1497                 :             :                         ? (ovlsiz[0] == 1
    1498                 :           7 :                            ? G_("%qD accessing %wu byte at offsets %s "
    1499                 :             :                                 "and %s overlaps %wu byte at offset %s")
    1500                 :             :                            :  G_("%qD accessing %wu byte at offsets %s "
    1501                 :             :                                  "and %s overlaps %wu bytes at offset "
    1502                 :             :                                  "%s"))
    1503                 :             :                         : (ovlsiz[0] == 1
    1504                 :         348 :                            ? G_("%qD accessing %wu bytes at offsets %s "
    1505                 :             :                                 "and %s overlaps %wu byte at offset %s")
    1506                 :             :                            : G_("%qD accessing %wu bytes at offsets %s "
    1507                 :             :                                 "and %s overlaps %wu bytes at offset "
    1508                 :             :                                 "%s")),
    1509                 :             :                         func, sizrange[0],
    1510                 :             :                         offstr[0], offstr[1], ovlsiz[0], offstr[2]);
    1511                 :          93 :           else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
    1512                 :          93 :             warning_n (loc, OPT_Wrestrict, sizrange[0],
    1513                 :             :                        "%qD accessing %wu byte at offsets %s "
    1514                 :             :                        "and %s overlaps between %wu and %wu bytes "
    1515                 :             :                        "at offset %s",
    1516                 :             :                        "%qD accessing %wu bytes at offsets %s "
    1517                 :             :                        "and %s overlaps between %wu and %wu bytes "
    1518                 :             :                        "at offset %s",
    1519                 :             :                        func, sizrange[0], offstr[0], offstr[1],
    1520                 :             :                        ovlsiz[0], ovlsiz[1], offstr[2]);
    1521                 :             :           else
    1522                 :           0 :             warning_n (loc, OPT_Wrestrict, sizrange[0],
    1523                 :             :                        "%qD accessing %wu byte at offsets %s and "
    1524                 :             :                        "%s overlaps %wu or more bytes at offset %s",
    1525                 :             :                        "%qD accessing %wu bytes at offsets %s and "
    1526                 :             :                        "%s overlaps %wu or more bytes at offset %s",
    1527                 :             :                        func, sizrange[0],
    1528                 :             :                        offstr[0], offstr[1], ovlsiz[0], offstr[2]);
    1529                 :         448 :           return true;
    1530                 :             :         }
    1531                 :             : 
    1532                 :         117 :       if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ())
    1533                 :             :         {
    1534                 :          66 :           if (ovlsiz[0] == ovlsiz[1])
    1535                 :           1 :             warning_n (loc, OPT_Wrestrict, ovlsiz[0],
    1536                 :             :                        "%qD accessing between %wu and %wu bytes "
    1537                 :             :                        "at offsets %s and %s overlaps %wu byte at "
    1538                 :             :                        "offset %s",
    1539                 :             :                        "%qD accessing between %wu and %wu bytes "
    1540                 :             :                        "at offsets %s and %s overlaps %wu bytes "
    1541                 :             :                        "at offset %s",
    1542                 :             :                        func, sizrange[0], sizrange[1],
    1543                 :             :                        offstr[0], offstr[1], ovlsiz[0], offstr[2]);
    1544                 :          65 :           else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
    1545                 :          65 :             warning_at (loc, OPT_Wrestrict,
    1546                 :             :                         "%qD accessing between %wu and %wu bytes at "
    1547                 :             :                         "offsets %s and %s overlaps between %wu and %wu "
    1548                 :             :                         "bytes at offset %s",
    1549                 :             :                         func, sizrange[0], sizrange[1],
    1550                 :             :                         offstr[0], offstr[1], ovlsiz[0], ovlsiz[1],
    1551                 :             :                         offstr[2]);
    1552                 :             :           else
    1553                 :           0 :             warning_at (loc, OPT_Wrestrict,
    1554                 :             :                         "%qD accessing between %wu and %wu bytes at "
    1555                 :             :                         "offsets %s and %s overlaps %wu or more bytes "
    1556                 :             :                         "at offset %s",
    1557                 :             :                         func, sizrange[0], sizrange[1],
    1558                 :             :                         offstr[0], offstr[1], ovlsiz[0], offstr[2]);
    1559                 :          66 :           return true;
    1560                 :             :         }
    1561                 :             : 
    1562                 :          51 :       if (ovlsiz[0] != ovlsiz[1])
    1563                 :          46 :         ovlsiz[1] = maxobjsize.to_shwi ();
    1564                 :             : 
    1565                 :          51 :       if (ovlsiz[0] == ovlsiz[1])
    1566                 :           5 :         warning_n (loc, OPT_Wrestrict, ovlsiz[0],
    1567                 :             :                    "%qD accessing %wu or more bytes at offsets "
    1568                 :             :                    "%s and %s overlaps %wu byte at offset %s",
    1569                 :             :                    "%qD accessing %wu or more bytes at offsets "
    1570                 :             :                    "%s and %s overlaps %wu bytes at offset %s",
    1571                 :             :                    func, sizrange[0], offstr[0], offstr[1],
    1572                 :             :                    ovlsiz[0], offstr[2]);
    1573                 :          46 :       else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
    1574                 :           0 :         warning_at (loc, OPT_Wrestrict,
    1575                 :             :                     "%qD accessing %wu or more bytes at offsets %s "
    1576                 :             :                     "and %s overlaps between %wu and %wu bytes "
    1577                 :             :                     "at offset %s",
    1578                 :             :                     func, sizrange[0], offstr[0], offstr[1],
    1579                 :             :                     ovlsiz[0], ovlsiz[1], offstr[2]);
    1580                 :             :       else
    1581                 :          46 :         warning_at (loc, OPT_Wrestrict,
    1582                 :             :                     "%qD accessing %wu or more bytes at offsets %s "
    1583                 :             :                     "and %s overlaps %wu or more bytes at offset %s",
    1584                 :             :                     func, sizrange[0], offstr[0], offstr[1],
    1585                 :             :                     ovlsiz[0], offstr[2]);
    1586                 :          51 :       return true;
    1587                 :             :     }
    1588                 :             : 
    1589                 :             :   /* Use more concise wording when one of the offsets is unbounded
    1590                 :             :      to avoid confusing the user with large and mostly meaningless
    1591                 :             :      numbers.  */
    1592                 :         188 :   bool open_range;
    1593                 :         188 :   if (DECL_P (dstref.base) && TREE_CODE (TREE_TYPE (dstref.base)) == ARRAY_TYPE)
    1594                 :         138 :     open_range = ((dstref.offrange[0] == 0
    1595                 :         109 :                    && dstref.offrange[1] == maxobjsize)
    1596                 :         312 :                   || (srcref.offrange[0] == 0
    1597                 :          65 :                       && srcref.offrange[1] == maxobjsize));
    1598                 :             :   else
    1599                 :          50 :     open_range = ((dstref.offrange[0] == -maxobjsize - 1
    1600                 :           0 :                    && dstref.offrange[1] == maxobjsize)
    1601                 :          50 :                   || (srcref.offrange[0] == -maxobjsize - 1
    1602                 :           0 :                       && srcref.offrange[1] == maxobjsize));
    1603                 :             : 
    1604                 :         188 :   if (sizrange[0] == sizrange[1] || sizrange[1] == 1)
    1605                 :             :     {
    1606                 :         107 :       if (ovlsiz[1] == 1)
    1607                 :             :         {
    1608                 :          57 :           if (open_range)
    1609                 :           0 :             warning_n (loc, OPT_Wrestrict, sizrange[1],
    1610                 :             :                        "%qD accessing %wu byte may overlap "
    1611                 :             :                        "%wu byte",
    1612                 :             :                        "%qD accessing %wu bytes may overlap "
    1613                 :             :                        "%wu byte",
    1614                 :             :                        func, sizrange[1], ovlsiz[1]);
    1615                 :             :           else
    1616                 :          57 :             warning_n (loc, OPT_Wrestrict, sizrange[1],
    1617                 :             :                        "%qD accessing %wu byte at offsets %s "
    1618                 :             :                        "and %s may overlap %wu byte at offset %s",
    1619                 :             :                        "%qD accessing %wu bytes at offsets %s "
    1620                 :             :                        "and %s may overlap %wu byte at offset %s",
    1621                 :             :                        func, sizrange[1], offstr[0], offstr[1],
    1622                 :             :                        ovlsiz[1], offstr[2]);
    1623                 :          57 :           return true;
    1624                 :             :         }
    1625                 :             : 
    1626                 :          50 :       if (open_range)
    1627                 :           0 :         warning_n (loc, OPT_Wrestrict, sizrange[1],
    1628                 :             :                    "%qD accessing %wu byte may overlap "
    1629                 :             :                    "up to %wu bytes",
    1630                 :             :                    "%qD accessing %wu bytes may overlap "
    1631                 :             :                    "up to %wu bytes",
    1632                 :             :                    func, sizrange[1], ovlsiz[1]);
    1633                 :             :       else
    1634                 :          50 :         warning_n (loc, OPT_Wrestrict, sizrange[1],
    1635                 :             :                    "%qD accessing %wu byte at offsets %s and "
    1636                 :             :                    "%s may overlap up to %wu bytes at offset %s",
    1637                 :             :                    "%qD accessing %wu bytes at offsets %s and "
    1638                 :             :                    "%s may overlap up to %wu bytes at offset %s",
    1639                 :             :                    func, sizrange[1], offstr[0], offstr[1],
    1640                 :             :                    ovlsiz[1], offstr[2]);
    1641                 :          50 :       return true;
    1642                 :             :     }
    1643                 :             : 
    1644                 :          81 :   if (sizrange[1] >= 0 && sizrange[1] < maxobjsize.to_shwi ())
    1645                 :             :     {
    1646                 :          34 :       if (open_range)
    1647                 :           0 :         warning_n (loc, OPT_Wrestrict, ovlsiz[1],
    1648                 :             :                    "%qD accessing between %wu and %wu bytes "
    1649                 :             :                    "may overlap %wu byte",
    1650                 :             :                    "%qD accessing between %wu and %wu bytes "
    1651                 :             :                    "may overlap up to %wu bytes",
    1652                 :             :                    func, sizrange[0], sizrange[1], ovlsiz[1]);
    1653                 :             :       else
    1654                 :          34 :         warning_n (loc, OPT_Wrestrict, ovlsiz[1],
    1655                 :             :                    "%qD accessing between %wu and %wu bytes "
    1656                 :             :                    "at offsets %s and %s may overlap %wu byte "
    1657                 :             :                    "at offset %s",
    1658                 :             :                    "%qD accessing between %wu and %wu bytes "
    1659                 :             :                    "at offsets %s and %s may overlap up to %wu "
    1660                 :             :                    "bytes at offset %s",
    1661                 :             :                    func, sizrange[0], sizrange[1],
    1662                 :             :                    offstr[0], offstr[1], ovlsiz[1], offstr[2]);
    1663                 :          34 :       return true;
    1664                 :             :     }
    1665                 :             : 
    1666                 :          47 :   warning_n (loc, OPT_Wrestrict, ovlsiz[1],
    1667                 :             :              "%qD accessing %wu or more bytes at offsets %s "
    1668                 :             :              "and %s may overlap %wu byte at offset %s",
    1669                 :             :              "%qD accessing %wu or more bytes at offsets %s "
    1670                 :             :              "and %s may overlap up to %wu bytes at offset %s",
    1671                 :             :              func, sizrange[0], offstr[0], offstr[1],
    1672                 :             :              ovlsiz[1], offstr[2]);
    1673                 :             : 
    1674                 :          47 :   return true;
    1675                 :             : }
    1676                 :             : 
    1677                 :             : /* Validate REF size and offsets in an expression passed as an argument
    1678                 :             :    to a CALL to a built-in function FUNC to make sure they are within
    1679                 :             :    the bounds of the referenced object if its size is known, or
    1680                 :             :    PTRDIFF_MAX otherwise.  DO_WARN is true when a diagnostic should
    1681                 :             :    be issued, false otherwise.
    1682                 :             :    Both initial values of the offsets and their final value computed
    1683                 :             :    by the function by incrementing the initial value by the size are
    1684                 :             :    validated.  Return the warning number if the offsets are not valid
    1685                 :             :    and a diagnostic has been issued, or would have been issued if
    1686                 :             :    DO_WARN had been true, otherwise an invalid warning number.  */
    1687                 :             : 
    1688                 :             : static opt_code
    1689                 :      333566 : maybe_diag_access_bounds (gimple *call, tree func, int strict,
    1690                 :             :                           const builtin_memref &ref, offset_int wroff,
    1691                 :             :                           bool do_warn)
    1692                 :             : {
    1693                 :      333566 :   location_t loc = gimple_location (call);
    1694                 :      333566 :   const offset_int maxobjsize = ref.maxobjsize;
    1695                 :             : 
    1696                 :             :   /* Check for excessive size first and regardless of warning options
    1697                 :             :      since the result is used to make codegen decisions.  */
    1698                 :      333566 :   if (ref.sizrange[0] > maxobjsize)
    1699                 :             :     {
    1700                 :         110 :       const opt_code opt = OPT_Wstringop_overflow_;
    1701                 :             :       /* Return true without issuing a warning.  */
    1702                 :         110 :       if (!do_warn)
    1703                 :             :         return opt;
    1704                 :             : 
    1705                 :         110 :       if (ref.ref && warning_suppressed_p (ref.ref, OPT_Wstringop_overflow_))
    1706                 :             :         return no_warning;
    1707                 :             : 
    1708                 :         110 :       bool warned = false;
    1709                 :         110 :       if (warn_stringop_overflow)
    1710                 :             :         {
    1711                 :         104 :           if (ref.sizrange[0] == ref.sizrange[1])
    1712                 :          86 :             warned = warning_at (loc, opt,
    1713                 :             :                                  "%qD specified bound %wu "
    1714                 :             :                                  "exceeds maximum object size %wu",
    1715                 :             :                                  func, ref.sizrange[0].to_uhwi (),
    1716                 :             :                                  maxobjsize.to_uhwi ());
    1717                 :             :           else
    1718                 :          18 :             warned = warning_at (loc, opt,
    1719                 :             :                                  "%qD specified bound between %wu and %wu "
    1720                 :             :                                  "exceeds maximum object size %wu",
    1721                 :             :                                  func, ref.sizrange[0].to_uhwi (),
    1722                 :             :                                  ref.sizrange[1].to_uhwi (),
    1723                 :             :                                  maxobjsize.to_uhwi ());
    1724                 :         170 :           return warned ? opt : no_warning;
    1725                 :             :         }
    1726                 :             :     }
    1727                 :             : 
    1728                 :             :   /* Check for out-bounds pointers regardless of warning options since
    1729                 :             :      the result is used to make codegen decisions.  An excessive WROFF
    1730                 :             :      can only come up as a result of an invalid strncat bound and is
    1731                 :             :      diagnosed separately using a more meaningful warning.  */
    1732                 :      333462 :   if (maxobjsize < wroff)
    1733                 :           0 :     wroff = 0;
    1734                 :      333462 :   offset_int ooboff[] = { ref.offrange[0], ref.offrange[1], wroff };
    1735                 :      333462 :   tree oobref = ref.offset_out_of_bounds (strict, ooboff);
    1736                 :      333462 :   if (!oobref)
    1737                 :             :     return no_warning;
    1738                 :             : 
    1739                 :        2731 :   const opt_code opt = OPT_Warray_bounds_;
    1740                 :             :   /* Return true without issuing a warning.  */
    1741                 :        2731 :   if (!do_warn)
    1742                 :             :     return opt;
    1743                 :             : 
    1744                 :        1545 :   if (!warn_array_bounds)
    1745                 :             :     return no_warning;
    1746                 :             : 
    1747                 :         591 :   if (warning_suppressed_p (ref.ptr, opt)
    1748                 :         591 :       || (ref.ref && warning_suppressed_p (ref.ref, opt)))
    1749                 :          18 :     return no_warning;
    1750                 :             : 
    1751                 :         573 :   char rangestr[2][64];
    1752                 :         573 :   if (ooboff[0] == ooboff[1]
    1753                 :         573 :       || (ooboff[0] != ref.offrange[0]
    1754                 :         178 :           && ooboff[0].to_shwi () >= ooboff[1].to_shwi ()))
    1755                 :         246 :     sprintf (rangestr[0], "%lli", (long long) ooboff[0].to_shwi ());
    1756                 :             :   else
    1757                 :         327 :     sprintf (rangestr[0], "[%lli, %lli]",
    1758                 :         327 :              (long long) ooboff[0].to_shwi (),
    1759                 :         327 :              (long long) ooboff[1].to_shwi ());
    1760                 :             : 
    1761                 :         573 :   bool warned = false;
    1762                 :             : 
    1763                 :         573 :   if (oobref == error_mark_node)
    1764                 :             :     {
    1765                 :          26 :       if (ref.sizrange[0] == ref.sizrange[1])
    1766                 :          21 :         sprintf (rangestr[1], "%llu",
    1767                 :          21 :                  (unsigned long long) ref.sizrange[0].to_shwi ());
    1768                 :             :       else
    1769                 :           5 :         sprintf (rangestr[1], "[%lli, %lli]",
    1770                 :           5 :                  (unsigned long long) ref.sizrange[0].to_uhwi (),
    1771                 :           5 :                  (unsigned long long) ref.sizrange[1].to_uhwi ());
    1772                 :             : 
    1773                 :          26 :       tree type;
    1774                 :             : 
    1775                 :          26 :       if (DECL_P (ref.base)
    1776                 :          26 :           && TREE_CODE (type = TREE_TYPE (ref.base)) == ARRAY_TYPE)
    1777                 :             :         {
    1778                 :          10 :           auto_diagnostic_group d;
    1779                 :          10 :           if (warning_at (loc, opt,
    1780                 :             :                           "%qD pointer overflow between offset %s "
    1781                 :             :                           "and size %s accessing array %qD with type %qT",
    1782                 :          10 :                           func, rangestr[0], rangestr[1], ref.base, type))
    1783                 :             :             {
    1784                 :          20 :               inform (DECL_SOURCE_LOCATION (ref.base),
    1785                 :          10 :                       "array %qD declared here", ref.base);
    1786                 :          10 :               warned = true;
    1787                 :             :             }
    1788                 :             :           else
    1789                 :           0 :             warned = warning_at (loc, opt,
    1790                 :             :                                  "%qD pointer overflow between offset %s "
    1791                 :             :                                  "and size %s",
    1792                 :             :                                  func, rangestr[0], rangestr[1]);
    1793                 :          10 :         }
    1794                 :             :       else
    1795                 :          16 :         warned = warning_at (loc, opt,
    1796                 :             :                              "%qD pointer overflow between offset %s "
    1797                 :             :                              "and size %s",
    1798                 :             :                              func, rangestr[0], rangestr[1]);
    1799                 :             :     }
    1800                 :         547 :   else if (oobref == ref.base)
    1801                 :             :     {
    1802                 :             :       /* True when the offset formed by an access to the reference
    1803                 :             :          is out of bounds, rather than the initial offset wich is
    1804                 :             :          in bounds.  This implies access past the end.  */
    1805                 :         348 :       bool form = ooboff[0] != ref.offrange[0];
    1806                 :             : 
    1807                 :         348 :       if (DECL_P (ref.base))
    1808                 :             :         {
    1809                 :         324 :           auto_diagnostic_group d;
    1810                 :         324 :           if ((ref.basesize < maxobjsize
    1811                 :         500 :                && warning_at (loc, opt,
    1812                 :             :                               form
    1813                 :             :                               ? G_("%qD forming offset %s is out of "
    1814                 :             :                                    "the bounds [0, %wu] of object %qD with "
    1815                 :             :                                    "type %qT")
    1816                 :             :                               : G_("%qD offset %s is out of the bounds "
    1817                 :             :                                    "[0, %wu] of object %qD with type %qT"),
    1818                 :             :                               func, rangestr[0], ref.basesize.to_uhwi (),
    1819                 :         304 :                               ref.base, TREE_TYPE (ref.base)))
    1820                 :         366 :               || warning_at (loc, opt,
    1821                 :             :                              form
    1822                 :             :                              ? G_("%qD forming offset %s is out of "
    1823                 :             :                                   "the bounds of object %qD with type %qT")
    1824                 :             :                              : G_("%qD offset %s is out of the bounds "
    1825                 :             :                                   "of object %qD with type %qT"),
    1826                 :             :                              func, rangestr[0],
    1827                 :          22 :                              ref.base, TREE_TYPE (ref.base)))
    1828                 :             :             {
    1829                 :         644 :               inform (DECL_SOURCE_LOCATION (ref.base),
    1830                 :         322 :                       "%qD declared here", ref.base);
    1831                 :         322 :               warned = true;
    1832                 :             :             }
    1833                 :         324 :         }
    1834                 :          24 :       else if (ref.basesize < maxobjsize)
    1835                 :          31 :         warned = warning_at (loc, opt,
    1836                 :             :                              form
    1837                 :             :                              ? G_("%qD forming offset %s is out "
    1838                 :             :                                   "of the bounds [0, %wu]")
    1839                 :             :                              : G_("%qD offset %s is out "
    1840                 :             :                                   "of the bounds [0, %wu]"),
    1841                 :             :                              func, rangestr[0], ref.basesize.to_uhwi ());
    1842                 :             :       else
    1843                 :           0 :         warned = warning_at (loc, opt,
    1844                 :             :                              form
    1845                 :             :                              ? G_("%qD forming offset %s is out of bounds")
    1846                 :             :                              : G_("%qD offset %s is out of bounds"),
    1847                 :             :                              func, rangestr[0]);
    1848                 :             :     }
    1849                 :         199 :   else if (TREE_CODE (ref.ref) == MEM_REF)
    1850                 :             :     {
    1851                 :           0 :       tree refop = TREE_OPERAND (ref.ref, 0);
    1852                 :           0 :       tree type = TREE_TYPE (refop);
    1853                 :           0 :       if (POINTER_TYPE_P (type))
    1854                 :           0 :         type = TREE_TYPE (type);
    1855                 :           0 :       type = TYPE_MAIN_VARIANT (type);
    1856                 :             : 
    1857                 :           0 :       if (warning_at (loc, opt,
    1858                 :             :                       "%qD offset %s from the object at %qE is out "
    1859                 :             :                       "of the bounds of %qT",
    1860                 :             :                       func, rangestr[0], ref.base, type))
    1861                 :             :         {
    1862                 :           0 :           if (TREE_CODE (ref.ref) == COMPONENT_REF)
    1863                 :           0 :             refop = TREE_OPERAND (ref.ref, 1);
    1864                 :           0 :           if (DECL_P (refop))
    1865                 :           0 :             inform (DECL_SOURCE_LOCATION (refop),
    1866                 :             :                     "subobject %qD declared here", refop);
    1867                 :             :           warned = true;
    1868                 :             :         }
    1869                 :             :     }
    1870                 :             :   else
    1871                 :             :     {
    1872                 :         199 :       tree refop = TREE_OPERAND (ref.ref, 0);
    1873                 :         199 :       tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ref.ref));
    1874                 :             : 
    1875                 :         199 :       if (warning_at (loc, opt,
    1876                 :             :                       "%qD offset %s from the object at %qE is out "
    1877                 :             :                       "of the bounds of referenced subobject %qD with "
    1878                 :             :                       "type %qT at offset %wi",
    1879                 :             :                       func, rangestr[0], ref.base,
    1880                 :         199 :                       TREE_OPERAND (ref.ref, 1), type,
    1881                 :             :                       ref.refoff.to_shwi ()))
    1882                 :             :         {
    1883                 :         199 :           if (TREE_CODE (ref.ref) == COMPONENT_REF)
    1884                 :         199 :             refop = TREE_OPERAND (ref.ref, 1);
    1885                 :         199 :           if (DECL_P (refop))
    1886                 :         199 :             inform (DECL_SOURCE_LOCATION (refop),
    1887                 :             :                     "subobject %qD declared here", refop);
    1888                 :             :           warned = true;
    1889                 :             :         }
    1890                 :             :     }
    1891                 :             : 
    1892                 :         374 :   return warned ? opt : no_warning;
    1893                 :             : }
    1894                 :             : 
    1895                 :             : /* Check a CALL statement for restrict-violations and issue warnings
    1896                 :             :    if/when appropriate.  */
    1897                 :             : 
    1898                 :             : void
    1899                 :     4805432 : pass_wrestrict::check_call (gimple *call)
    1900                 :             : {
    1901                 :             :   /* Avoid checking the call if it has already been diagnosed for
    1902                 :             :      some reason.  */
    1903                 :     4805432 :   if (warning_suppressed_p (call, OPT_Wrestrict))
    1904                 :             :     return;
    1905                 :             : 
    1906                 :     4796713 :   tree func = gimple_call_fndecl (call);
    1907                 :     4796713 :   if (!func || !fndecl_built_in_p (func, BUILT_IN_NORMAL))
    1908                 :             :     return;
    1909                 :             : 
    1910                 :             :   /* Argument number to extract from the call (depends on the built-in
    1911                 :             :      and its kind).  */
    1912                 :     1074256 :   unsigned dst_idx = -1;
    1913                 :     1074256 :   unsigned src_idx = -1;
    1914                 :     1074256 :   unsigned bnd_idx = -1;
    1915                 :             : 
    1916                 :             :   /* Is this CALL to a string function (as opposed to one to a raw
    1917                 :             :      memory function).  */
    1918                 :     1074256 :   bool strfun = true;
    1919                 :             : 
    1920                 :     1074256 :   switch (DECL_FUNCTION_CODE (func))
    1921                 :             :     {
    1922                 :       87216 :     case BUILT_IN_MEMCPY:
    1923                 :       87216 :     case BUILT_IN_MEMCPY_CHK:
    1924                 :       87216 :     case BUILT_IN_MEMPCPY:
    1925                 :       87216 :     case BUILT_IN_MEMPCPY_CHK:
    1926                 :       87216 :     case BUILT_IN_MEMMOVE:
    1927                 :       87216 :     case BUILT_IN_MEMMOVE_CHK:
    1928                 :       87216 :       strfun = false;
    1929                 :             :       /* Fall through.  */
    1930                 :             : 
    1931                 :             :     case BUILT_IN_STPNCPY:
    1932                 :             :     case BUILT_IN_STPNCPY_CHK:
    1933                 :             :     case BUILT_IN_STRNCAT:
    1934                 :             :     case BUILT_IN_STRNCAT_CHK:
    1935                 :             :     case BUILT_IN_STRNCPY:
    1936                 :             :     case BUILT_IN_STRNCPY_CHK:
    1937                 :             :       dst_idx = 0;
    1938                 :             :       src_idx = 1;
    1939                 :             :       bnd_idx = 2;
    1940                 :             :       break;
    1941                 :             : 
    1942                 :             :     case BUILT_IN_MEMSET:
    1943                 :             :     case BUILT_IN_MEMSET_CHK:
    1944                 :             :       dst_idx = 0;
    1945                 :             :       bnd_idx = 2;
    1946                 :             :       break;
    1947                 :             : 
    1948                 :        3057 :     case BUILT_IN_STPCPY:
    1949                 :        3057 :     case BUILT_IN_STPCPY_CHK:
    1950                 :        3057 :     case BUILT_IN_STRCPY:
    1951                 :        3057 :     case BUILT_IN_STRCPY_CHK:
    1952                 :        3057 :     case BUILT_IN_STRCAT:
    1953                 :        3057 :     case BUILT_IN_STRCAT_CHK:
    1954                 :        3057 :       dst_idx = 0;
    1955                 :        3057 :       src_idx = 1;
    1956                 :        3057 :       break;
    1957                 :             : 
    1958                 :             :     default:
    1959                 :             :       /* Handle other string functions here whose access may need
    1960                 :             :          to be validated for in-bounds offsets and non-overlapping
    1961                 :             :          copies.  */
    1962                 :             :       return;
    1963                 :             :     }
    1964                 :             : 
    1965                 :      122448 :   unsigned nargs = gimple_call_num_args (call);
    1966                 :             : 
    1967                 :      122448 :   tree dst = dst_idx < nargs ? gimple_call_arg (call, dst_idx) : NULL_TREE;
    1968                 :      122426 :   tree src = src_idx < nargs ? gimple_call_arg (call, src_idx) : NULL_TREE;
    1969                 :      122448 :   tree dstwr = bnd_idx < nargs ? gimple_call_arg (call, bnd_idx) : NULL_TREE;
    1970                 :             : 
    1971                 :             :   /* For string functions with an unspecified or unknown bound,
    1972                 :             :      assume the size of the access is one.  */
    1973                 :      122448 :   if (!dstwr && strfun)
    1974                 :        3063 :     dstwr = size_one_node;
    1975                 :             : 
    1976                 :             :   /* DST and SRC can be null for a call with an insufficient number
    1977                 :             :      of arguments to a built-in function declared without a protype.  */
    1978                 :      122448 :   if (!dst || (src_idx < nargs && !src))
    1979                 :             :     return;
    1980                 :             : 
    1981                 :             :   /* DST, SRC, or DSTWR can also have the wrong type in a call to
    1982                 :             :      a function declared without a prototype.  Avoid checking such
    1983                 :             :      invalid calls.  */
    1984                 :      122426 :   if (TREE_CODE (TREE_TYPE (dst)) != POINTER_TYPE
    1985                 :      120421 :       || (src && TREE_CODE (TREE_TYPE (src)) != POINTER_TYPE)
    1986                 :      242460 :       || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr))))
    1987                 :             :     return;
    1988                 :             : 
    1989                 :      120032 :   opt_code opt = check_bounds_or_overlap (m_ptr_qry, call, dst, src, dstwr,
    1990                 :             :                                           NULL_TREE);
    1991                 :             :   /* Avoid diagnosing the call again.  */
    1992                 :      120032 :   suppress_warning (call, opt);
    1993                 :             : }
    1994                 :             : 
    1995                 :             : } /* anonymous namespace */
    1996                 :             : 
    1997                 :             : /* Attempt to detect and diagnose invalid offset bounds and (except for
    1998                 :             :    memmove) overlapping copy in a call expression EXPR from SRC to DST
    1999                 :             :    and DSTSIZE and SRCSIZE bytes, respectively.  Both DSTSIZE and
    2000                 :             :    SRCSIZE may be NULL.  DO_WARN is false to detect either problem
    2001                 :             :    without issue a warning.  Return the OPT_Wxxx constant corresponding
    2002                 :             :    to the warning if one has been detected and zero otherwise.  */
    2003                 :             : 
    2004                 :             : opt_code
    2005                 :       47247 : check_bounds_or_overlap (gimple *call, tree dst, tree src, tree dstsize,
    2006                 :             :                          tree srcsize, bool bounds_only /* = false */,
    2007                 :             :                          bool do_warn /* = true */)
    2008                 :             : {
    2009                 :       94494 :   pointer_query ptrqry (get_range_query (cfun));
    2010                 :       47247 :   return check_bounds_or_overlap (ptrqry,
    2011                 :             :                                   call, dst, src, dstsize, srcsize,
    2012                 :       47247 :                                   bounds_only, do_warn);
    2013                 :       47247 : }
    2014                 :             : 
    2015                 :             : opt_code
    2016                 :      167279 : check_bounds_or_overlap (pointer_query &ptrqry,
    2017                 :             :                          gimple *call, tree dst, tree src, tree dstsize,
    2018                 :             :                          tree srcsize, bool bounds_only /* = false */,
    2019                 :             :                          bool do_warn /* = true */)
    2020                 :             : {
    2021                 :      167279 :   tree func = gimple_call_fndecl (call);
    2022                 :             : 
    2023                 :      167279 :   builtin_memref dstref (ptrqry, call, dst, dstsize);
    2024                 :      167279 :   builtin_memref srcref (ptrqry, call, src, srcsize);
    2025                 :             : 
    2026                 :             :   /* Create a descriptor of the access.  This may adjust both DSTREF
    2027                 :             :      and SRCREF based on one another and the kind of the access.  */
    2028                 :      167279 :   builtin_access acs (ptrqry, call, dstref, srcref);
    2029                 :             : 
    2030                 :             :   /* Set STRICT to the value of the -Warray-bounds=N argument for
    2031                 :             :      string functions or when N > 1.  */
    2032                 :      167279 :   int strict = (acs.strict () || warn_array_bounds > 1 ? warn_array_bounds : 0);
    2033                 :             : 
    2034                 :             :   /* The starting offset of the destination write access.  Nonzero only
    2035                 :             :      for the strcat family of functions.  */
    2036                 :      167279 :   offset_int wroff = acs.write_off (dstsize);
    2037                 :             : 
    2038                 :             :   /* Validate offsets to each reference before the access first to make
    2039                 :             :      sure they are within the bounds of the destination object if its
    2040                 :             :      size is known, or PTRDIFF_MAX otherwise.  */
    2041                 :      167279 :   opt_code opt
    2042                 :      167279 :     = maybe_diag_access_bounds (call, func, strict, dstref, wroff, do_warn);
    2043                 :      167279 :   if (opt == no_warning)
    2044                 :      166287 :     opt = maybe_diag_access_bounds (call, func, strict, srcref, 0, do_warn);
    2045                 :             : 
    2046                 :      166287 :   if (opt != no_warning)
    2047                 :             :     {
    2048                 :        1795 :       if (do_warn)
    2049                 :         609 :         suppress_warning (call, opt);
    2050                 :        1795 :       return opt;
    2051                 :             :     }
    2052                 :             : 
    2053                 :      165484 :   if (!warn_restrict || bounds_only || !src)
    2054                 :             :     return no_warning;
    2055                 :             : 
    2056                 :       13401 :   if (!bounds_only)
    2057                 :             :     {
    2058                 :       13401 :       switch (DECL_FUNCTION_CODE (func))
    2059                 :             :         {
    2060                 :             :         case BUILT_IN_MEMMOVE:
    2061                 :             :         case BUILT_IN_MEMMOVE_CHK:
    2062                 :             :         case BUILT_IN_MEMSET:
    2063                 :             :         case BUILT_IN_MEMSET_CHK:
    2064                 :             :           return no_warning;
    2065                 :             :         default:
    2066                 :             :           break;
    2067                 :             :         }
    2068                 :             :     }
    2069                 :             : 
    2070                 :       12370 :   location_t loc = gimple_location (call);
    2071                 :       12370 :   if (operand_equal_p (dst, src, 0))
    2072                 :             :     {
    2073                 :             :       /* Issue -Wrestrict unless the pointers are null (those do
    2074                 :             :          not point to objects and so do not indicate an overlap;
    2075                 :             :          such calls could be the result of sanitization and jump
    2076                 :             :          threading).  */
    2077                 :          80 :       if (!integer_zerop (dst) && !warning_suppressed_p (call, OPT_Wrestrict))
    2078                 :             :         {
    2079                 :          61 :           warning_at (loc, OPT_Wrestrict,
    2080                 :             :                       "%qD source argument is the same as destination",
    2081                 :             :                       func);
    2082                 :          61 :           suppress_warning (call, OPT_Wrestrict);
    2083                 :          61 :           return OPT_Wrestrict;
    2084                 :             :         }
    2085                 :             : 
    2086                 :          19 :       return no_warning;
    2087                 :             :     }
    2088                 :             : 
    2089                 :             :   /* Return false when overlap has been detected.  */
    2090                 :       12290 :   if (maybe_diag_overlap (loc, call, acs))
    2091                 :             :     {
    2092                 :         808 :       suppress_warning (call, OPT_Wrestrict);
    2093                 :         808 :       return OPT_Wrestrict;
    2094                 :             :     }
    2095                 :             : 
    2096                 :             :   return no_warning;
    2097                 :             : }
    2098                 :             : 
    2099                 :             : gimple_opt_pass *
    2100                 :      281914 : make_pass_warn_restrict (gcc::context *ctxt)
    2101                 :             : {
    2102                 :      281914 :   return new pass_wrestrict (ctxt);
    2103                 :             : }
    2104                 :             : 
    2105                 :             : DEBUG_FUNCTION void
    2106                 :           0 : dump_builtin_memref (FILE *fp, const builtin_memref &ref)
    2107                 :             : {
    2108                 :           0 :   fprintf (fp, "\n    ptr = ");
    2109                 :           0 :   print_generic_expr (fp, ref.ptr, TDF_LINENO);
    2110                 :           0 :   fprintf (fp, "\n    ref = ");
    2111                 :           0 :   if (ref.ref)
    2112                 :           0 :     print_generic_expr (fp, ref.ref, TDF_LINENO);
    2113                 :             :   else
    2114                 :           0 :     fputs ("null", fp);
    2115                 :           0 :   fprintf (fp, "\n    base = ");
    2116                 :           0 :   print_generic_expr (fp, ref.base, TDF_LINENO);
    2117                 :           0 :   fprintf (fp,
    2118                 :             :            "\n    basesize = %lli"
    2119                 :             :            "\n    refsize = %lli"
    2120                 :             :            "\n    refoff = %lli"
    2121                 :             :            "\n    offrange = [%lli, %lli]"
    2122                 :             :            "\n    sizrange = [%lli, %lli]"
    2123                 :             :            "\n    strbounded_p = %s\n",
    2124                 :           0 :            (long long)ref.basesize.to_shwi (),
    2125                 :           0 :            (long long)ref.refsize.to_shwi (),
    2126                 :           0 :            (long long)ref.refoff.to_shwi (),
    2127                 :           0 :            (long long)ref.offrange[0].to_shwi (),
    2128                 :           0 :            (long long)ref.offrange[1].to_shwi (),
    2129                 :           0 :            (long long)ref.sizrange[0].to_shwi (),
    2130                 :           0 :            (long long)ref.sizrange[1].to_shwi (),
    2131                 :           0 :            ref.strbounded_p ? "true" : "false");
    2132                 :           0 : }
    2133                 :             : 
    2134                 :             : void
    2135                 :           0 : builtin_access::dump (FILE *fp) const
    2136                 :             : {
    2137                 :           0 :   fprintf (fp, "  dstref:");
    2138                 :           0 :   dump_builtin_memref (fp, *dstref);
    2139                 :           0 :   fprintf (fp, "\n  srcref:");
    2140                 :           0 :   dump_builtin_memref (fp, *srcref);
    2141                 :             : 
    2142                 :           0 :   fprintf (fp,
    2143                 :             :            "  sizrange = [%lli, %lli]\n"
    2144                 :             :            "  ovloff = [%lli, %lli]\n"
    2145                 :             :            "  ovlsiz = [%lli, %lli]\n"
    2146                 :             :            "  dstoff = [%lli, %lli]\n"
    2147                 :             :            "  dstsiz = [%lli, %lli]\n"
    2148                 :             :            "  srcoff = [%lli, %lli]\n"
    2149                 :             :            "  srcsiz = [%lli, %lli]\n",
    2150                 :           0 :            (long long)sizrange[0], (long long)sizrange[1],
    2151                 :           0 :            (long long)ovloff[0], (long long)ovloff[1],
    2152                 :           0 :            (long long)ovlsiz[0], (long long)ovlsiz[1],
    2153                 :           0 :            (long long)dstoff[0].to_shwi (), (long long)dstoff[1].to_shwi (),
    2154                 :           0 :            (long long)dstsiz[0].to_shwi (), (long long)dstsiz[1].to_shwi (),
    2155                 :           0 :            (long long)srcoff[0].to_shwi (), (long long)srcoff[1].to_shwi (),
    2156                 :           0 :            (long long)srcsiz[0].to_shwi (), (long long)srcsiz[1].to_shwi ());
    2157                 :           0 : }
    2158                 :             : 
    2159                 :             : DEBUG_FUNCTION void
    2160                 :           0 : dump_builtin_access (FILE *fp, gimple *stmt, const builtin_access &acs)
    2161                 :             : {
    2162                 :           0 :   if (stmt)
    2163                 :             :     {
    2164                 :           0 :       fprintf (fp, "\nDumping builtin_access for ");
    2165                 :           0 :       print_gimple_expr (fp, stmt, TDF_LINENO);
    2166                 :           0 :       fputs (":\n", fp);
    2167                 :             :     }
    2168                 :             : 
    2169                 :           0 :   acs.dump (fp);
    2170                 :           0 : }
    2171                 :             : 
    2172                 :             : DEBUG_FUNCTION void
    2173                 :           0 : debug (gimple *stmt, const builtin_access &acs)
    2174                 :             : {
    2175                 :           0 :   dump_builtin_access (stdout, stmt, acs);
    2176                 :           0 : }
        

Generated by: LCOV version 2.1-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.