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: 2025-09-20 13:40:47 Functions: 82.1 % 28 23
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Pass to detect and issue warnings for violations of the restrict
       2                 :             :    qualifier.
       3                 :             :    Copyright (C) 2017-2025 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                 :      285689 : pass_wrestrict::pass_wrestrict (gcc::context *ctxt)
      81                 :             :   : gimple_opt_pass (pass_data_wrestrict, ctxt),
      82                 :      285689 :     m_ptr_qry ()
      83                 :      285689 : { }
      84                 :             : 
      85                 :             : bool
      86                 :     1042778 : pass_wrestrict::gate (function *fun ATTRIBUTE_UNUSED)
      87                 :             : {
      88                 :     1042778 :   return warn_array_bounds || warn_restrict || warn_stringop_overflow;
      89                 :             : }
      90                 :             : 
      91                 :             : void
      92                 :    10309668 : pass_wrestrict::check_block (basic_block bb)
      93                 :             : {
      94                 :             :   /* Iterate over statements, looking for function calls.  */
      95                 :   110196292 :   for (auto si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
      96                 :             :     {
      97                 :    89576956 :       gimple *stmt = gsi_stmt (si);
      98                 :    89576956 :       if (!is_gimple_call (stmt))
      99                 :    84441257 :         continue;
     100                 :             : 
     101                 :     5135699 :       check_call (stmt);
     102                 :             :     }
     103                 :    10309668 : }
     104                 :             : 
     105                 :             : unsigned
     106                 :     1042597 : pass_wrestrict::execute (function *fun)
     107                 :             : {
     108                 :             :   /* Create a new ranger instance and associate it with FUN.  */
     109                 :     1042597 :   m_ptr_qry.rvals = enable_ranger (fun);
     110                 :     1042597 :   bool new_dominance_for_diagnostics = false;
     111                 :             : 
     112                 :     1042597 :   if (flag_diagnostics_show_context
     113                 :     1042597 :       && !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                 :     1042597 :   basic_block bb;
     120                 :    11352265 :   FOR_EACH_BB_FN (bb, fun)
     121                 :    10309668 :     check_block (bb);
     122                 :             : 
     123                 :     1042597 :   if (new_dominance_for_diagnostics
     124                 :     1042597 :       && dom_info_available_p (fun, CDI_DOMINATORS))
     125                 :          23 :     free_dominance_info (fun, CDI_DOMINATORS);
     126                 :             : 
     127                 :     1042597 :   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                 :     1042597 :   disable_ranger (fun);
     132                 :     1042597 :   m_ptr_qry.rvals = NULL;
     133                 :             : 
     134                 :     1042597 :   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                 :      185301 :   bool strict () const
     213                 :             :   {
     214                 :      185301 :     return (detect_overlap != &builtin_access::generic_overlap
     215                 :       62003 :             && 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                 :      370602 : builtin_memref::builtin_memref (pointer_query &ptrqry, gimple *stmt, tree expr,
     258                 :      370602 :                                 tree size)
     259                 :      370602 : : ptr (expr),
     260                 :      370602 :   ref (),
     261                 :      370602 :   base (),
     262                 :      370602 :   basesize (-1),
     263                 :      370602 :   refsize (-1),
     264                 :      370602 :   refoff (HOST_WIDE_INT_MIN),
     265                 :      370602 :   offrange (),
     266                 :      370602 :   sizrange (),
     267                 :      370602 :   maxobjsize (tree_to_shwi (max_object_size ())),
     268                 :      370602 :   strbounded_p (),
     269                 :      370602 :   stmt (stmt),
     270                 :      370602 :   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                 :      370602 :   offrange[0] = offrange[1] = 0;
     275                 :      370602 :   sizrange[0] = sizrange[1] = 0;
     276                 :             : 
     277                 :      370602 :   if (!expr)
     278                 :      245235 :     return;
     279                 :             : 
     280                 :             :   /* Find the BASE object or pointer referenced by EXPR and set
     281                 :             :      the offset range OFFRANGE in the process.  */
     282                 :      338712 :   set_base_and_offset (expr);
     283                 :             : 
     284                 :      338712 :   if (size)
     285                 :             :     {
     286                 :      224918 :       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                 :      224918 :       get_size_range (m_ptr_qry.rvals, size, stmt, range, SR_ALLOW_ZERO);
     290                 :      224918 :       sizrange[0] = wi::to_offset (range[0]);
     291                 :      224918 :       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                 :      224918 :       if (sizrange[0] <= maxobjsize && sizrange[1] > maxobjsize)
     295                 :       26919 :         sizrange[1] = maxobjsize;
     296                 :             :     }
     297                 :             :   else
     298                 :      113794 :     sizrange[1] = maxobjsize;
     299                 :             : 
     300                 :      338712 :   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                 :      125367 :   if (offrange[0] < 0 && offrange[1] > 0)
     306                 :        1448 :     offrange[0] = 0;
     307                 :             : 
     308                 :      125367 :   offset_int maxoff = maxobjsize;
     309                 :      125367 :   tree basetype = TREE_TYPE (base);
     310                 :      125367 :   if (TREE_CODE (basetype) == ARRAY_TYPE)
     311                 :             :     {
     312                 :       71930 :       if (ref && array_ref_flexible_size_p (ref))
     313                 :             :         ;   /* Use the maximum possible offset for an array that might
     314                 :             :                have flexible size.  */
     315                 :       69349 :       else if (tree basesize = TYPE_SIZE_UNIT (basetype))
     316                 :       67697 :         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                 :       67697 :           maxoff = wi::to_offset (basesize);
     320                 :             :     }
     321                 :             : 
     322                 :      125367 :   if (offrange[0] >= 0)
     323                 :             :     {
     324                 :      125232 :       if (offrange[1] < 0)
     325                 :         519 :         offrange[1] = offrange[0] <= maxoff ? maxoff : maxobjsize;
     326                 :      124713 :       else if (offrange[0] <= maxoff && offrange[1] > maxoff)
     327                 :        1427 :         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                 :      185301 : offset_int builtin_access::write_off (tree startlen) const
     336                 :             : {
     337                 :      185301 :   if (detect_overlap != &builtin_access::strcat_overlap
     338                 :        2856 :       || !startlen || TREE_CODE (startlen) != INTEGER_CST)
     339                 :      184170 :     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                 :       43203 : builtin_memref::extend_offset_range (tree offset)
     350                 :             : {
     351                 :       43203 :   if (TREE_CODE (offset) == INTEGER_CST)
     352                 :             :     {
     353                 :       15728 :       offset_int off = int_cst_value (offset);
     354                 :       15728 :       if (off != 0)
     355                 :             :         {
     356                 :        7993 :           offrange[0] += off;
     357                 :        7993 :           offrange[1] += off;
     358                 :             :         }
     359                 :       15728 :       return;
     360                 :             :     }
     361                 :             : 
     362                 :       27475 :   if (TREE_CODE (offset) == SSA_NAME)
     363                 :             :     {
     364                 :             :       /* A pointer offset is represented as sizetype but treated
     365                 :             :          as signed.  */
     366                 :       27401 :       wide_int min, max;
     367                 :       27401 :       value_range_kind rng = VR_VARYING;
     368                 :       27401 :       int_range_max vr;
     369                 :       27401 :       if (m_ptr_qry.rvals->range_of_expr (vr, offset, stmt))
     370                 :             :         {
     371                 :       27401 :           tree vr_min, vr_max;
     372                 :       27401 :           rng = get_legacy_range (vr, vr_min, vr_max);
     373                 :       27401 :           if (!vr.undefined_p ())
     374                 :             :             {
     375                 :       27401 :               min = wi::to_wide (vr_min);
     376                 :       27401 :               max = wi::to_wide (vr_max);
     377                 :             :             }
     378                 :             :         }
     379                 :             : 
     380                 :       27401 :       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                 :         915 :           offrange[0] += offset_int::from (max + 1, SIGNED);
     385                 :         915 :           offrange[1] += offset_int::from (min - 1, SIGNED);
     386                 :         915 :           return;
     387                 :             :         }
     388                 :             : 
     389                 :       26486 :       if (rng == VR_RANGE
     390                 :       26486 :           && (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                 :       10208 :           offrange[0] += offset_int::from (min, SIGNED);
     398                 :       10208 :           offrange[1] += offset_int::from (max, SIGNED);
     399                 :       10208 :           return;
     400                 :             :         }
     401                 :             : 
     402                 :             :       /* Handle an anti-range the same as no range at all.  */
     403                 :       16278 :       gimple *stmt = SSA_NAME_DEF_STMT (offset);
     404                 :       16278 :       tree type;
     405                 :       16278 :       if (is_gimple_assign (stmt)
     406                 :       10840 :           && (type = TREE_TYPE (gimple_assign_rhs1 (stmt)))
     407                 :       10840 :           && INTEGRAL_TYPE_P (type)
     408                 :       27118 :           && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (offset)))
     409                 :             :         {
     410                 :       10839 :           tree_code code = gimple_assign_rhs_code (stmt);
     411                 :       10839 :           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                 :        4392 :               offrange[0] += wi::to_offset (TYPE_MIN_VALUE (type));
     417                 :        4392 :               offrange[1] += wi::to_offset (TYPE_MAX_VALUE (type));
     418                 :        4392 :               return;
     419                 :             :             }
     420                 :             :         }
     421                 :       27401 :     }
     422                 :             : 
     423                 :       11960 :   const offset_int maxoff = tree_to_shwi (max_object_size ()) >> 1;
     424                 :       11960 :   const offset_int minoff = -maxoff - 1;
     425                 :             : 
     426                 :       11960 :   offrange[0] += minoff;
     427                 :       11960 :   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                 :      375636 : builtin_memref::set_base_and_offset (tree expr)
     435                 :             : {
     436                 :      375636 :   tree offset = NULL_TREE;
     437                 :             : 
     438                 :      375636 :   if (TREE_CODE (expr) == SSA_NAME)
     439                 :             :     {
     440                 :             :       /* Try to tease the offset out of the pointer.  */
     441                 :      220022 :       gimple *stmt = SSA_NAME_DEF_STMT (expr);
     442                 :      220022 :       if (!base
     443                 :      183098 :           && gimple_assign_single_p (stmt)
     444                 :      271591 :           && gimple_assign_rhs_code (stmt) == ADDR_EXPR)
     445                 :        9863 :         expr = gimple_assign_rhs1 (stmt);
     446                 :      210159 :       else if (is_gimple_assign (stmt))
     447                 :             :         {
     448                 :      104460 :           tree_code code = gimple_assign_rhs_code (stmt);
     449                 :      104460 :           if (CONVERT_EXPR_CODE_P (code))
     450                 :             :             {
     451                 :       16418 :               tree rhs = gimple_assign_rhs1 (stmt);
     452                 :       16418 :               if (POINTER_TYPE_P (TREE_TYPE (rhs)))
     453                 :             :                 expr = gimple_assign_rhs1 (stmt);
     454                 :             :               else
     455                 :             :                 {
     456                 :       16418 :                   base = expr;
     457                 :      176176 :                   return;
     458                 :             :                 }
     459                 :             :             }
     460                 :       88042 :           else if (code == POINTER_PLUS_EXPR)
     461                 :             :             {
     462                 :       33983 :               expr = gimple_assign_rhs1 (stmt);
     463                 :       33983 :               offset = gimple_assign_rhs2 (stmt);
     464                 :             :             }
     465                 :             :           else
     466                 :             :             {
     467                 :       54059 :               base = expr;
     468                 :       54059 :               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                 :      105699 :           base = expr;
     480                 :      105699 :           return;
     481                 :             :         }
     482                 :             :     }
     483                 :             : 
     484                 :      199460 :   if (TREE_CODE (expr) == ADDR_EXPR)
     485                 :      158863 :     expr = TREE_OPERAND (expr, 0);
     486                 :             : 
     487                 :             :   /* Stash the reference for offset validation.  */
     488                 :      199460 :   ref = expr;
     489                 :             : 
     490                 :      199460 :   poly_int64 bitsize, bitpos;
     491                 :      199460 :   tree var_off;
     492                 :      199460 :   machine_mode mode;
     493                 :      199460 :   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                 :      199460 :   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                 :      199460 :   gcc_assert (base != NULL);
     505                 :             : 
     506                 :      199460 :   if (offset)
     507                 :       33983 :     extend_offset_range (offset);
     508                 :             : 
     509                 :      199460 :   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                 :      199460 :   offset_int cstoff;
     515                 :      199460 :   if (bytepos.is_constant (&cstoff))
     516                 :             :     {
     517                 :      199460 :       offrange[0] += cstoff;
     518                 :      199460 :       offrange[1] += cstoff;
     519                 :             : 
     520                 :             :       /* Besides the reference saved above, also stash the offset
     521                 :             :          for validation.  */
     522                 :      199460 :       if (TREE_CODE (expr) == COMPONENT_REF)
     523                 :       28160 :         refoff = cstoff;
     524                 :             :     }
     525                 :             :   else
     526                 :             :     offrange[1] += maxobjsize;
     527                 :             : 
     528                 :      199460 :   if (var_off)
     529                 :             :     {
     530                 :        1788 :       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                 :        1768 :         offrange[1] += maxobjsize;
     538                 :             :     }
     539                 :             : 
     540                 :      199460 :   if (TREE_CODE (base) == MEM_REF)
     541                 :             :     {
     542                 :        9220 :       tree memrefoff = fold_convert (ptrdiff_type_node, TREE_OPERAND (base, 1));
     543                 :        9220 :       extend_offset_range (memrefoff);
     544                 :             : 
     545                 :       12504 :       if (refoff != HOST_WIDE_INT_MIN
     546                 :        9220 :           && 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                 :        5936 :           offset_int off = tree_to_shwi (memrefoff);
     555                 :        5936 :           refoff += off;
     556                 :             : 
     557                 :        5936 :           if (!integer_zerop (memrefoff)
     558                 :        1370 :               && !COMPLETE_TYPE_P (TREE_TYPE (expr))
     559                 :        5943 :               && 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                 :        9220 :       base = TREE_OPERAND (base, 0);
     569                 :             :     }
     570                 :             : 
     571                 :      199460 :   if (TREE_CODE (ref) == COMPONENT_REF)
     572                 :       28160 :     if (tree size = component_ref_size (ref))
     573                 :       27964 :       if (TREE_CODE (size) == INTEGER_CST)
     574                 :       27946 :         refsize = wi::to_offset (size);
     575                 :             : 
     576                 :      199460 :   if (TREE_CODE (base) == SSA_NAME)
     577                 :       36924 :     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                 :      369578 : builtin_memref::offset_out_of_bounds (int strict, offset_int ooboff[3]) const
     594                 :             : {
     595                 :      369578 :   if (!ptr)
     596                 :             :     return NULL_TREE;
     597                 :             : 
     598                 :             :   /* The offset of the first write access or zero.  */
     599                 :      337735 :   offset_int wroff = ooboff[2];
     600                 :             : 
     601                 :             :   /* A temporary, possibly adjusted, copy of the offset range.  */
     602                 :      337735 :   offset_int offrng[2] = { ooboff[0], ooboff[1] };
     603                 :             : 
     604                 :      337735 :   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                 :       71653 :       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                 :      337735 :   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                 :      337735 :   bool hib = wi::les_p (offrng[0], offrng[1]);
     618                 :      337735 :   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                 :      337735 :   offset_int size = basesize;
     626                 :      337735 :   tree obj = base;
     627                 :             : 
     628                 :      337735 :   const bool decl_p = DECL_P (obj);
     629                 :             : 
     630                 :      337735 :   if (basesize < 0)
     631                 :             :     {
     632                 :      171706 :       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                 :      171706 :       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                 :      171633 :       if (strict
     645                 :      171633 :           && !decl_p
     646                 :        1692 :           && ref
     647                 :         818 :           && refsize >= 0
     648                 :      172321 :           && 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                 :      170999 :         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                 :      166663 :   if ((decl_p && offrng[hib] < 0) || offrng[lob] > size)
     662                 :         240 :     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                 :      166423 :   endoff = offrng[lob] + sizrange[0];
     668                 :      166423 :   if (endoff > maxobjsize)
     669                 :          21 :     return error_mark_node;
     670                 :             : 
     671                 :      166402 :   if (strict
     672                 :      166402 :       && decl_p
     673                 :        3454 :       && ref
     674                 :      166428 :       && refsize >= 0
     675                 :      167010 :       && 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                 :         582 :       size = refoff + refsize;
     680                 :         582 :       obj = ref;
     681                 :             :     }
     682                 :             : 
     683                 :      166402 :   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                 :        2239 :   ooboff[lob] = size;
     689                 :             : 
     690                 :        2239 :   if (endoff > ooboff[lob])
     691                 :        2239 :     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                 :      185301 : builtin_access::builtin_access (pointer_query &ptrqry, gimple *call,
     702                 :             :                                 builtin_memref &dst,
     703                 :      185301 :                                 builtin_memref &src)
     704                 :      185301 : : dstref (&dst), srcref (&src), sizrange (), ovloff (), ovlsiz (),
     705                 :      185301 :   dstoff (), srcoff (), dstsiz (), srcsiz ()
     706                 :             : {
     707                 :      185301 :   dstoff[0] = dst.offrange[0];
     708                 :      185301 :   dstoff[1] = dst.offrange[1];
     709                 :             : 
     710                 :             :   /* Zero out since the offset_int ctors invoked above are no-op.  */
     711                 :      185301 :   srcoff[0] = srcoff[1] = 0;
     712                 :      185301 :   dstsiz[0] = dstsiz[1] = 0;
     713                 :      185301 :   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                 :      185301 :   int ostype = 1;
     718                 :             : 
     719                 :             :   /* True when the size of one reference depends on the offset of
     720                 :             :      itself or the other.  */
     721                 :      185301 :   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                 :      185301 :   bool dstadjust_p = false;
     727                 :             : 
     728                 :             :   /* The size argument number (depends on the built-in).  */
     729                 :      185301 :   unsigned sizeargno = 2;
     730                 :             : 
     731                 :      185301 :   tree func = gimple_call_fndecl (call);
     732                 :      185301 :   switch (DECL_FUNCTION_CODE (func))
     733                 :             :     {
     734                 :      123298 :     case BUILT_IN_MEMCPY:
     735                 :      123298 :     case BUILT_IN_MEMCPY_CHK:
     736                 :      123298 :     case BUILT_IN_MEMPCPY:
     737                 :      123298 :     case BUILT_IN_MEMPCPY_CHK:
     738                 :      123298 :       ostype = 0;
     739                 :      123298 :       depends_p = false;
     740                 :      123298 :       detect_overlap = &builtin_access::generic_overlap;
     741                 :      123298 :       break;
     742                 :             : 
     743                 :       18650 :     case BUILT_IN_MEMMOVE:
     744                 :       18650 :     case BUILT_IN_MEMMOVE_CHK:
     745                 :             :       /* For memmove there is never any overlap to check for.  */
     746                 :       18650 :       ostype = 0;
     747                 :       18650 :       depends_p = false;
     748                 :       18650 :       detect_overlap = &builtin_access::no_overlap;
     749                 :       18650 :       break;
     750                 :             : 
     751                 :       31883 :     case BUILT_IN_MEMSET:
     752                 :       31883 :     case BUILT_IN_MEMSET_CHK:
     753                 :             :       /* For memset there is never any overlap to check for.  */
     754                 :       31883 :       ostype = 0;
     755                 :       31883 :       depends_p = false;
     756                 :       31883 :       detect_overlap = &builtin_access::no_overlap;
     757                 :       31883 :       break;
     758                 :             : 
     759                 :        4696 :     case BUILT_IN_STPNCPY:
     760                 :        4696 :     case BUILT_IN_STPNCPY_CHK:
     761                 :        4696 :     case BUILT_IN_STRNCPY:
     762                 :        4696 :     case BUILT_IN_STRNCPY_CHK:
     763                 :        4696 :       dstref->strbounded_p = true;
     764                 :        4696 :       detect_overlap = &builtin_access::strcpy_overlap;
     765                 :        4696 :       break;
     766                 :             : 
     767                 :        3918 :     case BUILT_IN_STPCPY:
     768                 :        3918 :     case BUILT_IN_STPCPY_CHK:
     769                 :        3918 :     case BUILT_IN_STRCPY:
     770                 :        3918 :     case BUILT_IN_STRCPY_CHK:
     771                 :        3918 :       detect_overlap = &builtin_access::strcpy_overlap;
     772                 :        3918 :       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                 :      185301 :   if (dst.basesize < 0)
     796                 :             :     {
     797                 :      185301 :       access_ref aref;
     798                 :      185301 :       if (ptrqry.get_ref (dst.base, call, &aref, ostype) && aref.base0)
     799                 :       89293 :         dst.basesize = aref.sizrng[1];
     800                 :             :       else
     801                 :       96008 :         dst.basesize = HOST_WIDE_INT_MIN;
     802                 :             :     }
     803                 :             : 
     804                 :      185301 :   if (src.base && src.basesize < 0)
     805                 :             :     {
     806                 :      153411 :       access_ref aref;
     807                 :      153411 :       if (ptrqry.get_ref (src.base, call, &aref, ostype) && aref.base0)
     808                 :       77136 :         src.basesize = aref.sizrng[1];
     809                 :             :       else
     810                 :       76275 :         src.basesize = HOST_WIDE_INT_MIN;
     811                 :             :     }
     812                 :             : 
     813                 :      185301 :   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                 :      185301 :   offset_int bounds[2] = { maxobjsize, maxobjsize };
     822                 :      185301 :   if (dstref->strbounded_p)
     823                 :             :     {
     824                 :        6204 :       unsigned nargs = gimple_call_num_args (call);
     825                 :        6204 :       if (nargs <= sizeargno)
     826                 :           4 :         return;
     827                 :             : 
     828                 :        6200 :       tree size = gimple_call_arg (call, sizeargno);
     829                 :        6200 :       tree range[2];
     830                 :        6200 :       if (get_size_range (ptrqry.rvals, size, call, range, true))
     831                 :             :         {
     832                 :        6200 :           bounds[0] = wi::to_offset (range[0]);
     833                 :        6200 :           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                 :       10482 :       if (dstref->sizrange[0] == 0 && dstref->sizrange[1] == maxobjsize
     841                 :       10482 :           && srcref->sizrange[0] == 0 && srcref->sizrange[1] == maxobjsize)
     842                 :             :         {
     843                 :        3352 :           dstref->sizrange[0] = bounds[0];
     844                 :        3352 :           dstref->sizrange[1] = bounds[1];
     845                 :             :         }
     846                 :             :     }
     847                 :             : 
     848                 :      185297 :   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                 :      185297 :   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                 :       16559 :       dstref->sizrange[0] = srcref->sizrange[0];
     859                 :       16559 :       dstref->sizrange[1] = srcref->sizrange[1];
     860                 :       16559 :       dstsize_set = true;
     861                 :             :     }
     862                 :      168738 :   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                 :       96889 :       srcref->sizrange[0] = dstref->sizrange[0];
     867                 :       96889 :       srcref->sizrange[1] = dstref->sizrange[1];
     868                 :             : 
     869                 :       96889 :       if (depends_p)
     870                 :             :         {
     871                 :        8861 :           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                 :        5923 :               srcref->sizrange[0] = bounds[1] > 0 ? 1 : 0;
     876                 :        5859 :               offset_int bound = wi::umin (srcref->basesize, bounds[1]);
     877                 :        5859 :               if (bound < srcref->sizrange[1])
     878                 :        1213 :                 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                 :        8861 :           if (srcref->offrange[1] >= 0
     885                 :        8861 :               && srcref->offrange[1] < srcref->sizrange[0])
     886                 :        6000 :             srcref->sizrange[0] -= srcref->offrange[1];
     887                 :             :           else
     888                 :        2861 :             srcref->sizrange[0] = 1;
     889                 :             : 
     890                 :        8861 :           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                 :      185297 :   if (detect_overlap == &builtin_access::generic_overlap)
     903                 :             :     {
     904                 :      123298 :       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                 :       61999 :   else if (detect_overlap == &builtin_access::strcpy_overlap)
     917                 :             :     {
     918                 :        8612 :       if (!dstref->strbounded_p)
     919                 :             :         {
     920                 :             :           /* For strcpy, adjust the destination size range to match that
     921                 :             :              of the source computed above.  */
     922                 :        3918 :           if (depends_p && dstadjust_p)
     923                 :             :             {
     924                 :        2307 :               dstref->sizrange[0] = srcref->sizrange[0];
     925                 :        2307 :               dstref->sizrange[1] = srcref->sizrange[1];
     926                 :             :             }
     927                 :             :         }
     928                 :             :     }
     929                 :       53387 :   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                 :      185297 :   if (dstref->strbounded_p)
     936                 :             :     {
     937                 :             :       /* For strncpy, adjust the destination size range to match that
     938                 :             :          of the source computed above.  */
     939                 :        6200 :       dstref->sizrange[0] = bounds[0];
     940                 :        6200 :       dstref->sizrange[1] = bounds[1];
     941                 :             : 
     942                 :        6200 :       if (bounds[0] < srcref->sizrange[0])
     943                 :        2586 :         srcref->sizrange[0] = bounds[0];
     944                 :             : 
     945                 :        6200 :       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                 :       24082 : clamp_offset (tree base, offset_int refoff[2], offset_int maxobjsize)
    1312                 :             : {
    1313                 :       24082 :   if (!base || TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE)
    1314                 :             :     return;
    1315                 :             : 
    1316                 :       10056 :   if (refoff[0] < 0 && refoff[1] >= 0)
    1317                 :           0 :     refoff[0] = 0;
    1318                 :             : 
    1319                 :       10056 :   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                 :       12069 : builtin_access::overlap ()
    1338                 :             : {
    1339                 :       12069 :   builtin_access &acs = *this;
    1340                 :             : 
    1341                 :       12069 :   const offset_int maxobjsize = dstref->maxobjsize;
    1342                 :             : 
    1343                 :       12069 :   acs.sizrange[0] = wi::smax (dstref->sizrange[0],
    1344                 :       12069 :                               srcref->sizrange[0]).to_shwi ();
    1345                 :       12069 :   acs.sizrange[1] = wi::smax (dstref->sizrange[1],
    1346                 :       12069 :                               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                 :       12069 :   offset_int size = dstref->sizrange[0] + srcref->sizrange[0];
    1352                 :       12069 :   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                 :       12041 :   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                 :       12041 :   clamp_offset (dstref->base, acs.dstoff, maxobjsize);
    1367                 :             : 
    1368                 :       12041 :   acs.srcoff[0] = srcref->offrange[0];
    1369                 :       12041 :   acs.srcoff[1] = srcref->offrange[1];
    1370                 :             : 
    1371                 :       12041 :   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                 :       12041 :   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                 :       12041 :   offset_int maxoff = acs.dstoff[0] + dstref->sizrange[0];
    1390                 :       12041 :   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                 :       12012 :   if (acs.srcoff[1] < acs.srcoff[0])
    1399                 :             :     {
    1400                 :           0 :       acs.srcoff[0] = -maxobjsize - 1;
    1401                 :           0 :       acs.srcoff[1] = maxobjsize;
    1402                 :             :     }
    1403                 :             : 
    1404                 :       12012 :   maxoff = acs.srcoff[0] + srcref->sizrange[0];
    1405                 :       12012 :   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                 :       11984 :   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                 :       12069 : maybe_diag_overlap (location_t loc, gimple *call, builtin_access &acs)
    1444                 :             : {
    1445                 :       12069 :   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                 :          53 :           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                 :          52 :           else if (ovlsiz[1] >= 0 && ovlsiz[1] < maxobjsize.to_shwi ())
    1560                 :          52 :             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                 :          53 :           return true;
    1575                 :             :         }
    1576                 :             : 
    1577                 :          41 :       if (ovlsiz[0] != ovlsiz[1])
    1578                 :          37 :         ovlsiz[1] = maxobjsize.to_shwi ();
    1579                 :             : 
    1580                 :          41 :       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                 :          37 :       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                 :          37 :         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                 :          41 :       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                 :      369681 : maybe_diag_access_bounds (gimple *call, tree func, int strict,
    1705                 :             :                           const builtin_memref &ref, offset_int wroff,
    1706                 :             :                           bool do_warn)
    1707                 :             : {
    1708                 :      369681 :   location_t loc = gimple_location (call);
    1709                 :      369681 :   const offset_int maxobjsize = ref.maxobjsize;
    1710                 :             : 
    1711                 :      369681 :   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                 :      369681 :   if (ref.sizrange[0] > maxobjsize)
    1716                 :             :     {
    1717                 :         109 :       const opt_code opt = OPT_Wstringop_overflow_;
    1718                 :             :       /* Return true without issuing a warning.  */
    1719                 :         109 :       if (!do_warn)
    1720                 :             :         return opt;
    1721                 :             : 
    1722                 :         109 :       if (ref.ref && warning_suppressed_p (ref.ref, OPT_Wstringop_overflow_))
    1723                 :             :         return no_warning;
    1724                 :             : 
    1725                 :         109 :       bool warned = false;
    1726                 :         109 :       if (warn_stringop_overflow)
    1727                 :             :         {
    1728                 :         103 :           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                 :          18 :             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                 :         169 :           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                 :      369578 :   if (maxobjsize < wroff)
    1750                 :           0 :     wroff = 0;
    1751                 :      369578 :   offset_int ooboff[] = { ref.offrange[0], ref.offrange[1], wroff };
    1752                 :      369578 :   tree oobref = ref.offset_out_of_bounds (strict, ooboff);
    1753                 :      369578 :   if (!oobref)
    1754                 :             :     return no_warning;
    1755                 :             : 
    1756                 :        2573 :   const opt_code opt = OPT_Warray_bounds_;
    1757                 :             :   /* Return true without issuing a warning.  */
    1758                 :        2573 :   if (!do_warn)
    1759                 :             :     return opt;
    1760                 :             : 
    1761                 :        1440 :   if (!warn_array_bounds)
    1762                 :             :     return no_warning;
    1763                 :             : 
    1764                 :         531 :   if (warning_suppressed_p (ref.ptr, opt)
    1765                 :         531 :       || (ref.ref && warning_suppressed_p (ref.ref, opt)))
    1766                 :          18 :     return no_warning;
    1767                 :             : 
    1768                 :         513 :   char rangestr[2][64];
    1769                 :         513 :   if (ooboff[0] == ooboff[1]
    1770                 :         513 :       || (ooboff[0] != ref.offrange[0]
    1771                 :         172 :           && ooboff[0].to_shwi () >= ooboff[1].to_shwi ()))
    1772                 :         222 :     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                 :         513 :   bool warned = false;
    1779                 :             : 
    1780                 :         513 :   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                 :         491 :   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                 :         300 :       bool form = ooboff[0] != ref.offrange[0];
    1823                 :             : 
    1824                 :         300 :       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                 :          21 :       else if (ref.basesize < maxobjsize)
    1852                 :          25 :         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                 :         322 :   return warned ? opt : no_warning;
    1910                 :      369681 : }
    1911                 :             : 
    1912                 :             : /* Check a CALL statement for restrict-violations and issue warnings
    1913                 :             :    if/when appropriate.  */
    1914                 :             : 
    1915                 :             : void
    1916                 :     5135699 : pass_wrestrict::check_call (gimple *call)
    1917                 :             : {
    1918                 :             :   /* Avoid checking the call if it has already been diagnosed for
    1919                 :             :      some reason.  */
    1920                 :     5135699 :   if (warning_suppressed_p (call, OPT_Wrestrict))
    1921                 :             :     return;
    1922                 :             : 
    1923                 :     5126719 :   tree func = gimple_call_fndecl (call);
    1924                 :     5126719 :   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                 :     1168489 :   unsigned dst_idx = -1;
    1930                 :     1168489 :   unsigned src_idx = -1;
    1931                 :     1168489 :   unsigned bnd_idx = -1;
    1932                 :             : 
    1933                 :             :   /* Is this CALL to a string function (as opposed to one to a raw
    1934                 :             :      memory function).  */
    1935                 :     1168489 :   bool strfun = true;
    1936                 :             : 
    1937                 :     1168489 :   switch (DECL_FUNCTION_CODE (func))
    1938                 :             :     {
    1939                 :      102311 :     case BUILT_IN_MEMCPY:
    1940                 :      102311 :     case BUILT_IN_MEMCPY_CHK:
    1941                 :      102311 :     case BUILT_IN_MEMPCPY:
    1942                 :      102311 :     case BUILT_IN_MEMPCPY_CHK:
    1943                 :      102311 :     case BUILT_IN_MEMMOVE:
    1944                 :      102311 :     case BUILT_IN_MEMMOVE_CHK:
    1945                 :      102311 :       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                 :        2917 :     case BUILT_IN_STPCPY:
    1966                 :        2917 :     case BUILT_IN_STPCPY_CHK:
    1967                 :        2917 :     case BUILT_IN_STRCPY:
    1968                 :        2917 :     case BUILT_IN_STRCPY_CHK:
    1969                 :        2917 :     case BUILT_IN_STRCAT:
    1970                 :        2917 :     case BUILT_IN_STRCAT_CHK:
    1971                 :        2917 :       dst_idx = 0;
    1972                 :        2917 :       src_idx = 1;
    1973                 :        2917 :       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                 :      140256 :   unsigned nargs = gimple_call_num_args (call);
    1983                 :             : 
    1984                 :      140256 :   tree dst = dst_idx < nargs ? gimple_call_arg (call, dst_idx) : NULL_TREE;
    1985                 :      140244 :   tree src = src_idx < nargs ? gimple_call_arg (call, src_idx) : NULL_TREE;
    1986                 :      140256 :   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                 :      140256 :   if (!dstwr && strfun)
    1991                 :        2923 :     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                 :      140256 :   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                 :      140244 :   if (TREE_CODE (TREE_TYPE (dst)) != POINTER_TYPE
    2002                 :      138030 :       || (src && TREE_CODE (TREE_TYPE (src)) != POINTER_TYPE)
    2003                 :      277590 :       || (dstwr && !INTEGRAL_TYPE_P (TREE_TYPE (dstwr))))
    2004                 :             :     return;
    2005                 :             : 
    2006                 :      137344 :   opt_code opt = check_bounds_or_overlap (m_ptr_qry, call, dst, src, dstwr,
    2007                 :             :                                           NULL_TREE);
    2008                 :             :   /* Avoid diagnosing the call again.  */
    2009                 :      137344 :   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                 :       47957 : 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                 :       95914 :   pointer_query ptrqry (get_range_query (cfun));
    2027                 :       47957 :   return check_bounds_or_overlap (ptrqry,
    2028                 :             :                                   call, dst, src, dstsize, srcsize,
    2029                 :       47957 :                                   bounds_only, do_warn);
    2030                 :       47957 : }
    2031                 :             : 
    2032                 :             : opt_code
    2033                 :      185301 : 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                 :      185301 :   tree func = gimple_call_fndecl (call);
    2039                 :             : 
    2040                 :      185301 :   builtin_memref dstref (ptrqry, call, dst, dstsize);
    2041                 :      185301 :   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                 :      185301 :   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                 :      185301 :   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                 :      185301 :   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                 :      185301 :   opt_code opt
    2059                 :      185301 :     = maybe_diag_access_bounds (call, func, strict, dstref, wroff, do_warn);
    2060                 :      185301 :   if (opt == no_warning)
    2061                 :      184380 :     opt = maybe_diag_access_bounds (call, func, strict, srcref, 0, do_warn);
    2062                 :             : 
    2063                 :      184380 :   if (opt != no_warning)
    2064                 :             :     {
    2065                 :        1681 :       if (do_warn)
    2066                 :         548 :         suppress_warning (call, opt);
    2067                 :        1681 :       return opt;
    2068                 :             :     }
    2069                 :             : 
    2070                 :      183620 :   if (!warn_restrict || bounds_only || !src)
    2071                 :             :     return no_warning;
    2072                 :             : 
    2073                 :       13080 :   if (!bounds_only)
    2074                 :             :     {
    2075                 :       13080 :       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                 :       12137 :   location_t loc = gimple_location (call);
    2088                 :       12137 :   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                 :       12069 :   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                 :      285689 : make_pass_warn_restrict (gcc::context *ctxt)
    2118                 :             : {
    2119                 :      285689 :   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.1-beta

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