LCOV - code coverage report
Current view: top level - gcc - gimple-ssa-warn-restrict.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 90.6 % 875 793
Test Date: 2026-02-28 14:20:25 Functions: 82.1 % 28 23
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-beta

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