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

Generated by: LCOV version 1.0

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 --enable-host-shared. GCC test suite is run with the built compiler.