LCOV - code coverage report
Current view: top level - gcc - pointer-query.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 89.1 % 1169 1041
Test Date: 2026-09-19 16:22:48 Functions: 95.3 % 43 41
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Definitions of the pointer_query and related classes.
       2              : 
       3              :    Copyright (C) 2020-2026 Free Software Foundation, Inc.
       4              : 
       5              :    This file is part of GCC.
       6              : 
       7              :    GCC is free software; you can redistribute it and/or modify it under
       8              :    the terms of the GNU General Public License as published by the Free
       9              :    Software Foundation; either version 3, or (at your option) any later
      10              :    version.
      11              : 
      12              :    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              :    WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              :    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              :    for more details.
      16              : 
      17              :    You should have received a copy of the GNU General Public License
      18              :    along with GCC; see the file COPYING3.  If not see
      19              :    <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #include "config.h"
      22              : #include "system.h"
      23              : #include "coretypes.h"
      24              : #include "backend.h"
      25              : #include "tree.h"
      26              : #include "gimple.h"
      27              : #include "stringpool.h"
      28              : #include "tree-vrp.h"
      29              : #include "diagnostic-core.h"
      30              : #include "fold-const.h"
      31              : #include "tree-object-size.h"
      32              : #include "tree-ssa-strlen.h"
      33              : #include "langhooks.h"
      34              : #include "attribs.h"
      35              : #include "gimple-iterator.h"
      36              : #include "gimple-fold.h"
      37              : #include "gimple-ssa.h"
      38              : #include "intl.h"
      39              : #include "attr-fnspec.h"
      40              : #include "gimple-range.h"
      41              : #include "pointer-query.h"
      42              : #include "tree-pretty-print.h"
      43              : #include "tree-ssanames.h"
      44              : #include "target.h"
      45              : 
      46              : static bool compute_objsize_r (tree, gimple *, bool, int, access_ref *,
      47              :                                ssa_name_limit_t &, pointer_query *);
      48              : 
      49              : /* Wrapper around the wide_int overload of get_range that accepts
      50              :    offset_int instead.  For middle end expressions returns the same
      51              :    result.  For a subset of nonconstamt expressions emitted by the front
      52              :    end determines a more precise range than would be possible otherwise.  */
      53              : 
      54              : static bool
      55      4691172 : get_offset_range (tree x, gimple *stmt, offset_int r[2], range_query *rvals)
      56              : {
      57      4691172 :   offset_int add = 0;
      58      4691172 :   if (TREE_CODE (x) == PLUS_EXPR)
      59              :     {
      60              :       /* Handle constant offsets in pointer addition expressions seen
      61              :          n the front end IL.  */
      62           39 :       tree op = TREE_OPERAND (x, 1);
      63           39 :       if (TREE_CODE (op) == INTEGER_CST)
      64              :         {
      65           39 :           op = fold_convert (signed_type_for (TREE_TYPE (op)), op);
      66           39 :           add = wi::to_offset (op);
      67           39 :           x = TREE_OPERAND (x, 0);
      68              :         }
      69              :     }
      70              : 
      71      4691172 :   if (TREE_CODE (x) == NOP_EXPR)
      72              :     /* Also handle conversions to sizetype seen in the front end IL.  */
      73          119 :     x = TREE_OPERAND (x, 0);
      74              : 
      75      4691172 :   tree type = TREE_TYPE (x);
      76      4691172 :   if ((!INTEGRAL_TYPE_P (type)
      77              :        /* ???  We get along without caring about overflow by using
      78              :           offset_int, but that falls apart when indexes are bigger
      79              :           than pointer differences.  */
      80      1637664 :        || TYPE_PRECISION (type) > TYPE_PRECISION (ptrdiff_type_node))
      81      4691357 :       && !POINTER_TYPE_P (type))
      82              :     return false;
      83              : 
      84      4690978 :    if (TREE_CODE (x) != INTEGER_CST
      85       699595 :       && TREE_CODE (x) != SSA_NAME)
      86              :     {
      87          182 :       if (TYPE_UNSIGNED (type)
      88          182 :           && TYPE_PRECISION (type) == TYPE_PRECISION (sizetype))
      89           50 :         type = signed_type_for (type);
      90              : 
      91          182 :       r[0] = wi::to_offset (TYPE_MIN_VALUE (type)) + add;
      92          182 :       r[1] = wi::to_offset (TYPE_MAX_VALUE (type)) + add;
      93          182 :       return x;
      94              :     }
      95              : 
      96     23453980 :   wide_int wr[2];
      97      4690796 :   if (!get_range (x, stmt, wr, rvals))
      98              :     return false;
      99              : 
     100      4527123 :   signop sgn = SIGNED;
     101              :   /* Only convert signed integers or unsigned sizetype to a signed
     102              :      offset and avoid converting large positive values in narrower
     103              :      types to negative offsets.  */
     104      4527123 :   if (TYPE_UNSIGNED (type)
     105      4527123 :       && wr[0].get_precision () < TYPE_PRECISION (sizetype))
     106              :     sgn = UNSIGNED;
     107              : 
     108      4527123 :   r[0] = offset_int::from (wr[0], sgn);
     109      4527123 :   r[1] = offset_int::from (wr[1], sgn);
     110      4527123 :   return true;
     111     14072388 : }
     112              : 
     113              : /* Return the argument that the call STMT to a built-in function returns
     114              :    or null if it doesn't.  On success, set OFFRNG[] to the range of offsets
     115              :    from the argument reflected in the value returned by the built-in if it
     116              :    can be determined, otherwise to 0 and HWI_M1U respectively.  Set
     117              :    *PAST_END for functions like mempcpy that might return a past the end
     118              :    pointer (most functions return a dereferenceable pointer to an existing
     119              :    element of an array).  */
     120              : 
     121              : static tree
     122       344943 : gimple_call_return_array (gimple *stmt, offset_int offrng[2], bool *past_end,
     123              :                           ssa_name_limit_t &snlim, pointer_query *qry)
     124              : {
     125              :   /* Clear and set below for the rare function(s) that might return
     126              :      a past-the-end pointer.  */
     127       344943 :   *past_end = false;
     128              : 
     129       344943 :   {
     130              :     /* Check for attribute fn spec to see if the function returns one
     131              :        of its arguments.  */
     132       344943 :     attr_fnspec fnspec = gimple_call_fnspec (as_a <gcall *>(stmt));
     133       344943 :     unsigned int argno;
     134       344943 :     if (fnspec.returns_arg (&argno))
     135              :       {
     136              :         /* Functions return the first argument (not a range).  */
     137         5799 :         offrng[0] = offrng[1] = 0;
     138         5799 :         return gimple_call_arg (stmt, argno);
     139              :       }
     140              :   }
     141              : 
     142       339144 :   if (gimple_call_num_args (stmt) < 1)
     143              :     return NULL_TREE;
     144              : 
     145       326309 :   tree fn = gimple_call_fndecl (stmt);
     146       326309 :   if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
     147              :     {
     148              :       /* See if this is a call to placement new.  */
     149       257193 :       if (!fn
     150       239030 :           || !DECL_IS_OPERATOR_NEW_P (fn)
     151       266415 :           || DECL_IS_REPLACEABLE_OPERATOR_NEW_P (fn))
     152              :         return NULL_TREE;
     153              : 
     154              :       /* Check the mangling, keeping in mind that operator new takes
     155              :          a size_t which could be unsigned int or unsigned long.  */
     156         9222 :       tree fname = DECL_ASSEMBLER_NAME (fn);
     157         9222 :       if (!id_equal (fname, "_ZnwjPv")       // ordinary form
     158         9171 :           && !id_equal (fname, "_ZnwmPv")    // ordinary form
     159          756 :           && !id_equal (fname, "_ZnajPv")    // array form
     160         9974 :           && !id_equal (fname, "_ZnamPv"))   // array form
     161              :         return NULL_TREE;
     162              : 
     163         8565 :       if (gimple_call_num_args (stmt) != 2)
     164              :         return NULL_TREE;
     165              : 
     166              :       /* Allocation functions return a pointer to the beginning.  */
     167         8565 :       offrng[0] = offrng[1] = 0;
     168         8565 :       return gimple_call_arg (stmt, 1);
     169              :     }
     170              : 
     171        69116 :   switch (DECL_FUNCTION_CODE (fn))
     172              :     {
     173            0 :     case BUILT_IN_MEMCPY:
     174            0 :     case BUILT_IN_MEMCPY_CHK:
     175            0 :     case BUILT_IN_MEMMOVE:
     176            0 :     case BUILT_IN_MEMMOVE_CHK:
     177            0 :     case BUILT_IN_MEMSET:
     178            0 :     case BUILT_IN_STRCAT:
     179            0 :     case BUILT_IN_STRCAT_CHK:
     180            0 :     case BUILT_IN_STRCPY:
     181            0 :     case BUILT_IN_STRCPY_CHK:
     182            0 :     case BUILT_IN_STRNCAT:
     183            0 :     case BUILT_IN_STRNCAT_CHK:
     184            0 :     case BUILT_IN_STRNCPY:
     185            0 :     case BUILT_IN_STRNCPY_CHK:
     186              :       /* Functions return the first argument (not a range).  */
     187            0 :       offrng[0] = offrng[1] = 0;
     188            0 :       return gimple_call_arg (stmt, 0);
     189              : 
     190          211 :     case BUILT_IN_MEMPCPY:
     191          211 :     case BUILT_IN_MEMPCPY_CHK:
     192          211 :       {
     193              :         /* The returned pointer is in a range constrained by the smaller
     194              :            of the upper bound of the size argument and the source object
     195              :            size.  */
     196          211 :         offrng[0] = 0;
     197          211 :         offrng[1] = HOST_WIDE_INT_M1U;
     198          211 :         tree off = gimple_call_arg (stmt, 2);
     199          211 :         bool off_valid = get_offset_range (off, stmt, offrng, qry->rvals);
     200          211 :         if (!off_valid || offrng[0] != offrng[1])
     201              :           {
     202              :             /* If the offset is either indeterminate or in some range,
     203              :                try to constrain its upper bound to at most the size
     204              :                of the source object.  */
     205           92 :             access_ref aref;
     206           92 :             tree src = gimple_call_arg (stmt, 1);
     207           92 :             if (compute_objsize_r (src, stmt, false, 1, &aref, snlim, qry)
     208           92 :                 && aref.sizrng[1] < offrng[1])
     209           36 :               offrng[1] = aref.sizrng[1];
     210              :           }
     211              : 
     212              :         /* Mempcpy may return a past-the-end pointer.  */
     213          211 :         *past_end = true;
     214          211 :         return gimple_call_arg (stmt, 0);
     215              :       }
     216              : 
     217         4316 :     case BUILT_IN_MEMCHR:
     218         4316 :       {
     219         4316 :         tree off = gimple_call_arg (stmt, 2);
     220         4316 :         if (get_offset_range (off, stmt, offrng, qry->rvals))
     221         4258 :           offrng[1] -= 1;
     222              :         else
     223           58 :           offrng[1] = HOST_WIDE_INT_M1U;
     224              : 
     225         4316 :         offrng[0] = 0;
     226         4316 :         return gimple_call_arg (stmt, 0);
     227              :       }
     228              : 
     229          355 :     case BUILT_IN_STRCHR:
     230          355 :     case BUILT_IN_STRRCHR:
     231          355 :     case BUILT_IN_STRSTR:
     232          355 :       offrng[0] = 0;
     233          355 :       offrng[1] = HOST_WIDE_INT_M1U;
     234          355 :       return gimple_call_arg (stmt, 0);
     235              : 
     236           98 :     case BUILT_IN_STPCPY:
     237           98 :     case BUILT_IN_STPCPY_CHK:
     238           98 :       {
     239           98 :         access_ref aref;
     240           98 :         tree src = gimple_call_arg (stmt, 1);
     241           98 :         if (compute_objsize_r (src, stmt, false, 1, &aref, snlim, qry))
     242           98 :           offrng[1] = aref.sizrng[1] - 1;
     243              :         else
     244            0 :           offrng[1] = HOST_WIDE_INT_M1U;
     245              : 
     246           98 :         offrng[0] = 0;
     247           98 :         return gimple_call_arg (stmt, 0);
     248              :       }
     249              : 
     250           88 :     case BUILT_IN_STPNCPY:
     251           88 :     case BUILT_IN_STPNCPY_CHK:
     252           88 :       {
     253              :         /* The returned pointer is in a range between the first argument
     254              :            and it plus the smaller of the upper bound of the size argument
     255              :            and the source object size.  */
     256           88 :         offrng[1] = HOST_WIDE_INT_M1U;
     257           88 :         tree off = gimple_call_arg (stmt, 2);
     258           88 :         if (!get_offset_range (off, stmt, offrng, qry->rvals)
     259           88 :             || offrng[0] != offrng[1])
     260              :           {
     261              :             /* If the offset is either indeterminate or in some range,
     262              :                try to constrain its upper bound to at most the size
     263              :                of the source object.  */
     264           13 :             access_ref aref;
     265           13 :             tree src = gimple_call_arg (stmt, 1);
     266           13 :             if (compute_objsize_r (src, stmt, false, 1, &aref, snlim, qry)
     267           13 :                 && aref.sizrng[1] < offrng[1])
     268           13 :               offrng[1] = aref.sizrng[1];
     269              :           }
     270              : 
     271              :         /* When the source is the empty string the returned pointer is
     272              :            a copy of the argument.  Otherwise stpcpy can also return
     273              :            a past-the-end pointer.  */
     274           88 :         offrng[0] = 0;
     275           88 :         *past_end = true;
     276           88 :         return gimple_call_arg (stmt, 0);
     277              :       }
     278              : 
     279              :     default:
     280              :       break;
     281              :     }
     282              : 
     283              :   return NULL_TREE;
     284              : }
     285              : 
     286              : /* Return true when EXP's range can be determined and set RANGE[] to it
     287              :    after adjusting it if necessary to make EXP a represents a valid size
     288              :    of object, or a valid size argument to an allocation function declared
     289              :    with attribute alloc_size (whose argument may be signed), or to a string
     290              :    manipulation function like memset.
     291              :    When ALLOW_ZERO is set in FLAGS, allow returning a range of [0, 0] for
     292              :    a size in an anti-range [1, N] where N > PTRDIFF_MAX.  A zero range is
     293              :    a (nearly) invalid argument to allocation functions like malloc but it
     294              :    is a valid argument to functions like memset.
     295              :    When USE_LARGEST is set in FLAGS set RANGE to the largest valid subrange
     296              :    in a multi-range, otherwise to the smallest valid subrange.  */
     297              : 
     298              : bool
     299      1175597 : get_size_range (range_query *query, tree exp, gimple *stmt, tree range[2],
     300              :                 int flags /* = 0 */)
     301              : {
     302      1175597 :   if (!exp)
     303              :     return false;
     304              : 
     305      1175597 :   if (tree_fits_uhwi_p (exp))
     306              :     {
     307              :       /* EXP is a constant.  */
     308       819405 :       range[0] = range[1] = exp;
     309       819405 :       return true;
     310              :     }
     311              : 
     312       356192 :   tree exptype = TREE_TYPE (exp);
     313       356192 :   bool integral = INTEGRAL_TYPE_P (exptype);
     314              : 
     315       356192 :   wide_int min, max;
     316       356192 :   enum value_range_kind range_type;
     317              : 
     318       356192 :   if (!query)
     319        47067 :     query = get_range_query (cfun);
     320              : 
     321       356192 :   if (integral)
     322              :     {
     323       356170 :       int_range_max vr;
     324       356170 :       tree tmin, tmax;
     325              : 
     326       356170 :       query->range_of_expr (vr, exp, stmt);
     327              : 
     328       356170 :       if (vr.undefined_p ())
     329            9 :         vr.set_varying (TREE_TYPE (exp));
     330       356170 :       range_type = get_legacy_range (vr, tmin, tmax);
     331       356170 :       min = wi::to_wide (tmin);
     332       356170 :       max = wi::to_wide (tmax);
     333       356170 :     }
     334              :   else
     335              :     range_type = VR_VARYING;
     336              : 
     337       356170 :   if (range_type == VR_VARYING)
     338              :     {
     339        45349 :       if (integral)
     340              :         {
     341              :           /* Use the full range of the type of the expression when
     342              :              no value range information is available.  */
     343        45327 :           range[0] = TYPE_MIN_VALUE (exptype);
     344        45327 :           range[1] = TYPE_MAX_VALUE (exptype);
     345        45327 :           return true;
     346              :         }
     347              : 
     348           22 :       range[0] = NULL_TREE;
     349           22 :       range[1] = NULL_TREE;
     350           22 :       return false;
     351              :     }
     352              : 
     353       310843 :   unsigned expprec = TYPE_PRECISION (exptype);
     354              : 
     355       310843 :   bool signed_p = !TYPE_UNSIGNED (exptype);
     356              : 
     357       310843 :   if (range_type == VR_ANTI_RANGE)
     358              :     {
     359        22437 :       if (signed_p)
     360              :         {
     361           81 :           if (wi::les_p (max, 0))
     362              :             {
     363              :               /* EXP is not in a strictly negative range.  That means
     364              :                  it must be in some (not necessarily strictly) positive
     365              :                  range which includes zero.  Since in signed to unsigned
     366              :                  conversions negative values end up converted to large
     367              :                  positive values, and otherwise they are not valid sizes,
     368              :                  the resulting range is in both cases [0, TYPE_MAX].  */
     369           15 :               min = wi::zero (expprec);
     370           15 :               max = wi::to_wide (TYPE_MAX_VALUE (exptype));
     371              :             }
     372           66 :           else if (wi::les_p (min - 1, 0))
     373              :             {
     374              :               /* EXP is not in a negative-positive range.  That means EXP
     375              :                  is either negative, or greater than max.  Since negative
     376              :                  sizes are invalid make the range [MAX + 1, TYPE_MAX].  */
     377           42 :               min = max + 1;
     378           42 :               max = wi::to_wide (TYPE_MAX_VALUE (exptype));
     379              :             }
     380              :           else
     381              :             {
     382           24 :               max = min - 1;
     383           24 :               min = wi::zero (expprec);
     384              :             }
     385              :         }
     386              :       else
     387              :         {
     388        22356 :           wide_int maxsize = wi::to_wide (max_object_size ());
     389        22356 :           min = wide_int::from (min, maxsize.get_precision (), UNSIGNED);
     390        22356 :           max = wide_int::from (max, maxsize.get_precision (), UNSIGNED);
     391        22356 :           if (wi::eq_p (0, min - 1))
     392              :             {
     393              :               /* EXP is unsigned and not in the range [1, MAX].  That means
     394              :                  it's either zero or greater than MAX.  Even though 0 would
     395              :                  normally be detected by -Walloc-zero, unless ALLOW_ZERO
     396              :                  is set, set the range to [MAX, TYPE_MAX] so that when MAX
     397              :                  is greater than the limit the whole range is diagnosed.  */
     398          362 :               wide_int maxsize = wi::to_wide (max_object_size ());
     399          362 :               if (flags & SR_ALLOW_ZERO)
     400              :                 {
     401          422 :                   if (wi::leu_p (maxsize, max + 1)
     402          211 :                       || !(flags & SR_USE_LARGEST))
     403          125 :                     min = max = wi::zero (expprec);
     404              :                   else
     405              :                     {
     406           86 :                       min = max + 1;
     407           86 :                       max = wi::to_wide (TYPE_MAX_VALUE (exptype));
     408              :                     }
     409              :                 }
     410              :               else
     411              :                 {
     412          151 :                   min = max + 1;
     413          151 :                   max = wi::to_wide (TYPE_MAX_VALUE (exptype));
     414              :                 }
     415          362 :             }
     416        43988 :           else if ((flags & SR_USE_LARGEST)
     417        32001 :                    && wi::ltu_p (max + 1, maxsize))
     418              :             {
     419              :               /* When USE_LARGEST is set and the larger of the two subranges
     420              :                  is a valid size, use it...  */
     421           36 :               min = max + 1;
     422           36 :               max = maxsize;
     423              :             }
     424              :           else
     425              :             {
     426              :               /* ...otherwise use the smaller subrange.  */
     427        21958 :               max = min - 1;
     428        21958 :               min = wi::zero (expprec);
     429              :             }
     430        22356 :         }
     431              :     }
     432              : 
     433       310843 :   range[0] = wide_int_to_tree (exptype, min);
     434       310843 :   range[1] = wide_int_to_tree (exptype, max);
     435              : 
     436       310843 :   return true;
     437       356192 : }
     438              : 
     439              : bool
     440        53609 : get_size_range (tree exp, tree range[2], int flags /* = 0 */)
     441              : {
     442        53609 :   return get_size_range (/*query=*/NULL, exp, /*stmt=*/NULL, range, flags);
     443              : }
     444              : 
     445              : /* If STMT is a call to an allocation function, returns the constant
     446              :    maximum size of the object allocated by the call represented as
     447              :    sizetype.  If nonnull, sets RNG1[] to the range of the size.
     448              :    When nonnull, uses RVALS for range information, otherwise gets global
     449              :    range info.
     450              :    Returns null when STMT is not a call to a valid allocation function.  */
     451              : 
     452              : tree
     453       495809 : gimple_call_alloc_size (gimple *stmt, wide_int rng1[2] /* = NULL */,
     454              :                         range_query *qry /* = NULL */)
     455              : {
     456       495809 :   if (!stmt || !is_gimple_call (stmt))
     457              :     return NULL_TREE;
     458              : 
     459       495805 :   tree allocfntype;
     460       495805 :   if (tree fndecl = gimple_call_fndecl (stmt))
     461       477323 :     allocfntype = TREE_TYPE (fndecl);
     462              :   else
     463        18482 :     allocfntype = gimple_call_fntype (stmt);
     464              : 
     465       495805 :   if (!allocfntype)
     466              :     return NULL_TREE;
     467              : 
     468       494725 :   unsigned argidx1 = UINT_MAX, argidx2 = UINT_MAX;
     469       494725 :   tree at = lookup_attribute ("alloc_size", TYPE_ATTRIBUTES (allocfntype));
     470       494725 :   if (!at)
     471              :     {
     472       348662 :       if (!gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA_WITH_ALIGN))
     473              :         return NULL_TREE;
     474              : 
     475              :       argidx1 = 0;
     476              :     }
     477              : 
     478       150864 :   unsigned nargs = gimple_call_num_args (stmt);
     479              : 
     480       150864 :   if (argidx1 == UINT_MAX)
     481              :     {
     482       146063 :       tree atval = TREE_VALUE (at);
     483       146063 :       if (!atval)
     484              :         return NULL_TREE;
     485              : 
     486       146063 :       argidx1 = TREE_INT_CST_LOW (TREE_VALUE (atval)) - 1;
     487       146063 :       if (nargs <= argidx1)
     488              :         return NULL_TREE;
     489              : 
     490       146063 :       atval = TREE_CHAIN (atval);
     491       146063 :       if (atval)
     492              :         {
     493         1071 :           argidx2 = TREE_INT_CST_LOW (TREE_VALUE (atval)) - 1;
     494         1071 :           if (nargs <= argidx2)
     495              :             return NULL_TREE;
     496              :         }
     497              :     }
     498              : 
     499       150864 :   tree size = gimple_call_arg (stmt, argidx1);
     500              : 
     501       754320 :   wide_int rng1_buf[2];
     502              :   /* If RNG1 is not set, use the buffer.  */
     503       150864 :   if (!rng1)
     504           38 :     rng1 = rng1_buf;
     505              : 
     506              :   /* Use maximum precision to avoid overflow below.  */
     507       150864 :   const int prec = ADDR_MAX_PRECISION;
     508              : 
     509       150864 :   {
     510       150864 :     tree r[2];
     511              :     /* Determine the largest valid range size, including zero.  */
     512       150864 :     if (!get_size_range (qry, size, stmt, r, SR_ALLOW_ZERO | SR_USE_LARGEST))
     513            2 :       return NULL_TREE;
     514       150862 :     rng1[0] = wi::to_wide (r[0], prec);
     515       150862 :     rng1[1] = wi::to_wide (r[1], prec);
     516              :   }
     517              : 
     518       150862 :   if (argidx2 > nargs && TREE_CODE (size) == INTEGER_CST)
     519        55354 :     return fold_convert (sizetype, size);
     520              : 
     521              :   /* To handle ranges do the math in wide_int and return the product
     522              :      of the upper bounds as a constant.  Ignore anti-ranges.  */
     523        95508 :   tree n = argidx2 < nargs ? gimple_call_arg (stmt, argidx2) : integer_one_node;
     524       477540 :   wide_int rng2[2];
     525        95508 :   {
     526        95508 :     tree r[2];
     527              :       /* As above, use the full non-negative range on failure.  */
     528        95508 :     if (!get_size_range (qry, n, stmt, r, SR_ALLOW_ZERO | SR_USE_LARGEST))
     529            0 :       return NULL_TREE;
     530        95508 :     rng2[0] = wi::to_wide (r[0], prec);
     531        95508 :     rng2[1] = wi::to_wide (r[1], prec);
     532              :   }
     533              : 
     534              :   /* Compute products of both bounds for the caller but return the lesser
     535              :      of SIZE_MAX and the product of the upper bounds as a constant.  */
     536        95508 :   rng1[0] = rng1[0] * rng2[0];
     537        95508 :   rng1[1] = rng1[1] * rng2[1];
     538              : 
     539        95508 :   const tree size_max = TYPE_MAX_VALUE (sizetype);
     540        95508 :   if (wi::gtu_p (rng1[1], wi::to_wide (size_max, prec)))
     541              :     {
     542           79 :       rng1[1] = wi::to_wide (size_max, prec);
     543           79 :       return size_max;
     544              :     }
     545              : 
     546        95429 :   return wide_int_to_tree (sizetype, rng1[1]);
     547       739116 : }
     548              : 
     549              : /* For an access to an object referenced to by the function parameter PTR
     550              :    of pointer type, and set RNG[] to the range of sizes of the object
     551              :    obtainedfrom the attribute access specification for the current function.
     552              :    Set STATIC_ARRAY if the array parameter has been declared [static].
     553              :    Return the function parameter on success and null otherwise.  */
     554              : 
     555              : static tree
     556       836626 : gimple_parm_array_size (tree ptr, wide_int rng[2],
     557              :                         bool *static_array /* = NULL */)
     558              : {
     559              :   /* For a function argument try to determine the byte size of the array
     560              :      from the current function declaratation (e.g., attribute access or
     561              :      related).  */
     562       836626 :   tree var = SSA_NAME_VAR (ptr);
     563       836626 :   if (TREE_CODE (var) != PARM_DECL || !POINTER_TYPE_P (TREE_TYPE (var)))
     564              :     return NULL_TREE;
     565              : 
     566       789838 :   const unsigned prec = TYPE_PRECISION (sizetype);
     567              : 
     568       789838 :   rdwr_map rdwr_idx;
     569       789838 :   attr_access *access = get_parm_access (rdwr_idx, var);
     570       789838 :   if (!access)
     571              :     return NULL_TREE;
     572              : 
     573         2834 :   if (access->sizarg != UINT_MAX)
     574              :     {
     575              :       /* TODO: Try to extract the range from the argument based on
     576              :          those of subsequent assertions or based on known calls to
     577              :          the current function.  */
     578              :       return NULL_TREE;
     579              :     }
     580              : 
     581         2814 :   if (!access->minsize)
     582              :     return NULL_TREE;
     583              : 
     584              :   /* Only consider ordinary array bound at level 2 (or above if it's
     585              :      ever added).  */
     586         2003 :   if (warn_array_parameter < 2 && !access->static_p)
     587              :     return NULL_TREE;
     588              : 
     589          215 :   if (static_array)
     590          215 :     *static_array = access->static_p;
     591              : 
     592          215 :   rng[0] = wi::zero (prec);
     593          215 :   rng[1] = wi::uhwi (access->minsize, prec);
     594              :   /* Multiply the array bound encoded in the attribute by the size
     595              :      of what the pointer argument to which it decays points to.  */
     596          215 :   tree eltype = TREE_TYPE (TREE_TYPE (ptr));
     597          215 :   tree size = TYPE_SIZE_UNIT (eltype);
     598          215 :   if (!size || TREE_CODE (size) != INTEGER_CST)
     599              :     return NULL_TREE;
     600              : 
     601          185 :   rng[1] *= wi::to_wide (size, prec);
     602          185 :   return var;
     603       789838 : }
     604              : 
     605              : /* Initialize the object.  */
     606              : 
     607     20235494 : access_ref::access_ref ()
     608     20235494 :   : ref (), eval ([](tree x){ return x; }), deref (), ref_nullptr_p (false),
     609     20235494 :     trail1special (true), base0 (true), parmarray ()
     610              : {
     611              :   /* Set to valid.  */
     612     20235494 :   offrng[0] = offrng[1] = 0;
     613     20235494 :   offmax[0] = offmax[1] = 0;
     614              :   /* Invalidate.   */
     615     20235494 :   sizrng[0] = sizrng[1] = -1;
     616     20235494 : }
     617              : 
     618              : /* Return the PHI node REF refers to or null if it doesn't.  */
     619              : 
     620              : gphi *
     621       623050 : access_ref::phi () const
     622              : {
     623       623050 :   if (!ref || TREE_CODE (ref) != SSA_NAME)
     624              :     return NULL;
     625              : 
     626       620080 :   gimple *def_stmt = SSA_NAME_DEF_STMT (ref);
     627       620080 :   if (!def_stmt || gimple_code (def_stmt) != GIMPLE_PHI)
     628              :     return NULL;
     629              : 
     630       619148 :   return as_a <gphi *> (def_stmt);
     631              : }
     632              : 
     633              : /* Determine the size and offset for ARG, append it to ALL_REFS, and
     634              :    merge the result with *THIS.  Ignore ARG if SKIP_NULL is set and
     635              :    ARG refers to the null pointer.  Return true on success and false
     636              :    on failure.  */
     637              : 
     638              : void
     639       701195 : access_ref::merge_ref (vec<access_ref> *all_refs, tree arg, gimple *stmt,
     640              :                        int ostype, bool skip_null,
     641              :                        ssa_name_limit_t &snlim, pointer_query &qry)
     642              : {
     643       701195 :   access_ref aref;
     644       701195 :   if (!compute_objsize_r (arg, stmt, false, ostype, &aref, snlim, &qry)
     645       701195 :       || aref.sizrng[0] < 0)
     646              :     {
     647              :       /* This may be a PHI with all null pointer arguments.  Handle it
     648              :          conservatively by setting all properties to the most permissive
     649              :          values. */
     650        59801 :       base0 = false;
     651        59801 :       offrng[0] = offrng[1] = 0;
     652        59801 :       add_max_offset ();
     653        59801 :       set_max_size_range ();
     654        59801 :       return;
     655              :     }
     656              : 
     657       641394 :   if (all_refs)
     658              :     {
     659          264 :       access_ref dummy_ref;
     660          264 :       aref.get_ref (all_refs, &dummy_ref, ostype, &snlim, &qry);
     661              :     }
     662              : 
     663       641394 :   if (TREE_CODE (arg) == SSA_NAME)
     664       534658 :     qry.put_ref (arg, aref, ostype);
     665              : 
     666       641394 :   if (all_refs)
     667          264 :     all_refs->safe_push (aref);
     668              : 
     669       641394 :   aref.deref += deref;
     670              : 
     671       641394 :   bool merged_parmarray = aref.parmarray;
     672              : 
     673       641394 :   const bool nullp = skip_null && integer_zerop (arg);
     674       641394 :   const offset_int maxobjsize = wi::to_offset (max_object_size ());
     675       641394 :   offset_int minsize = sizrng[0];
     676              : 
     677       641394 :   if (sizrng[0] < 0)
     678              :     {
     679              :       /* If *THIS doesn't contain a meaningful result yet set it to AREF
     680              :          unless the argument is null and it's okay to ignore it.  */
     681       552132 :       if (!nullp)
     682       532416 :         *this = aref;
     683              : 
     684              :       /* Set if the current argument refers to one or more objects of
     685              :          known size (or range of sizes), as opposed to referring to
     686              :          one or more unknown object(s).  */
     687       552132 :       const bool arg_known_size = (aref.sizrng[0] != 0
     688      1021125 :                                    || aref.sizrng[1] != maxobjsize);
     689       552132 :       if (arg_known_size)
     690        86588 :         sizrng[0] = aref.sizrng[0];
     691              : 
     692              :       return;
     693              :     }
     694              : 
     695              :   /* Disregard null pointers in PHIs with two or more arguments.
     696              :      TODO: Handle this better!  */
     697        89262 :   if (nullp)
     698              :     return;
     699              : 
     700        86164 :   const bool known_size = (sizrng[0] != 0 || sizrng[1] != maxobjsize);
     701              : 
     702       168806 :   if (known_size && aref.sizrng[0] < minsize)
     703        27508 :     minsize = aref.sizrng[0];
     704              : 
     705              :   /* Extend the size and offset of *THIS to account for AREF.  The result
     706              :      can be cached but results in false negatives.  */
     707              : 
     708        86164 :   offset_int orng[2];
     709        86164 :   if (sizrng[1] < aref.sizrng[1])
     710              :     {
     711        27404 :       orng[0] = offrng[0];
     712        27404 :       orng[1] = offrng[1];
     713        27404 :       *this = aref;
     714              :     }
     715              :   else
     716              :     {
     717        58760 :       orng[0] = aref.offrng[0];
     718        58760 :       orng[1] = aref.offrng[1];
     719              :     }
     720              : 
     721        86164 :   if (orng[0] < offrng[0])
     722         7750 :     offrng[0] = orng[0];
     723        86164 :   if (offrng[1] < orng[1])
     724        21832 :     offrng[1] = orng[1];
     725              : 
     726              :   /* Reset the PHI's BASE0 flag if any of the nonnull arguments
     727              :      refers to an object at an unknown offset.  */
     728        86164 :   if (!aref.base0)
     729        17968 :     base0 = false;
     730              : 
     731        86164 :   sizrng[0] = minsize;
     732        86164 :   parmarray = merged_parmarray;
     733              : 
     734        86164 :   return;
     735              : }
     736              : 
     737              : /* Determine and return the largest object to which *THIS refers.  If
     738              :    *THIS refers to a PHI and PREF is nonnull, fill *PREF with the details
     739              :    of the object determined by compute_objsize(ARG, OSTYPE) for each PHI
     740              :    argument ARG.  */
     741              : 
     742              : tree
     743       619144 : access_ref::get_ref (vec<access_ref> *all_refs,
     744              :                      access_ref *pref /* = NULL */,
     745              :                      int ostype /* = 1 */,
     746              :                      ssa_name_limit_t *psnlim /* = NULL */,
     747              :                      pointer_query *qry /* = NULL */) const
     748              : {
     749       619144 :   if (!ref || TREE_CODE (ref) != SSA_NAME)
     750              :     return NULL;
     751              : 
     752              :   /* FIXME: Calling get_ref() with a null PSNLIM is dangerous and might
     753              :      cause unbounded recursion.  */
     754       618938 :   ssa_name_limit_t snlim_buf;
     755       618938 :   if (!psnlim)
     756           82 :     psnlim = &snlim_buf;
     757              : 
     758       618938 :   pointer_query empty_qry;
     759       618938 :   if (!qry)
     760           82 :     qry = &empty_qry;
     761              : 
     762       618938 :   if (gimple *def_stmt = SSA_NAME_DEF_STMT (ref))
     763              :     {
     764       618938 :       if (is_gimple_assign (def_stmt))
     765              :         {
     766            0 :           tree_code code = gimple_assign_rhs_code (def_stmt);
     767            0 :           if (code != MIN_EXPR && code != MAX_EXPR)
     768              :             return NULL_TREE;
     769              : 
     770            0 :           access_ref aref;
     771            0 :           tree arg1 = gimple_assign_rhs1 (def_stmt);
     772            0 :           aref.merge_ref (all_refs, arg1, def_stmt, ostype, false,
     773              :                           *psnlim, *qry);
     774              : 
     775            0 :           tree arg2 = gimple_assign_rhs2 (def_stmt);
     776            0 :           aref.merge_ref (all_refs, arg2, def_stmt, ostype, false,
     777              :                           *psnlim, *qry);
     778              : 
     779            0 :           if (pref && pref != this)
     780              :             {
     781            0 :               tree ref = pref->ref;
     782            0 :               *pref = aref;
     783            0 :               pref->ref = ref;
     784              :             }
     785              : 
     786            0 :           return aref.ref;
     787              :         }
     788              :     }
     789              :   else
     790              :     return NULL_TREE;
     791              : 
     792       618938 :   gphi *phi_stmt = this->phi ();
     793       618938 :   if (!phi_stmt)
     794           23 :     return ref;
     795              : 
     796       618915 :   if (!psnlim->visit_phi (ref))
     797              :     return NULL_TREE;
     798              : 
     799              :   /* The conservative result of the PHI reflecting the offset and size
     800              :      of the largest PHI argument, regardless of whether or not they all
     801              :      refer to the same object.  */
     802       559098 :   access_ref phi_ref;
     803       559098 :   if (pref)
     804              :     {
     805              :       /* The identity of the object has not been determined yet but
     806              :          PREF->REF is set by the caller to the PHI for convenience.
     807              :          The size is negative/invalid and the offset is zero (it's
     808              :          updated only after the identity of the object has been
     809              :          established).  */
     810       559098 :       gcc_assert (pref->sizrng[0] < 0);
     811       559098 :       gcc_assert (pref->offrng[0] == 0 && pref->offrng[1] == 0);
     812              : 
     813       559098 :       phi_ref = *pref;
     814              :     }
     815              : 
     816       559098 :   const offset_int maxobjsize = wi::to_offset (max_object_size ());
     817       559098 :   const unsigned nargs = gimple_phi_num_args (phi_stmt);
     818       739455 :   for (unsigned i = 0; i < nargs; ++i)
     819              :     {
     820       701195 :       access_ref phi_arg_ref;
     821       701195 :       bool skip_null = i || i + 1 < nargs;
     822       701195 :       tree arg = gimple_phi_arg_def (phi_stmt, i);
     823       701195 :       phi_ref.merge_ref (all_refs, arg, phi_stmt, ostype, skip_null,
     824              :                          *psnlim, *qry);
     825              : 
     826       701195 :       if (!phi_ref.base0
     827      1222033 :           && phi_ref.sizrng[0] == 0
     828      1222033 :           && phi_ref.sizrng[1] >= maxobjsize)
     829              :         /* When an argument results in the most permissive result,
     830              :            the remaining arguments cannot constrain it.  Short-circuit
     831              :            the evaluation.  */
     832              :         break;
     833              :     }
     834              : 
     835       559098 :   if (phi_ref.sizrng[0] < 0)
     836              :     {
     837              :       /* Fail if none of the PHI's arguments resulted in updating PHI_REF
     838              :          (perhaps because they have all been already visited by prior
     839              :          recursive calls).  */
     840            0 :       psnlim->leave_phi (ref);
     841            0 :       return NULL_TREE;
     842              :     }
     843              : 
     844              :   /* Avoid changing *THIS.  */
     845       559098 :   if (pref && pref != this)
     846              :     {
     847              :       /* Keep the SSA_NAME of the PHI unchanged so that all PHI arguments
     848              :          can be referred to later if necessary.  This is useful even if
     849              :          they all refer to the same object.  */
     850       559098 :       tree ref = pref->ref;
     851       559098 :       *pref = phi_ref;
     852       559098 :       pref->ref = ref;
     853              :     }
     854              : 
     855       559098 :   psnlim->leave_phi (ref);
     856              : 
     857       559098 :   return phi_ref.ref;
     858       618938 : }
     859              : 
     860              : /* Return the maximum amount of space remaining and if non-null, set
     861              :    argument to the minimum.  */
     862              : 
     863              : offset_int
     864     15955135 : access_ref::size_remaining (offset_int *pmin /* = NULL */) const
     865              : {
     866     15955135 :   offset_int minbuf;
     867     15955135 :   if (!pmin)
     868     11714205 :     pmin = &minbuf;
     869              : 
     870     15955135 :   if (sizrng[0] < 0)
     871              :     {
     872              :       /* If the identity of the object hasn't been determined return
     873              :          the maximum size range.  */
     874            0 :       *pmin = 0;
     875            0 :       return wi::to_offset (max_object_size ());
     876              :     }
     877              : 
     878              :   /* add_offset() ensures the offset range isn't inverted.  */
     879     15955135 :   gcc_checking_assert (offrng[0] <= offrng[1]);
     880              : 
     881     15955135 :   if (base0)
     882              :     {
     883              :       /* The offset into referenced object is zero-based (i.e., it's
     884              :          not referenced by a pointer into middle of some unknown object).  */
     885     10350247 :       if (offrng[0] < 0 && offrng[1] < 0)
     886              :         {
     887              :           /* If the offset is negative the remaining size is zero.  */
     888         2509 :           *pmin = 0;
     889         2509 :           return 0;
     890              :         }
     891              : 
     892     10347738 :       if (sizrng[1] <= offrng[0])
     893              :         {
     894              :           /* If the starting offset is greater than or equal to the upper
     895              :              bound on the size of the object, the space remaining is zero.
     896              :              As a special case, if it's equal, set *PMIN to -1 to let
     897              :              the caller know the offset is valid and just past the end.  */
     898        77047 :           *pmin = sizrng[1] == offrng[0] ? -1 : 0;
     899        72463 :           return 0;
     900              :         }
     901              : 
     902              :       /* Otherwise return the size minus the lower bound of the offset.  */
     903     10275275 :       offset_int or0 = offrng[0] < 0 ? 0 : offrng[0];
     904              : 
     905     10275275 :       *pmin = sizrng[0] - or0;
     906     10275275 :       return sizrng[1] - or0;
     907              :     }
     908              : 
     909              :   /* The offset to the referenced object isn't zero-based (i.e., it may
     910              :      refer to a byte other than the first.  The size of such an object
     911              :      is constrained only by the size of the address space (the result
     912              :      of max_object_size()).  */
     913      5604888 :   if (sizrng[1] <= offrng[0])
     914              :     {
     915            5 :       *pmin = 0;
     916            5 :       return 0;
     917              :     }
     918              : 
     919      5604883 :   offset_int or0 = offrng[0] < 0 ? 0 : offrng[0];
     920              : 
     921      5604883 :   *pmin = sizrng[0] - or0;
     922      5604883 :   return sizrng[1] - or0;
     923              : }
     924              : 
     925              : /* Return true if the offset and object size are in range for SIZE.  */
     926              : 
     927              : bool
     928       617905 : access_ref::offset_in_range (const offset_int &size) const
     929              : {
     930       617905 :   if (size_remaining () < size)
     931              :     return false;
     932              : 
     933       605912 :   if (base0)
     934        63294 :     return offmax[0] >= 0 && offmax[1] <= sizrng[1];
     935              : 
     936       542636 :   offset_int maxoff = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node));
     937       542636 :   return offmax[0] > -maxoff && offmax[1] < maxoff;
     938              : }
     939              : 
     940              : /* Add the range [MIN, MAX] to the offset range.  For known objects (with
     941              :    zero-based offsets) at least one of whose offset's bounds is in range,
     942              :    constrain the other (or both) to the bounds of the object (i.e., zero
     943              :    and the upper bound of its size).  This improves the quality of
     944              :    diagnostics.  */
     945              : 
     946      8285409 : void access_ref::add_offset (const offset_int &min, const offset_int &max)
     947              : {
     948      8285409 :   if (min <= max)
     949              :     {
     950              :       /* To add an ordinary range just add it to the bounds.  */
     951      8063092 :       offrng[0] += min;
     952      8063092 :       offrng[1] += max;
     953              :     }
     954       222317 :   else if (!base0)
     955              :     {
     956              :       /* To add an inverted range to an offset to an unknown object
     957              :          expand it to the maximum.  */
     958       193253 :       add_max_offset ();
     959      4651366 :       return;
     960              :     }
     961              :   else
     962              :     {
     963              :       /* To add an inverted range to an offset to an known object set
     964              :          the upper bound to the maximum representable offset value
     965              :          (which may be greater than MAX_OBJECT_SIZE).
     966              :          The lower bound is either the sum of the current offset and
     967              :          MIN when abs(MAX) is greater than the former, or zero otherwise.
     968              :          Zero because then the inverted range includes the negative of
     969              :          the lower bound.  */
     970        29064 :       offset_int maxoff = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node));
     971        29064 :       offrng[1] = maxoff;
     972              : 
     973        29064 :       if (max >= 0)
     974              :         {
     975            0 :           offrng[0] = 0;
     976            0 :           if (offmax[0] > 0)
     977            0 :             offmax[0] = 0;
     978            0 :           return;
     979              :         }
     980              : 
     981        29064 :       offset_int absmax = wi::abs (max);
     982        29064 :       if (offrng[0] < absmax)
     983              :         {
     984        26610 :           offrng[0] += min;
     985              :           /* Cap the lower bound at the upper (set to MAXOFF above)
     986              :              to avoid inadvertently recreating an inverted range.  */
     987        26610 :           if (offrng[1] < offrng[0])
     988            2 :             offrng[0] = offrng[1];
     989              :         }
     990              :       else
     991         2454 :         offrng[0] = 0;
     992              :     }
     993              : 
     994              :   /* Set the minimum and maximmum computed so far. */
     995      8092156 :   if (offrng[1] < 0 && offrng[1] < offmax[0])
     996        30598 :     offmax[0] = offrng[1];
     997      8092156 :   if (offrng[0] > 0 && offrng[0] > offmax[1])
     998      2900255 :     offmax[1] = offrng[0];
     999              : 
    1000      8092156 :   if (!base0)
    1001              :     return;
    1002              : 
    1003              :   /* When referencing a known object check to see if the offset computed
    1004              :      so far is in bounds... */
    1005      3827296 :   offset_int remrng[2];
    1006      3827296 :   remrng[1] = size_remaining (remrng);
    1007      3827296 :   if (remrng[1] > 0 || remrng[0] < 0)
    1008              :     {
    1009              :       /* ...if so, constrain it so that neither bound exceeds the size of
    1010              :          the object.  Out of bounds offsets are left unchanged, and, for
    1011              :          better or worse, become in bounds later.  They should be detected
    1012              :          and diagnosed at the point they first become invalid by
    1013              :          -Warray-bounds.  */
    1014      3823900 :       if (offrng[0] < 0)
    1015       109026 :         offrng[0] = 0;
    1016      3823900 :       if (offrng[1] > sizrng[1])
    1017       138482 :         offrng[1] = sizrng[1];
    1018              :     }
    1019              : }
    1020              : 
    1021              : /* Issue one inform message describing each target of an access REF.
    1022              :    WRITE is set for a write access and clear for a read access.  */
    1023              : 
    1024              : void
    1025         3580 : access_ref::inform_access (access_mode mode, int ostype /* = 1 */) const
    1026              : {
    1027         3580 :   const access_ref &aref = *this;
    1028         3580 :   if (!aref.ref)
    1029         3081 :     return;
    1030              : 
    1031         3439 :   if (phi ())
    1032              :     {
    1033              :       /* Set MAXREF to refer to the largest object and fill ALL_REFS
    1034              :          with data for all objects referenced by the PHI arguments.  */
    1035           82 :       access_ref maxref;
    1036           82 :       auto_vec<access_ref> all_refs;
    1037           82 :       if (!get_ref (&all_refs, &maxref, ostype))
    1038              :         return;
    1039              : 
    1040           82 :       if (all_refs.length ())
    1041              :         {
    1042              :           /* Except for MAXREF, the rest of the arguments' offsets need not
    1043              :              reflect one added to the PHI itself.  Determine the latter from
    1044              :              MAXREF on which the result is based.  */
    1045           82 :           const offset_int orng[] =
    1046              :             {
    1047           82 :              offrng[0] - maxref.offrng[0],
    1048           82 :              wi::smax (offrng[1] - maxref.offrng[1], offrng[0]),
    1049              :             };
    1050              : 
    1051              :           /* Add the final PHI's offset to that of each of the arguments
    1052              :              and recurse to issue an inform message for it.  */
    1053          692 :           for (unsigned i = 0; i != all_refs.length (); ++i)
    1054              :             {
    1055              :               /* Skip any PHIs; those could lead to infinite recursion.  */
    1056          264 :               if (all_refs[i].phi ())
    1057           35 :                 continue;
    1058              : 
    1059          229 :               all_refs[i].add_offset (orng[0], orng[1]);
    1060          229 :               all_refs[i].inform_access (mode, ostype);
    1061              :             }
    1062           82 :           return;
    1063              :         }
    1064           82 :     }
    1065              : 
    1066              :   /* Convert offset range and avoid including a zero range since it
    1067              :      isn't necessarily meaningful.  */
    1068         3357 :   HOST_WIDE_INT diff_min = tree_to_shwi (TYPE_MIN_VALUE (ptrdiff_type_node));
    1069         3357 :   HOST_WIDE_INT diff_max = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node));
    1070         3357 :   HOST_WIDE_INT minoff;
    1071         3357 :   HOST_WIDE_INT maxoff = diff_max;
    1072         3357 :   if (wi::fits_shwi_p (aref.offrng[0]))
    1073         3357 :     minoff = aref.offrng[0].to_shwi ();
    1074              :   else
    1075            0 :     minoff = aref.offrng[0] < 0 ? diff_min : diff_max;
    1076              : 
    1077         3357 :   if (wi::fits_shwi_p (aref.offrng[1]))
    1078         3354 :     maxoff = aref.offrng[1].to_shwi ();
    1079              : 
    1080         3357 :   if (maxoff <= diff_min || maxoff >= diff_max)
    1081              :     /* Avoid mentioning an upper bound that's equal to or in excess
    1082              :        of the maximum of ptrdiff_t.  */
    1083          124 :     maxoff = minoff;
    1084              : 
    1085              :   /* Convert size range and always include it since all sizes are
    1086              :      meaningful. */
    1087         3357 :   unsigned long long minsize = 0, maxsize = 0;
    1088         3357 :   if (wi::fits_shwi_p (aref.sizrng[0])
    1089         3357 :       && wi::fits_shwi_p (aref.sizrng[1]))
    1090              :     {
    1091         3357 :       minsize = aref.sizrng[0].to_shwi ();
    1092         3357 :       maxsize = aref.sizrng[1].to_shwi ();
    1093              :     }
    1094              : 
    1095              :   /* SIZRNG doesn't necessarily have the same range as the allocation
    1096              :      size determined by gimple_call_alloc_size ().  */
    1097         3357 :   char sizestr[80];
    1098         3357 :   if (minsize == maxsize)
    1099         3102 :     sprintf (sizestr, "%llu", minsize);
    1100              :   else
    1101          255 :     sprintf (sizestr, "[%llu, %llu]", minsize, maxsize);
    1102              : 
    1103         3357 :   char offstr[80];
    1104         3357 :   if (minoff == 0
    1105         3357 :       && (maxoff == 0 || aref.sizrng[1] <= maxoff))
    1106          979 :     offstr[0] = '\0';
    1107         2378 :   else if (minoff == maxoff)
    1108         2113 :     sprintf (offstr, "%lli", (long long) minoff);
    1109              :   else
    1110          265 :     sprintf (offstr, "[%lli, %lli]", (long long) minoff, (long long) maxoff);
    1111              : 
    1112         3357 :   location_t loc = UNKNOWN_LOCATION;
    1113              : 
    1114         3357 :   tree ref = this->ref;
    1115         3357 :   tree allocfn = NULL_TREE;
    1116         3357 :   if (TREE_CODE (ref) == SSA_NAME)
    1117              :     {
    1118          772 :       gimple *stmt = SSA_NAME_DEF_STMT (ref);
    1119          772 :       if (!stmt)
    1120              :         return;
    1121              : 
    1122          772 :       if (is_gimple_call (stmt))
    1123              :         {
    1124          732 :           loc = gimple_location (stmt);
    1125          732 :           if (gimple_call_builtin_p (stmt, BUILT_IN_ALLOCA_WITH_ALIGN))
    1126              :             {
    1127              :               /* Strip the SSA_NAME suffix from the variable name and
    1128              :                  recreate an identifier with the VLA's original name.  */
    1129           23 :               ref = gimple_call_lhs (stmt);
    1130           23 :               if (SSA_NAME_IDENTIFIER (ref))
    1131              :                 {
    1132           22 :                   ref = SSA_NAME_IDENTIFIER (ref);
    1133           22 :                   const char *id = IDENTIFIER_POINTER (ref);
    1134           22 :                   size_t len = strcspn (id, ".$");
    1135           22 :                   if (!len)
    1136            0 :                     len = strlen (id);
    1137           22 :                   ref = get_identifier_with_length (id, len);
    1138              :                 }
    1139              :             }
    1140              :           else
    1141              :             {
    1142              :               /* Except for VLAs, retrieve the allocation function.  */
    1143          709 :               allocfn = gimple_call_fndecl (stmt);
    1144          709 :               if (!allocfn)
    1145            7 :                 allocfn = gimple_call_fn (stmt);
    1146          709 :               if (TREE_CODE (allocfn) == SSA_NAME)
    1147              :                 {
    1148              :                   /* For an ALLOC_CALL via a function pointer make a small
    1149              :                      effort to determine the destination of the pointer.  */
    1150            4 :                   gimple *def = SSA_NAME_DEF_STMT (allocfn);
    1151            4 :                   if (gimple_assign_single_p (def))
    1152              :                     {
    1153            3 :                       tree rhs = gimple_assign_rhs1 (def);
    1154            3 :                       if (DECL_P (rhs))
    1155              :                         allocfn = rhs;
    1156            2 :                       else if (TREE_CODE (rhs) == COMPONENT_REF)
    1157            1 :                         allocfn = TREE_OPERAND (rhs, 1);
    1158              :                     }
    1159              :                 }
    1160              :             }
    1161              :         }
    1162           40 :       else if (gimple_nop_p (stmt))
    1163              :         /* Handle DECL_PARM below.  */
    1164            5 :         ref = SSA_NAME_VAR (ref);
    1165           35 :       else if (is_gimple_assign (stmt)
    1166           35 :                && (gimple_assign_rhs_code (stmt) == MIN_EXPR
    1167           18 :                    || gimple_assign_rhs_code (stmt) == MAX_EXPR))
    1168              :         {
    1169              :           /* MIN or MAX_EXPR here implies a reference to a known object
    1170              :              and either an unknown or distinct one (the latter being
    1171              :              the result of an invalid relational expression).  Determine
    1172              :              the identity of the former and point to it in the note.
    1173              :              TODO: Consider merging with PHI handling.  */
    1174          105 :           access_ref arg_ref[2];
    1175           35 :           tree arg = gimple_assign_rhs1 (stmt);
    1176           35 :           compute_objsize (arg, /* ostype = */ 1 , &arg_ref[0]);
    1177           35 :           arg = gimple_assign_rhs2 (stmt);
    1178           35 :           compute_objsize (arg, /* ostype = */ 1 , &arg_ref[1]);
    1179              : 
    1180              :           /* Use the argument that references a known object with more
    1181              :              space remaining.  */
    1182           35 :           const bool idx
    1183           35 :             = (!arg_ref[0].ref || !arg_ref[0].base0
    1184           52 :                || (arg_ref[0].base0 && arg_ref[1].base0
    1185           11 :                    && (arg_ref[0].size_remaining ()
    1186           22 :                        < arg_ref[1].size_remaining ())));
    1187              : 
    1188           35 :           arg_ref[idx].offrng[0] = offrng[0];
    1189           35 :           arg_ref[idx].offrng[1] = offrng[1];
    1190           35 :           arg_ref[idx].inform_access (mode);
    1191           35 :           return;
    1192              :         }
    1193              :     }
    1194              : 
    1195         3322 :   if (DECL_P (ref))
    1196         2482 :     loc = DECL_SOURCE_LOCATION (ref);
    1197          840 :   else if (EXPR_P (ref) && EXPR_HAS_LOCATION (ref))
    1198            0 :     loc = EXPR_LOCATION (ref);
    1199          840 :   else if (TREE_CODE (ref) != IDENTIFIER_NODE
    1200          840 :            && TREE_CODE (ref) != SSA_NAME)
    1201              :     {
    1202          108 :       if (TREE_CODE (ref) == INTEGER_CST && ref_nullptr_p)
    1203              :         {
    1204            5 :           if (mode == access_read_write || mode == access_write_only)
    1205            1 :             inform (loc, "destination object is likely at address zero");
    1206              :           else
    1207            4 :             inform (loc, "source object is likely at address zero");
    1208              :         }
    1209              :       return;
    1210              :     }
    1211              : 
    1212         3214 :   if (mode == access_read_write || mode == access_write_only)
    1213              :     {
    1214         1625 :       if (allocfn == NULL_TREE)
    1215              :         {
    1216         1422 :           if (*offstr)
    1217         1119 :             inform (loc, "at offset %s into destination object %qE of size %s",
    1218              :                     offstr, ref, sizestr);
    1219              :           else
    1220          303 :             inform (loc, "destination object %qE of size %s", ref, sizestr);
    1221              :           return;
    1222              :         }
    1223              : 
    1224          203 :       if (*offstr)
    1225           55 :         inform (loc,
    1226              :                 "at offset %s into destination object of size %s "
    1227              :                 "allocated by %qE", offstr, sizestr, allocfn);
    1228              :       else
    1229          148 :         inform (loc, "destination object of size %s allocated by %qE",
    1230              :                 sizestr, allocfn);
    1231              :       return;
    1232              :     }
    1233              : 
    1234         1589 :   if (mode == access_read_only)
    1235              :     {
    1236          379 :       if (allocfn == NULL_TREE)
    1237              :         {
    1238          372 :           if (*offstr)
    1239          249 :             inform (loc, "at offset %s into source object %qE of size %s",
    1240              :                     offstr, ref, sizestr);
    1241              :           else
    1242          123 :             inform (loc, "source object %qE of size %s", ref, sizestr);
    1243              : 
    1244              :           return;
    1245              :         }
    1246              : 
    1247            7 :       if (*offstr)
    1248            0 :         inform (loc,
    1249              :                 "at offset %s into source object of size %s allocated by %qE",
    1250              :                 offstr, sizestr, allocfn);
    1251              :       else
    1252            7 :         inform (loc, "source object of size %s allocated by %qE",
    1253              :                 sizestr, allocfn);
    1254              :       return;
    1255              :     }
    1256              : 
    1257         1210 :   if (allocfn == NULL_TREE)
    1258              :     {
    1259          711 :       if (*offstr)
    1260          588 :         inform (loc, "at offset %s into object %qE of size %s",
    1261              :                 offstr, ref, sizestr);
    1262              :       else
    1263          123 :         inform (loc, "object %qE of size %s", ref, sizestr);
    1264              : 
    1265              :       return;
    1266              :     }
    1267              : 
    1268          499 :   if (*offstr)
    1269          252 :     inform (loc,
    1270              :             "at offset %s into object of size %s allocated by %qE",
    1271              :             offstr, sizestr, allocfn);
    1272              :   else
    1273          247 :     inform (loc, "object of size %s allocated by %qE",
    1274              :             sizestr, allocfn);
    1275              : }
    1276              : 
    1277              : /* Dump *THIS to FILE.  */
    1278              : 
    1279              : void
    1280            0 : access_ref::dump (FILE *file) const
    1281              : {
    1282            0 :   for (int i = deref; i < 0; ++i)
    1283            0 :     fputc ('&', file);
    1284              : 
    1285            0 :   for (int i = 0; i < deref; ++i)
    1286            0 :     fputc ('*', file);
    1287              : 
    1288            0 :   if (gphi *phi_stmt = phi ())
    1289              :     {
    1290            0 :       fputs ("PHI <", file);
    1291            0 :       unsigned nargs = gimple_phi_num_args (phi_stmt);
    1292            0 :       for (unsigned i = 0; i != nargs; ++i)
    1293              :         {
    1294            0 :           tree arg = gimple_phi_arg_def (phi_stmt, i);
    1295            0 :           print_generic_expr (file, arg);
    1296            0 :           if (i + 1 < nargs)
    1297            0 :             fputs (", ", file);
    1298              :         }
    1299            0 :       fputc ('>', file);
    1300              :     }
    1301              :   else
    1302            0 :     print_generic_expr (file, ref);
    1303              : 
    1304            0 :   if (offrng[0] != offrng[1])
    1305            0 :     fprintf (file, " + [%lli, %lli]",
    1306            0 :              (long long) offrng[0].to_shwi (),
    1307            0 :              (long long) offrng[1].to_shwi ());
    1308            0 :   else if (offrng[0] != 0)
    1309            0 :     fprintf (file, " %c %lli",
    1310            0 :              offrng[0] < 0 ? '-' : '+',
    1311            0 :              (long long) offrng[0].to_shwi ());
    1312              : 
    1313            0 :   if (base0)
    1314            0 :     fputs (" (base0)", file);
    1315              : 
    1316            0 :   fputs ("; size: ", file);
    1317            0 :   if (sizrng[0] != sizrng[1])
    1318              :     {
    1319            0 :       offset_int maxsize = wi::to_offset (max_object_size ());
    1320            0 :       if (sizrng[0] == 0 && sizrng[1] >= maxsize)
    1321            0 :         fputs ("unknown", file);
    1322              :       else
    1323            0 :         fprintf (file, "[%llu, %llu]",
    1324            0 :                  (unsigned long long) sizrng[0].to_uhwi (),
    1325            0 :                  (unsigned long long) sizrng[1].to_uhwi ());
    1326              :     }
    1327            0 :   else if (sizrng[0] != 0)
    1328            0 :     fprintf (file, "%llu",
    1329            0 :              (unsigned long long) sizrng[0].to_uhwi ());
    1330              : 
    1331            0 :   fputc ('\n', file);
    1332            0 : }
    1333              : 
    1334              : /* Set the access to at most MAXWRITE and MAXREAD bytes, and at least 1
    1335              :    when MINWRITE or MINREAD, respectively, is set.  */
    1336       752811 : access_data::access_data (range_query *query, gimple *stmt, access_mode mode,
    1337              :                           tree maxwrite /* = NULL_TREE */,
    1338              :                           bool minwrite /* = false */,
    1339              :                           tree maxread /* = NULL_TREE */,
    1340              :                           bool minread /* = false */)
    1341       752811 :   : stmt (stmt), call (), dst (), src (), mode (mode), ostype ()
    1342              : {
    1343       752811 :   set_bound (dst_bndrng, maxwrite, minwrite, query, stmt);
    1344       752811 :   set_bound (src_bndrng, maxread, minread, query, stmt);
    1345       752811 : }
    1346              : 
    1347              : /* Set the access to at most MAXWRITE and MAXREAD bytes, and at least 1
    1348              :    when MINWRITE or MINREAD, respectively, is set.  */
    1349          108 : access_data::access_data (range_query *query, tree expr, access_mode mode,
    1350              :                           tree maxwrite /* = NULL_TREE */,
    1351              :                           bool minwrite /* = false */,
    1352              :                           tree maxread /* = NULL_TREE */,
    1353              :                           bool minread /* = false */)
    1354          108 :   : stmt (), call (expr),  dst (), src (), mode (mode), ostype ()
    1355              : {
    1356          108 :   set_bound (dst_bndrng, maxwrite, minwrite, query, stmt);
    1357          108 :   set_bound (src_bndrng, maxread, minread, query, stmt);
    1358          108 : }
    1359              : 
    1360              : /* Set BNDRNG to the range of BOUND for the statement STMT.  */
    1361              : 
    1362              : void
    1363      1505838 : access_data::set_bound (offset_int bndrng[2], tree bound, bool minaccess,
    1364              :                         range_query *query, gimple *stmt)
    1365              : {
    1366              :   /* Set the default bounds of the access and adjust below.  */
    1367      2670765 :   bndrng[0] = minaccess ? 1 : 0;
    1368      1505838 :   bndrng[1] = HOST_WIDE_INT_M1U;
    1369              : 
    1370              :   /* When BOUND is nonnull and a range can be extracted from it,
    1371              :      set the bounds of the access to reflect both it and MINACCESS.
    1372              :      BNDRNG[0] is the size of the minimum access.  */
    1373      1505838 :   tree rng[2];
    1374      1505838 :   if (bound && get_size_range (query, bound, stmt, rng, SR_ALLOW_ZERO))
    1375              :     {
    1376        49432 :       bndrng[0] = wi::to_offset (rng[0]);
    1377        49432 :       bndrng[1] = wi::to_offset (rng[1]);
    1378        56475 :       bndrng[0] = bndrng[0] > 0 && minaccess ? 1 : 0;
    1379              :     }
    1380      1505838 : }
    1381              : 
    1382              : /* Set a bit for the PHI in VISITED and return true if it wasn't
    1383              :    already set.  */
    1384              : 
    1385              : bool
    1386       758627 : ssa_name_limit_t::visit_phi (tree ssa_name)
    1387              : {
    1388       758627 :   if (!visited)
    1389       523868 :     visited = BITMAP_ALLOC (NULL);
    1390              : 
    1391              :   /* Return false if SSA_NAME has already been visited.  */
    1392       758627 :   return bitmap_set_bit (visited, SSA_NAME_VERSION (ssa_name));
    1393              : }
    1394              : 
    1395              : /* Clear a bit for the PHI in VISITED.  */
    1396              : 
    1397              : void
    1398       559098 : ssa_name_limit_t::leave_phi (tree ssa_name)
    1399              : {
    1400              :   /* Return false if SSA_NAME has already been visited.  */
    1401       559098 :   bitmap_clear_bit (visited, SSA_NAME_VERSION (ssa_name));
    1402       559098 : }
    1403              : 
    1404              : /* Return false if the SSA_NAME chain length counter has reached
    1405              :    the limit, otherwise increment the counter and return true.  */
    1406              : 
    1407              : bool
    1408      6908660 : ssa_name_limit_t::next ()
    1409              : {
    1410              :   /* Return a negative value to let caller avoid recursing beyond
    1411              :      the specified limit.  */
    1412      6908660 :   if (ssa_def_max == 0)
    1413              :     return false;
    1414              : 
    1415      6908651 :   --ssa_def_max;
    1416      6908651 :   return true;
    1417              : }
    1418              : 
    1419              : /* If the SSA_NAME has already been "seen" return a positive value.
    1420              :    Otherwise add it to VISITED.  If the SSA_NAME limit has been
    1421              :    reached, return a negative value.  Otherwise return zero.  */
    1422              : 
    1423              : int
    1424       139712 : ssa_name_limit_t::next_phi (tree ssa_name)
    1425              : {
    1426       139712 :   {
    1427       139712 :     gimple *def_stmt = SSA_NAME_DEF_STMT (ssa_name);
    1428              :     /* Return a positive value if the PHI has already been visited.  */
    1429       139712 :     if (gimple_code (def_stmt) == GIMPLE_PHI
    1430       139712 :         && !visit_phi (ssa_name))
    1431              :       return 1;
    1432              :   }
    1433              : 
    1434              :   /* Return a negative value to let caller avoid recursing beyond
    1435              :      the specified limit.  */
    1436       100514 :   if (ssa_def_max == 0)
    1437              :     return -1;
    1438              : 
    1439       100514 :   --ssa_def_max;
    1440              : 
    1441       100514 :   return 0;
    1442              : }
    1443              : 
    1444     12624399 : ssa_name_limit_t::~ssa_name_limit_t ()
    1445              : {
    1446     12624399 :   if (visited)
    1447       523868 :     BITMAP_FREE (visited);
    1448     12624399 : }
    1449              : 
    1450              : /* Default ctor.  Initialize object with pointers to the range_query
    1451              :    instance to use or null.  */
    1452              : 
    1453     14686532 : pointer_query::pointer_query (range_query *qry /* = NULL */)
    1454     14686532 :   : rvals (qry), hits (), misses (), failures (), depth (), max_depth (),
    1455     14686532 :     var_cache ()
    1456              : {
    1457              :   /* No op.  */
    1458     14686532 : }
    1459              : 
    1460              : /* Return a pointer to the cached access_ref instance for the SSA_NAME
    1461              :    PTR if it's there or null otherwise.  */
    1462              : 
    1463              : const access_ref *
    1464      6908651 : pointer_query::get_ref (tree ptr, int ostype /* = 1 */) const
    1465              : {
    1466      6908651 :   unsigned version = SSA_NAME_VERSION (ptr);
    1467      6908651 :   unsigned idx = version << 1 | (ostype & 1);
    1468      6908651 :   if (var_cache.indices.length () <= idx)
    1469              :     {
    1470      3080892 :       ++misses;
    1471      3080892 :       return NULL;
    1472              :     }
    1473              : 
    1474      3827759 :   unsigned cache_idx = var_cache.indices[idx];
    1475      3827759 :   if (var_cache.access_refs.length () <= cache_idx)
    1476              :     {
    1477            0 :       ++misses;
    1478            0 :       return NULL;
    1479              :     }
    1480              : 
    1481      3827759 :   const access_ref &cache_ref = var_cache.access_refs[cache_idx];
    1482      3827759 :   if (cache_ref.ref)
    1483              :     {
    1484      1816024 :       ++hits;
    1485      1816024 :       return &cache_ref;
    1486              :     }
    1487              : 
    1488      2011735 :   ++misses;
    1489      2011735 :   return NULL;
    1490              : }
    1491              : 
    1492              : /* Retrieve the access_ref instance for a variable from the cache if it's
    1493              :    there or compute it and insert it into the cache if it's nonnonull.  */
    1494              : 
    1495              : bool
    1496      8785351 : pointer_query::get_ref (tree ptr, gimple *stmt, access_ref *pref,
    1497              :                         int ostype /* = 1 */)
    1498              : {
    1499      8785351 :   const unsigned version
    1500      8785351 :     = TREE_CODE (ptr) == SSA_NAME ? SSA_NAME_VERSION (ptr) : 0;
    1501              : 
    1502      2181219 :   if (version)
    1503              :     {
    1504      2181219 :       unsigned idx = version << 1 | (ostype & 1);
    1505      2181219 :       if (idx < var_cache.indices.length ())
    1506              :         {
    1507      1117013 :           unsigned cache_idx = var_cache.indices[idx] - 1;
    1508      1117013 :           if (cache_idx < var_cache.access_refs.length ()
    1509      1117013 :               && var_cache.access_refs[cache_idx].ref)
    1510              :             {
    1511            0 :               ++hits;
    1512            0 :               *pref = var_cache.access_refs[cache_idx];
    1513            0 :               return true;
    1514              :             }
    1515              :         }
    1516              : 
    1517      2181219 :       ++misses;
    1518              :     }
    1519              : 
    1520      8785351 :   if (!compute_objsize (ptr, stmt, ostype, pref, this))
    1521              :     {
    1522         9403 :       ++failures;
    1523         9403 :       return false;
    1524              :     }
    1525              : 
    1526              :   return true;
    1527              : }
    1528              : 
    1529              : /* Add a copy of the access_ref REF for the SSA_NAME to the cache if it's
    1530              :    nonnull.  */
    1531              : 
    1532              : void
    1533      3693556 : pointer_query::put_ref (tree ptr, const access_ref &ref, int ostype /* = 1 */)
    1534              : {
    1535              :   /* Only add populated/valid entries.  */
    1536      3693556 :   if (!ref.ref || ref.sizrng[0] < 0)
    1537              :     return;
    1538              : 
    1539              :   /* Add REF to the two-level cache.  */
    1540      3693556 :   unsigned version = SSA_NAME_VERSION (ptr);
    1541      3693556 :   unsigned idx = version << 1 | (ostype & 1);
    1542              : 
    1543              :   /* Grow INDICES if necessary.  An index is valid if it's nonzero.
    1544              :      Its value minus one is the index into ACCESS_REFS.  Not all
    1545              :      entries are valid.  */
    1546      3693556 :   if (var_cache.indices.length () <= idx)
    1547      1911556 :     var_cache.indices.safe_grow_cleared (idx + 1);
    1548              : 
    1549      3693556 :   if (!var_cache.indices[idx])
    1550      5687825 :     var_cache.indices[idx] = var_cache.access_refs.length () + 1;
    1551              : 
    1552              :   /* Grow ACCESS_REF cache if necessary.  An entry is valid if its
    1553              :      REF member is nonnull.  All entries except for the last two
    1554              :      are valid.  Once nonnull, the REF value must stay unchanged.  */
    1555      3693556 :   unsigned cache_idx = var_cache.indices[idx];
    1556      3693556 :   if (var_cache.access_refs.length () <= cache_idx)
    1557      3352990 :     var_cache.access_refs.safe_grow_cleared (cache_idx + 1);
    1558              : 
    1559      3693556 :   access_ref &cache_ref = var_cache.access_refs[cache_idx];
    1560      3693556 :   if (cache_ref.ref)
    1561              :   {
    1562       340566 :     gcc_checking_assert (cache_ref.ref == ref.ref);
    1563              :     return;
    1564              :   }
    1565              : 
    1566      3352990 :   cache_ref = ref;
    1567              : }
    1568              : 
    1569              : /* Flush the cache if it's nonnull.  */
    1570              : 
    1571              : void
    1572      8557762 : pointer_query::flush_cache ()
    1573              : {
    1574      8557762 :   var_cache.indices.release ();
    1575      8557762 :   var_cache.access_refs.release ();
    1576      8557762 : }
    1577              : 
    1578              : /* Dump statistics and, optionally, cache contents to DUMP_FILE.  */
    1579              : 
    1580              : void
    1581          167 : pointer_query::dump (FILE *dump_file, bool contents /* = false */)
    1582              : {
    1583          167 :   unsigned nused = 0, nrefs = 0;
    1584          167 :   unsigned nidxs = var_cache.indices.length ();
    1585          167 :   for (unsigned i = 0; i != nidxs; ++i)
    1586              :     {
    1587            0 :       unsigned ari = var_cache.indices[i];
    1588            0 :       if (!ari)
    1589            0 :         continue;
    1590              : 
    1591            0 :       ++nused;
    1592              : 
    1593            0 :       const access_ref &aref = var_cache.access_refs[ari];
    1594            0 :       if (!aref.ref)
    1595            0 :         continue;
    1596              : 
    1597            0 :       ++nrefs;
    1598              :     }
    1599              : 
    1600          167 :   fprintf (dump_file, "pointer_query counters:\n"
    1601              :            "  index cache size:   %u\n"
    1602              :            "  index entries:      %u\n"
    1603              :            "  access cache size:  %u\n"
    1604              :            "  access entries:     %u\n"
    1605              :            "  hits:               %u\n"
    1606              :            "  misses:             %u\n"
    1607              :            "  failures:           %u\n"
    1608              :            "  max_depth:          %u\n",
    1609              :            nidxs, nused,
    1610              :            var_cache.access_refs.length (), nrefs,
    1611              :            hits, misses, failures, max_depth);
    1612              : 
    1613          167 :   if (!contents || !nidxs)
    1614              :     return;
    1615              : 
    1616            0 :   fputs ("\npointer_query cache contents:\n", dump_file);
    1617              : 
    1618            0 :   for (unsigned i = 0; i != nidxs; ++i)
    1619              :     {
    1620            0 :       unsigned ari = var_cache.indices[i];
    1621            0 :       if (!ari)
    1622            0 :         continue;
    1623              : 
    1624            0 :       const access_ref &aref = var_cache.access_refs[ari];
    1625            0 :       if (!aref.ref)
    1626            0 :         continue;
    1627              : 
    1628              :       /* The level-1 cache index corresponds to the SSA_NAME_VERSION
    1629              :          shifted left by one and ORed with the Object Size Type in
    1630              :          the lowest bit.  Print the two separately.  */
    1631            0 :       unsigned ver = i >> 1;
    1632            0 :       unsigned ost = i & 1;
    1633              : 
    1634            0 :       fprintf (dump_file, "  %u.%u[%u]: ", ver, ost, ari);
    1635            0 :       if (tree name = ssa_name (ver))
    1636              :         {
    1637            0 :           print_generic_expr (dump_file, name);
    1638            0 :           fputs (" = ", dump_file);
    1639              :         }
    1640              :       else
    1641            0 :         fprintf (dump_file, "  _%u = ", ver);
    1642              : 
    1643            0 :       aref.dump (dump_file);
    1644              :     }
    1645              : 
    1646            0 :   fputc ('\n', dump_file);
    1647              : }
    1648              : 
    1649              : /* A helper of compute_objsize_r() to determine the size from an assignment
    1650              :    statement STMT with the RHS of either MIN_EXPR or MAX_EXPR.  On success
    1651              :    set PREF->REF to the operand with more or less space remaining,
    1652              :    respectively, if both refer to the same (sub)object, or to PTR if they
    1653              :    might not, and return true.  Otherwise, if the identity of neither
    1654              :    operand can be determined, return false.  */
    1655              : 
    1656              : static bool
    1657         1323 : handle_min_max_size (tree ptr, int ostype, access_ref *pref,
    1658              :                      ssa_name_limit_t &snlim, pointer_query *qry)
    1659              : {
    1660         1323 :   gimple *stmt = SSA_NAME_DEF_STMT (ptr);
    1661         1323 :   const tree_code code = gimple_assign_rhs_code (stmt);
    1662              : 
    1663              :   /* In a valid MAX_/MIN_EXPR both operands must refer to the same array.
    1664              :      Determine the size/offset of each and use the one with more or less
    1665              :      space remaining, respectively.  If either fails, use the information
    1666              :      determined from the other instead, adjusted up or down as appropriate
    1667              :      for the expression.  */
    1668         1323 :   access_ref aref[2] = { *pref, *pref };
    1669         1323 :   tree arg1 = gimple_assign_rhs1 (stmt);
    1670         1323 :   if (!compute_objsize_r (arg1, stmt, false, ostype, &aref[0], snlim, qry))
    1671              :     {
    1672            7 :       aref[0].base0 = false;
    1673            7 :       aref[0].offrng[0] = aref[0].offrng[1] = 0;
    1674            7 :       aref[0].add_max_offset ();
    1675            7 :       aref[0].set_max_size_range ();
    1676              :     }
    1677              : 
    1678         1323 :   tree arg2 = gimple_assign_rhs2 (stmt);
    1679         1323 :   if (!compute_objsize_r (arg2, stmt, false, ostype, &aref[1], snlim, qry))
    1680              :     {
    1681            2 :       aref[1].base0 = false;
    1682            2 :       aref[1].offrng[0] = aref[1].offrng[1] = 0;
    1683            2 :       aref[1].add_max_offset ();
    1684            2 :       aref[1].set_max_size_range ();
    1685              :     }
    1686              : 
    1687         1323 :   if (!aref[0].ref && !aref[1].ref)
    1688              :     /* Fail if the identity of neither argument could be determined.  */
    1689              :     return false;
    1690              : 
    1691         1323 :   bool i0 = false;
    1692         1323 :   if (aref[0].ref && aref[0].base0)
    1693              :     {
    1694          128 :       if (aref[1].ref && aref[1].base0)
    1695              :         {
    1696              :           /* If the object referenced by both arguments has been determined
    1697              :              set *PREF to the one with more or less space remainng, whichever
    1698              :              is appropriate for CODE.
    1699              :              TODO: Indicate when the objects are distinct so it can be
    1700              :              diagnosed.  */
    1701           89 :           i0 = code == MAX_EXPR;
    1702           89 :           const bool i1 = !i0;
    1703              : 
    1704           89 :           if (aref[i0].size_remaining () < aref[i1].size_remaining ())
    1705           23 :             *pref = aref[i1];
    1706              :           else
    1707           66 :             *pref = aref[i0];
    1708              : 
    1709           89 :           if (aref[i0].ref != aref[i1].ref)
    1710              :             /* If the operands don't refer to the same (sub)object set
    1711              :                PREF->REF to the SSA_NAME from which STMT was obtained
    1712              :                so that both can be identified in a diagnostic.  */
    1713           63 :             pref->ref = ptr;
    1714              : 
    1715              :           return true;
    1716              :         }
    1717              : 
    1718              :       /* If only the object referenced by one of the arguments could be
    1719              :          determined, use it and...  */
    1720           39 :       *pref = aref[0];
    1721           39 :       i0 = true;
    1722           39 :     }
    1723              :   else
    1724         1195 :     *pref = aref[1];
    1725              : 
    1726         1234 :   const bool i1 = !i0;
    1727              :   /* ...see if the offset obtained from the other pointer can be used
    1728              :      to tighten up the bound on the offset obtained from the first.  */
    1729          667 :   if ((code == MAX_EXPR && aref[i1].offrng[1] < aref[i0].offrng[0])
    1730         1883 :       || (code == MIN_EXPR && aref[i0].offrng[0] < aref[i1].offrng[1]))
    1731              :     {
    1732          127 :       pref->offrng[0] = aref[i0].offrng[0];
    1733          127 :       pref->offrng[1] = aref[i0].offrng[1];
    1734              :     }
    1735              : 
    1736              :   /* Replace PTR->REF with the SSA_NAME to indicate the expression
    1737              :      might not refer to the same (sub)object.  */
    1738         1234 :   pref->ref = ptr;
    1739         1234 :   return true;
    1740              : }
    1741              : 
    1742              : /* A helper of compute_objsize_r() to determine the size of a DECL.
    1743              :    Return true on success and (possibly in the future) false on failure.  */
    1744              : 
    1745              : static bool
    1746      5079486 : handle_decl (tree decl, bool addr, access_ref *pref)
    1747              : {
    1748      5079486 :   tree decl_type = TREE_TYPE (decl);
    1749              : 
    1750      5079486 :   pref->ref = decl;
    1751              : 
    1752              :   /* Reset the offset in case it was set by a prior call and not
    1753              :      cleared by the caller.  The offset is only adjusted after
    1754              :      the identity of the object has been determined.  */
    1755      5079486 :   pref->offrng[0] = pref->offrng[1] = 0;
    1756              : 
    1757      5079486 :   if (!addr && POINTER_TYPE_P (decl_type))
    1758              :     {
    1759              :       /* Set the maximum size if the reference is to the pointer
    1760              :          itself (as opposed to what it points to), and clear
    1761              :          BASE0 since the offset isn't necessarily zero-based.  */
    1762        46833 :       pref->set_max_size_range ();
    1763        46833 :       pref->base0 = false;
    1764        46833 :       return true;
    1765              :     }
    1766              : 
    1767              :   /* Valid offsets into the object are nonnegative.  */
    1768      5032653 :   pref->base0 = true;
    1769              : 
    1770      5032653 :   if (tree size = decl_init_size (decl, false))
    1771      5007451 :     if (TREE_CODE (size) == INTEGER_CST)
    1772              :       {
    1773      5007317 :         pref->sizrng[0] = wi::to_offset (size);
    1774      5007317 :         pref->sizrng[1] = pref->sizrng[0];
    1775      5007317 :         return true;
    1776              :       }
    1777              : 
    1778        25336 :   pref->set_max_size_range ();
    1779        25336 :   return true;
    1780              : }
    1781              : 
    1782              : /* A helper of compute_objsize_r() to determine the size from ARRAY_REF
    1783              :    AREF.  ADDR is true if PTR is the operand of ADDR_EXPR.  Return true
    1784              :    on success and false on failure.  */
    1785              : 
    1786              : static bool
    1787       880962 : handle_array_ref (tree aref, gimple *stmt, bool addr, int ostype,
    1788              :                   access_ref *pref, ssa_name_limit_t &snlim,
    1789              :                   pointer_query *qry)
    1790              : {
    1791       880962 :   gcc_assert (TREE_CODE (aref) == ARRAY_REF);
    1792              : 
    1793       880962 :   tree arefop = TREE_OPERAND (aref, 0);
    1794       880962 :   tree reftype = TREE_TYPE (arefop);
    1795       880962 :   if (!addr && TREE_CODE (TREE_TYPE (reftype)) == POINTER_TYPE)
    1796              :     /* Avoid arrays of pointers.  FIXME: Handle pointers to arrays
    1797              :        of known bound.  */
    1798              :     return false;
    1799              : 
    1800       871553 :   if (!compute_objsize_r (arefop, stmt, addr, ostype, pref, snlim, qry))
    1801              :     return false;
    1802              : 
    1803       871553 :   offset_int orng[2];
    1804       871553 :   tree off = pref->eval (TREE_OPERAND (aref, 1));
    1805       871553 :   range_query *const rvals = qry ? qry->rvals : NULL;
    1806       871553 :   if (!get_offset_range (off, stmt, orng, rvals))
    1807              :     {
    1808              :       /* Set ORNG to the maximum offset representable in ptrdiff_t.  */
    1809        45910 :       orng[1] = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node));
    1810        45910 :       orng[0] = -orng[1] - 1;
    1811              :     }
    1812              : 
    1813              :   /* Convert the array index range determined above to a byte offset.  */
    1814       871553 :   tree lowbnd = array_ref_low_bound (aref);
    1815       871553 :   if (TREE_CODE (lowbnd) == INTEGER_CST && !integer_zerop (lowbnd))
    1816              :     {
    1817              :       /* Adjust the index by the low bound of the array domain (0 in C/C++,
    1818              :          1 in Fortran and anything in Ada) by applying the same processing
    1819              :          as in get_offset_range.  */
    1820        17143 :       const wide_int wlb = wi::to_wide (lowbnd);
    1821        17143 :       signop sgn = SIGNED;
    1822        17143 :       if (TYPE_UNSIGNED (TREE_TYPE (lowbnd))
    1823        17143 :           && wlb.get_precision () < TYPE_PRECISION (sizetype))
    1824              :         sgn = UNSIGNED;
    1825        17143 :       const offset_int lb = offset_int::from (wlb, sgn);
    1826        17143 :       orng[0] -= lb;
    1827        17143 :       orng[1] -= lb;
    1828        17143 :     }
    1829              : 
    1830       871553 :   tree eltype = TREE_TYPE (aref);
    1831       871553 :   tree tpsize = TYPE_SIZE_UNIT (eltype);
    1832       871553 :   if (!tpsize || TREE_CODE (tpsize) != INTEGER_CST)
    1833              :     {
    1834          511 :       pref->add_max_offset ();
    1835          511 :       return true;
    1836              :     }
    1837              : 
    1838       871042 :   offset_int sz = wi::to_offset (tpsize);
    1839       871042 :   orng[0] *= sz;
    1840       871042 :   orng[1] *= sz;
    1841              : 
    1842       871042 :   if (ostype && TREE_CODE (eltype) == ARRAY_TYPE)
    1843              :     {
    1844              :       /* Except for the permissive raw memory functions which use
    1845              :          the size of the whole object determined above, use the size
    1846              :          of the referenced array.  Because the overall offset is from
    1847              :          the beginning of the complete array object add this overall
    1848              :          offset to the size of array.  */
    1849         7164 :       offset_int sizrng[2] =
    1850              :         {
    1851         7164 :          pref->offrng[0] + orng[0] + sz,
    1852         7164 :          pref->offrng[1] + orng[1] + sz
    1853              :         };
    1854         7164 :       if (sizrng[1] < sizrng[0])
    1855            2 :         std::swap (sizrng[0], sizrng[1]);
    1856         7164 :       if (sizrng[0] >= 0 && sizrng[0] <= pref->sizrng[0])
    1857         6625 :         pref->sizrng[0] = sizrng[0];
    1858         7164 :       if (sizrng[1] >= 0 && sizrng[1] <= pref->sizrng[1])
    1859         6767 :         pref->sizrng[1] = sizrng[1];
    1860              :     }
    1861              : 
    1862       871042 :   pref->add_offset (orng[0], orng[1]);
    1863       871042 :   return true;
    1864              : }
    1865              : 
    1866              : /* Given a COMPONENT_REF CREF, set *PREF size to the size of the referenced
    1867              :    member.  */
    1868              : 
    1869              : static void
    1870        56294 : set_component_ref_size (tree cref, access_ref *pref)
    1871              : {
    1872        56294 :   const tree base = TREE_OPERAND (cref, 0);
    1873        56294 :   const tree base_type = TREE_TYPE (base);
    1874              : 
    1875              :   /* SAM is set for array members that might need special treatment.  */
    1876        56294 :   special_array_member sam;
    1877        56294 :   tree size = component_ref_size (cref, &sam);
    1878        56294 :   if (sam == special_array_member::int_0)
    1879          191 :     pref->sizrng[0] = pref->sizrng[1] = 0;
    1880        56103 :   else if (!pref->trail1special && sam == special_array_member::trail_1)
    1881           27 :     pref->sizrng[0] = pref->sizrng[1] = 1;
    1882        56076 :   else if (size && TREE_CODE (size) == INTEGER_CST)
    1883        53828 :     pref->sizrng[0] = pref->sizrng[1] = wi::to_offset (size);
    1884              :   else
    1885              :     {
    1886              :       /* When the size of the member is unknown it's either a flexible
    1887              :          array member or a trailing special array member (either zero
    1888              :          length or one-element).  Set the size to the maximum minus
    1889              :          the constant size of the base object's type.  */
    1890         2248 :       pref->sizrng[0] = 0;
    1891         2248 :       pref->sizrng[1] = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node));
    1892         2248 :       if (tree base_size = TYPE_SIZE_UNIT (base_type))
    1893         2248 :         if (TREE_CODE (base_size) == INTEGER_CST)
    1894         2207 :           pref->sizrng[1] -= wi::to_offset (base_size);
    1895              :     }
    1896        56294 : }
    1897              : 
    1898              : /* A helper of compute_objsize_r() to determine the size from COMPONENT_REF
    1899              :    CREF.  Return true on success and false on failure.  */
    1900              : 
    1901              : static bool
    1902      3312895 : handle_component_ref (tree cref, gimple *stmt, bool addr, int ostype,
    1903              :                       access_ref *pref, ssa_name_limit_t &snlim,
    1904              :                       pointer_query *qry)
    1905              : {
    1906      3312895 :   gcc_assert (TREE_CODE (cref) == COMPONENT_REF);
    1907              : 
    1908      3312895 :   const tree base = TREE_OPERAND (cref, 0);
    1909      3312895 :   const tree field = TREE_OPERAND (cref, 1);
    1910      3312895 :   access_ref base_ref = *pref;
    1911              : 
    1912              :   /* Unconditionally determine the size of the base object (it could
    1913              :      be smaller than the referenced member when the object is stored
    1914              :      in a buffer with an insufficient size).  */
    1915      3312895 :   if (!compute_objsize_r (base, stmt, addr, 0, &base_ref, snlim, qry))
    1916              :     return false;
    1917              : 
    1918              :   /* Add the offset of the member to the offset into the object computed
    1919              :      so far.  */
    1920      3312895 :   tree offset = byte_position (field);
    1921      3312895 :   if (TREE_CODE (offset) == INTEGER_CST)
    1922      3312868 :     base_ref.add_offset (wi::to_offset (offset));
    1923              :   else
    1924           27 :     base_ref.add_max_offset ();
    1925              : 
    1926      3312895 :   if (!base_ref.ref)
    1927              :     /* PREF->REF may have been already set to an SSA_NAME earlier
    1928              :        to provide better context for diagnostics.  In that case,
    1929              :        leave it unchanged.  */
    1930            0 :     base_ref.ref = base;
    1931              : 
    1932      3312895 :   const tree base_type = TREE_TYPE (base);
    1933      3312895 :   if (TREE_CODE (base_type) == UNION_TYPE)
    1934              :     /* In accesses through union types consider the entire unions
    1935              :        rather than just their members.  */
    1936              :     ostype = 0;
    1937              : 
    1938      2905409 :   if (ostype == 0)
    1939              :     {
    1940              :       /* In OSTYPE zero (for raw memory functions like memcpy), use
    1941              :          the maximum size instead if the identity of the enclosing
    1942              :          object cannot be determined.  */
    1943      3256590 :       *pref = base_ref;
    1944      3256590 :       return true;
    1945              :     }
    1946              : 
    1947        56305 :   pref->ref = field;
    1948              : 
    1949        56305 :   if (!addr && POINTER_TYPE_P (TREE_TYPE (field)))
    1950              :     {
    1951              :       /* Set maximum size if the reference is to the pointer member
    1952              :          itself (as opposed to what it points to).  */
    1953           11 :       pref->set_max_size_range ();
    1954           11 :       return true;
    1955              :     }
    1956              : 
    1957        56294 :   set_component_ref_size (cref, pref);
    1958              : 
    1959        56294 :   if (base_ref.size_remaining () < pref->size_remaining ())
    1960              :     /* Use the base object if it's smaller than the member.  */
    1961          443 :     *pref = base_ref;
    1962              : 
    1963              :   return true;
    1964              : }
    1965              : 
    1966              : /* A helper of compute_objsize_r() to determine the size from MEM_REF
    1967              :    MREF.  Return true on success and false on failure.  */
    1968              : 
    1969              : static bool
    1970      3053505 : handle_mem_ref (tree mref, gimple *stmt, int ostype, access_ref *pref,
    1971              :                 ssa_name_limit_t &snlim, pointer_query *qry)
    1972              : {
    1973      3053505 :   gcc_assert (TREE_CODE (mref) == MEM_REF);
    1974              : 
    1975      3053505 :   tree mreftype = TYPE_MAIN_VARIANT (TREE_TYPE (mref));
    1976      3053505 :   if (VECTOR_TYPE_P (mreftype))
    1977              :       {
    1978              :       /* Hack: Handle MEM_REFs of vector types as those to complete
    1979              :          objects; those may be synthesized from multiple assignments
    1980              :          to consecutive data members (see PR 93200 and 96963).
    1981              :          FIXME: Vectorized assignments should only be present after
    1982              :          vectorization so this hack is only necessary after it has
    1983              :          run and could be avoided in calls from prior passes (e.g.,
    1984              :          tree-ssa-strlen.cc).
    1985              :          FIXME: Deal with this more generally, e.g., by marking up
    1986              :          such MEM_REFs at the time they're created.  */
    1987        68041 :       ostype = 0;
    1988              :     }
    1989              : 
    1990      3053505 :   tree mrefop = TREE_OPERAND (mref, 0);
    1991      3053505 :   if (!compute_objsize_r (mrefop, stmt, false, ostype, pref, snlim, qry))
    1992              :     return false;
    1993              : 
    1994      3053499 :   ++pref->deref;
    1995              : 
    1996      3053499 :   offset_int orng[2];
    1997      3053499 :   tree off = pref->eval (TREE_OPERAND (mref, 1));
    1998      3053499 :   range_query *const rvals = qry ? qry->rvals : NULL;
    1999      3053499 :   if (!get_offset_range (off, stmt, orng, rvals))
    2000              :     {
    2001              :       /* Set ORNG to the maximum offset representable in ptrdiff_t.  */
    2002            0 :       orng[1] = wi::to_offset (TYPE_MAX_VALUE (ptrdiff_type_node));
    2003            0 :       orng[0] = -orng[1] - 1;
    2004              :     }
    2005              : 
    2006      3053499 :   pref->add_offset (orng[0], orng[1]);
    2007      3053499 :   return true;
    2008              : }
    2009              : 
    2010              : /* A helper of compute_objsize_r() to determine the size from SSA_NAME
    2011              :    PTR.  Return true on success and false on failure.  */
    2012              : 
    2013              : static bool
    2014      6908660 : handle_ssa_name (tree ptr, bool addr, int ostype,
    2015              :                  access_ref *pref, ssa_name_limit_t &snlim,
    2016              :                  pointer_query *qry)
    2017              : {
    2018      6908660 :   if (!snlim.next ())
    2019              :     return false;
    2020              : 
    2021              :   /* Only process an SSA_NAME if the recursion limit has not yet
    2022              :      been reached.  */
    2023      6908651 :   if (qry)
    2024              :     {
    2025      6908651 :       if (++qry->depth > qry->max_depth)
    2026       712793 :         qry->max_depth = qry->depth;
    2027      6908651 :       if (const access_ref *cache_ref = qry->get_ref (ptr, ostype))
    2028              :         {
    2029              :           /* Add the number of DEREFerences accumulated so far.  */
    2030      1816024 :           const int deref = pref->deref;
    2031      1816024 :           *pref = *cache_ref;
    2032      1816024 :           pref->deref += deref;
    2033      1816024 :           return true;
    2034              :         }
    2035              :     }
    2036              : 
    2037      5092627 :   gimple *stmt = SSA_NAME_DEF_STMT (ptr);
    2038      5092627 :   if (is_gimple_call (stmt))
    2039              :     {
    2040              :       /* If STMT is a call to an allocation function get the size
    2041              :          from its argument(s).  If successful, also set *PREF->REF
    2042              :          to PTR for the caller to include in diagnostics.  */
    2043      2478835 :       wide_int wr[2];
    2044       495767 :       range_query *const rvals = qry ? qry->rvals : NULL;
    2045       495767 :       if (gimple_call_alloc_size (stmt, wr, rvals))
    2046              :         {
    2047       150824 :           pref->ref = ptr;
    2048       150824 :           pref->sizrng[0] = offset_int::from (wr[0], UNSIGNED);
    2049       150824 :           pref->sizrng[1] = offset_int::from (wr[1], UNSIGNED);
    2050              :           /* Constrain both bounds to a valid size.  */
    2051       150824 :           offset_int maxsize = wi::to_offset (max_object_size ());
    2052       150824 :           if (pref->sizrng[0] > maxsize)
    2053          352 :             pref->sizrng[0] = maxsize;
    2054       150824 :           if (pref->sizrng[1] > maxsize)
    2055        14361 :             pref->sizrng[1] = maxsize;
    2056              :         }
    2057              :       else
    2058              :         {
    2059              :           /* For functions known to return one of their pointer arguments
    2060              :              try to determine what the returned pointer points to, and on
    2061              :              success add OFFRNG which was set to the offset added by
    2062              :              the function (e.g., memchr) to the overall offset.  */
    2063       344943 :           bool past_end;
    2064       344943 :           offset_int offrng[2];
    2065       344943 :           if (tree ret = gimple_call_return_array (stmt, offrng, &past_end,
    2066              :                                                    snlim, qry))
    2067              :             {
    2068        19432 :               if (!compute_objsize_r (ret, stmt, addr, ostype, pref, snlim, qry))
    2069         1815 :                 return false;
    2070              : 
    2071              :               /* Cap OFFRNG[1] to at most the remaining size of
    2072              :                  the object.  */
    2073        17617 :               offset_int remrng[2];
    2074        17617 :               remrng[1] = pref->size_remaining (remrng);
    2075        17617 :               if (remrng[1] != 0 && !past_end)
    2076              :                 /* Decrement the size for functions that never return
    2077              :                    a past-the-end pointer.  */
    2078        17316 :                 remrng[1] -= 1;
    2079              : 
    2080        17617 :               if (remrng[1] < offrng[1])
    2081          408 :                 offrng[1] = remrng[1];
    2082        17617 :               pref->add_offset (offrng[0], offrng[1]);
    2083              :             }
    2084              :           else
    2085              :             {
    2086              :               /* For other calls that might return arbitrary pointers
    2087              :                  including into the middle of objects set the size
    2088              :                  range to maximum, clear PREF->BASE0, and also set
    2089              :                  PREF->REF to include in diagnostics.  */
    2090       325511 :               pref->set_max_size_range ();
    2091       325511 :               pref->base0 = false;
    2092       325511 :               pref->ref = ptr;
    2093              :             }
    2094              :         }
    2095       493952 :       qry->put_ref (ptr, *pref, ostype);
    2096       493952 :       return true;
    2097      1487301 :     }
    2098              : 
    2099      4596860 :   if (gimple_nop_p (stmt))
    2100              :     {
    2101              :       /* For a function argument try to determine the byte size
    2102              :          of the array from the current function declaratation
    2103              :          (e.g., attribute access or related).  */
    2104      4183130 :       wide_int wr[2];
    2105       836626 :       bool static_array = false;
    2106       836626 :       if (tree ref = gimple_parm_array_size (ptr, wr, &static_array))
    2107              :         {
    2108          185 :           pref->parmarray = !static_array;
    2109          185 :           pref->sizrng[0] = offset_int::from (wr[0], UNSIGNED);
    2110          185 :           pref->sizrng[1] = offset_int::from (wr[1], UNSIGNED);
    2111          185 :           pref->ref = ref;
    2112          185 :           qry->put_ref (ptr, *pref, ostype);
    2113          185 :           return true;
    2114              :         }
    2115              : 
    2116       836441 :       pref->set_max_size_range ();
    2117       836441 :       pref->base0 = false;
    2118       836441 :       pref->ref = ptr;
    2119       836441 :       qry->put_ref (ptr, *pref, ostype);
    2120       836441 :       return true;
    2121      2509878 :     }
    2122              : 
    2123      3760234 :   if (gimple_code (stmt) == GIMPLE_PHI)
    2124              :     {
    2125              :       /* Pass PTR to get_ref() via PREF.  If all PHI arguments refer
    2126              :          to the same object the function will replace it with it.  */
    2127       618798 :       pref->ref = ptr;
    2128       618798 :       access_ref phi_ref = *pref;
    2129       618798 :       if (!pref->get_ref (NULL, &phi_ref, ostype, &snlim, qry))
    2130              :         return false;
    2131       558981 :       *pref = phi_ref;
    2132       558981 :       qry->put_ref (ptr, *pref, ostype);
    2133       558981 :       return true;
    2134              :     }
    2135              : 
    2136      3141436 :   if (!is_gimple_assign (stmt))
    2137              :     {
    2138              :       /* Clear BASE0 since the assigned pointer might point into
    2139              :          the middle of the object, set the maximum size range and,
    2140              :          if the SSA_NAME refers to a function argumnent, set
    2141              :          PREF->REF to it.  */
    2142         7799 :       pref->base0 = false;
    2143         7799 :       pref->set_max_size_range ();
    2144         7799 :       pref->ref = ptr;
    2145         7799 :       return true;
    2146              :     }
    2147              : 
    2148      3133637 :   tree_code code = gimple_assign_rhs_code (stmt);
    2149              : 
    2150      3133637 :   if (code == MAX_EXPR || code == MIN_EXPR)
    2151              :     {
    2152         1323 :       if (!handle_min_max_size (ptr, ostype, pref, snlim, qry))
    2153              :         return false;
    2154              : 
    2155         1323 :       qry->put_ref (ptr, *pref, ostype);
    2156         1323 :       return true;
    2157              :     }
    2158              : 
    2159      3132314 :   tree rhs = gimple_assign_rhs1 (stmt);
    2160              : 
    2161      3132314 :   if (code == POINTER_PLUS_EXPR
    2162      3132314 :       && TREE_CODE (TREE_TYPE (rhs)) == POINTER_TYPE)
    2163              :     {
    2164              :       /* Compute the size of the object first. */
    2165       806987 :       if (!compute_objsize_r (rhs, stmt, addr, ostype, pref, snlim, qry))
    2166              :         return false;
    2167              : 
    2168       761064 :       offset_int orng[2];
    2169       761064 :       tree off = gimple_assign_rhs2 (stmt);
    2170       761064 :       range_query *const rvals = qry ? qry->rvals : NULL;
    2171       761064 :       if (get_offset_range (off, stmt, orng, rvals))
    2172       643219 :         pref->add_offset (orng[0], orng[1]);
    2173              :       else
    2174       117845 :         pref->add_max_offset ();
    2175              : 
    2176       761064 :       qry->put_ref (ptr, *pref, ostype);
    2177       761064 :       return true;
    2178              :     }
    2179              : 
    2180      2325327 :   if (code == ADDR_EXPR || code == SSA_NAME)
    2181              :     {
    2182       508289 :       if (!compute_objsize_r (rhs, stmt, addr, ostype, pref, snlim, qry))
    2183              :         return false;
    2184       506952 :       qry->put_ref (ptr, *pref, ostype);
    2185       506952 :       return true;
    2186              :     }
    2187              : 
    2188      1817038 :   if (ostype > 1 && POINTER_TYPE_P (TREE_TYPE (rhs)))
    2189              :     {
    2190              :       /* When determining the qualifiers follow the pointer but
    2191              :          avoid caching the result.  As the pointer is added to
    2192              :          and/or dereferenced the computed size and offset need
    2193              :          not be meaningful for other queries involving the same
    2194              :          pointer.  */
    2195            0 :       if (!compute_objsize_r (rhs, stmt, addr, ostype, pref, snlim, qry))
    2196              :         return false;
    2197              : 
    2198            0 :       rhs = pref->ref;
    2199              :     }
    2200              : 
    2201              :   /* (This could also be an assignment from a nonlocal pointer.)  Save
    2202              :      PTR to mention in diagnostics but otherwise treat it as a pointer
    2203              :      to an unknown object.  */
    2204      1817038 :   pref->ref = rhs;
    2205      1817038 :   pref->base0 = false;
    2206      1817038 :   pref->set_max_size_range ();
    2207      1817038 :   return true;
    2208              : }
    2209              : 
    2210              : /* Helper to compute the size of the object referenced by the PTR
    2211              :    expression which must have pointer type, using Object Size type
    2212              :    OSTYPE (only the least significant 2 bits are used).
    2213              :    On success, sets PREF->REF to the DECL of the referenced object
    2214              :    if it's unique, otherwise to null, PREF->OFFRNG to the range of
    2215              :    offsets into it, and PREF->SIZRNG to the range of sizes of
    2216              :    the object(s).
    2217              :    ADDR is true for an enclosing ADDR_EXPR.
    2218              :    SNLIM is used to avoid visiting the same PHI operand multiple
    2219              :    times, and, when nonnull, RVALS to determine range information.
    2220              :    Returns true on success, false when a meaningful size (or range)
    2221              :    cannot be determined.
    2222              : 
    2223              :    The function is intended for diagnostics and should not be used
    2224              :    to influence code generation or optimization.  */
    2225              : 
    2226              : static bool
    2227     22024939 : compute_objsize_r (tree ptr, gimple *stmt, bool addr, int ostype,
    2228              :                    access_ref *pref, ssa_name_limit_t &snlim,
    2229              :                    pointer_query *qry)
    2230              : {
    2231     22025669 :   STRIP_NOPS (ptr);
    2232              : 
    2233     22025669 :   if (DECL_P (ptr))
    2234      5079486 :     return handle_decl (ptr, addr, pref);
    2235              : 
    2236     16946183 :   switch (TREE_CODE (ptr))
    2237              :     {
    2238      1793153 :     case ADDR_EXPR:
    2239      1793153 :       {
    2240      1793153 :         tree ref = TREE_OPERAND (ptr, 0);
    2241      1793153 :         if (!compute_objsize_r (ref, stmt, true, ostype, pref, snlim, qry))
    2242              :           return false;
    2243              : 
    2244      1793153 :         --pref->deref;
    2245      1793153 :         return true;
    2246              :       }
    2247              : 
    2248         4026 :     case BIT_FIELD_REF:
    2249         4026 :       {
    2250         4026 :         tree ref = TREE_OPERAND (ptr, 0);
    2251         4026 :         if (!compute_objsize_r (ref, stmt, addr, ostype, pref, snlim, qry))
    2252              :           return false;
    2253              : 
    2254         4026 :         offset_int off = wi::to_offset (pref->eval (TREE_OPERAND (ptr, 2)));
    2255         4026 :         pref->add_offset (off / BITS_PER_UNIT);
    2256         4026 :         return true;
    2257              :       }
    2258              : 
    2259       880962 :     case ARRAY_REF:
    2260       880962 :       return handle_array_ref (ptr, stmt, addr, ostype, pref, snlim, qry);
    2261              : 
    2262      3312895 :     case COMPONENT_REF:
    2263      3312895 :       return handle_component_ref (ptr, stmt, addr, ostype, pref, snlim, qry);
    2264              : 
    2265      3053505 :     case MEM_REF:
    2266      3053505 :       return handle_mem_ref (ptr, stmt, ostype, pref, snlim, qry);
    2267              : 
    2268        11022 :     case TARGET_MEM_REF:
    2269        11022 :       {
    2270        11022 :         tree ref = TREE_OPERAND (ptr, 0);
    2271        11022 :         if (!compute_objsize_r (ref, stmt, addr, ostype, pref, snlim, qry))
    2272              :           return false;
    2273              : 
    2274              :         /* TODO: Handle remaining operands.  Until then, add maximum offset.  */
    2275        11022 :         pref->ref = ptr;
    2276        11022 :         pref->add_max_offset ();
    2277        11022 :         return true;
    2278              :       }
    2279              : 
    2280       633551 :     case INTEGER_CST:
    2281              :       /* Pointer constants other than null smaller than param_min_pagesize
    2282              :          might be the result of erroneous null pointer addition/subtraction.
    2283              :          Unless zero is a valid address set size to zero.  For null pointers,
    2284              :          set size to the maximum for now since those may be the result of
    2285              :          jump threading.  Similarly, for values >= param_min_pagesize in
    2286              :          order to support (type *) 0x7cdeab00.  */
    2287       633551 :       if (integer_zerop (ptr)
    2288       680949 :           || wi::to_widest (ptr) >= param_min_pagesize)
    2289       589778 :         pref->set_max_size_range ();
    2290        43773 :       else if (POINTER_TYPE_P (TREE_TYPE (ptr)))
    2291              :         {
    2292          585 :           tree deref_type = TREE_TYPE (TREE_TYPE (ptr));
    2293          585 :           addr_space_t as = TYPE_ADDR_SPACE (deref_type);
    2294          585 :           if (targetm.addr_space.zero_address_valid (as))
    2295            0 :             pref->set_max_size_range ();
    2296              :           else
    2297              :             {
    2298          585 :               pref->sizrng[0] = pref->sizrng[1] = 0;
    2299          585 :               pref->ref_nullptr_p = true;
    2300              :             }
    2301              :         }
    2302              :       else
    2303        43188 :         pref->sizrng[0] = pref->sizrng[1] = 0;
    2304              : 
    2305       633551 :       pref->ref = ptr;
    2306       633551 :       return true;
    2307              : 
    2308       258672 :     case STRING_CST:
    2309       258672 :       pref->sizrng[0] = pref->sizrng[1] = TREE_STRING_LENGTH (ptr);
    2310       258672 :       pref->ref = ptr;
    2311       258672 :       return true;
    2312              : 
    2313          519 :     case POINTER_PLUS_EXPR:
    2314          519 :     {
    2315          519 :       tree ref = TREE_OPERAND (ptr, 0);
    2316          519 :       if (!compute_objsize_r (ref, stmt, addr, ostype, pref, snlim, qry))
    2317              :         return false;
    2318              : 
    2319              :       /* The below only makes sense if the offset is being applied to the
    2320              :          address of the object.  */
    2321          519 :       if (pref->deref != -1)
    2322              :         return false;
    2323              : 
    2324          441 :       offset_int orng[2];
    2325          441 :       tree off = pref->eval (TREE_OPERAND (ptr, 1));
    2326          441 :       if (get_offset_range (off, stmt, orng, qry->rvals))
    2327          432 :         pref->add_offset (orng[0], orng[1]);
    2328              :       else
    2329            9 :         pref->add_max_offset ();
    2330              :       return true;
    2331              :     }
    2332              : 
    2333          730 :     case VIEW_CONVERT_EXPR:
    2334          730 :       ptr = TREE_OPERAND (ptr, 0);
    2335          730 :       return compute_objsize_r (ptr, stmt, addr, ostype, pref, snlim, qry);
    2336              : 
    2337      6908660 :     case SSA_NAME:
    2338      6908660 :       return handle_ssa_name (ptr, addr, ostype, pref, snlim, qry);
    2339              : 
    2340        88488 :     default:
    2341        88488 :       break;
    2342              :     }
    2343              : 
    2344              :   /* Assume all other expressions point into an unknown object
    2345              :      of the maximum valid size.  */
    2346        88488 :   pref->ref = ptr;
    2347        88488 :   pref->base0 = false;
    2348        88488 :   pref->set_max_size_range ();
    2349        88488 :   if (TREE_CODE (ptr) == SSA_NAME)
    2350            0 :     qry->put_ref (ptr, *pref);
    2351              :   return true;
    2352              : }
    2353              : 
    2354              : /* A "public" wrapper around the above.  Clients should use this overload
    2355              :    instead.  */
    2356              : 
    2357              : tree
    2358     10939514 : compute_objsize (tree ptr, gimple *stmt, int ostype, access_ref *pref,
    2359              :                  pointer_query *ptr_qry)
    2360              : {
    2361     10939514 :   pointer_query qry;
    2362     10939514 :   if (ptr_qry)
    2363     10938400 :     ptr_qry->depth = 0;
    2364              :   else
    2365              :     ptr_qry = &qry;
    2366              : 
    2367              :   /* Clear and invalidate in case *PREF is being reused.  */
    2368     10939514 :   pref->offrng[0] = pref->offrng[1] = 0;
    2369     10939514 :   pref->sizrng[0] = pref->sizrng[1] = -1;
    2370              : 
    2371     10939514 :   ssa_name_limit_t snlim;
    2372     10939514 :   if (!compute_objsize_r (ptr, stmt, false, ostype, pref, snlim, ptr_qry))
    2373              :     return NULL_TREE;
    2374              : 
    2375     10930018 :   offset_int maxsize = pref->size_remaining ();
    2376     10930018 :   if (pref->base0 && pref->offrng[0] < 0 && pref->offrng[1] >= 0)
    2377          109 :     pref->offrng[0] = 0;
    2378     10930018 :   return wide_int_to_tree (sizetype, maxsize);
    2379     10939514 : }
    2380              : 
    2381              : /* Transitional wrapper.  The function should be removed once callers
    2382              :    transition to the pointer_query API.  */
    2383              : 
    2384              : tree
    2385       658940 : compute_objsize (tree ptr, gimple *stmt, int ostype, access_ref *pref,
    2386              :                  range_query *rvals /* = NULL */)
    2387              : {
    2388       658940 :   pointer_query qry;
    2389       658940 :   qry.rvals = rvals;
    2390       658940 :   return compute_objsize (ptr, stmt, ostype, pref, &qry);
    2391       658940 : }
    2392              : 
    2393              : /* Legacy wrapper around the above.  The function should be removed
    2394              :    once callers transition to one of the two above.  */
    2395              : 
    2396              : tree
    2397            0 : compute_objsize (tree ptr, gimple *stmt, int ostype, tree *pdecl /* = NULL */,
    2398              :                  tree *poff /* = NULL */, range_query *rvals /* = NULL */)
    2399              : {
    2400              :   /* Set the initial offsets to zero and size to negative to indicate
    2401              :      none has been computed yet.  */
    2402            0 :   access_ref ref;
    2403            0 :   tree size = compute_objsize (ptr, stmt, ostype, &ref, rvals);
    2404            0 :   if (!size || !ref.base0)
    2405              :     return NULL_TREE;
    2406              : 
    2407            0 :   if (pdecl)
    2408            0 :     *pdecl = ref.ref;
    2409              : 
    2410            0 :   if (poff)
    2411            0 :     *poff = wide_int_to_tree (ptrdiff_type_node, ref.offrng[ref.offrng[0] < 0]);
    2412              : 
    2413              :   return size;
    2414              : }
    2415              : 
    2416              : /* Determine the offset *FLDOFF of the first byte of a struct member
    2417              :    of TYPE (possibly recursively) into which the byte offset OFF points,
    2418              :    starting after the field START_AFTER if it's non-null.  On success,
    2419              :    if nonnull, set *FLDOFF to the offset of the first byte, and return
    2420              :    the field decl.  If nonnull, set *NEXTOFF to the offset of the next
    2421              :    field (which reflects any padding between the returned field and
    2422              :    the next).  Otherwise, if no such member can be found, return null.  */
    2423              : 
    2424              : tree
    2425         1540 : field_at_offset (tree type, tree start_after, HOST_WIDE_INT off,
    2426              :                  HOST_WIDE_INT *fldoff /* = nullptr */,
    2427              :                  HOST_WIDE_INT *nextoff /* = nullptr */)
    2428              : {
    2429         1540 :   tree first_fld = TYPE_FIELDS (type);
    2430              : 
    2431         1540 :   HOST_WIDE_INT offbuf = 0, nextbuf = 0;
    2432         1540 :   if (!fldoff)
    2433            9 :     fldoff = &offbuf;
    2434         1540 :   if (!nextoff)
    2435          692 :     nextoff = &nextbuf;
    2436              : 
    2437         1540 :   *nextoff = 0;
    2438              : 
    2439              :   /* The field to return.  */
    2440         1540 :   tree last_fld = NULL_TREE;
    2441              :   /* The next field to advance to.  */
    2442         1540 :   tree next_fld = NULL_TREE;
    2443              : 
    2444              :   /* NEXT_FLD's cached offset.  */
    2445         1540 :   HOST_WIDE_INT next_pos = -1;
    2446              : 
    2447         1800 :   for (tree fld = first_fld; fld; fld = next_fld)
    2448              :     {
    2449              :       next_fld = fld;
    2450         1781 :       do
    2451              :         /* Advance to the next relevant data member.  */
    2452         1781 :         next_fld = TREE_CHAIN (next_fld);
    2453              :       while (next_fld
    2454         3442 :              && (TREE_CODE (next_fld) != FIELD_DECL
    2455         1661 :                  || DECL_ARTIFICIAL (next_fld)));
    2456              : 
    2457         1781 :       if (TREE_CODE (fld) != FIELD_DECL || DECL_ARTIFICIAL (fld))
    2458            0 :         continue;
    2459              : 
    2460         1781 :       if (fld == start_after)
    2461            0 :         continue;
    2462              : 
    2463         1781 :       tree fldtype = TREE_TYPE (fld);
    2464              :       /* The offset of FLD within its immediately enclosing structure.  */
    2465         1781 :       HOST_WIDE_INT fldpos = next_pos < 0 ? int_byte_position (fld) : next_pos;
    2466              : 
    2467         1781 :       tree typesize = TYPE_SIZE_UNIT (fldtype);
    2468         1781 :       if (typesize && TREE_CODE (typesize) != INTEGER_CST)
    2469              :         /* Bail if FLD is a variable length member.  */
    2470              :         return NULL_TREE;
    2471              : 
    2472              :       /* If the size is not available the field is a flexible array
    2473              :          member.  Treat this case as success.  */
    2474         3552 :       HOST_WIDE_INT fldsize = (tree_fits_uhwi_p (typesize)
    2475         1781 :                                ? tree_to_uhwi (typesize)
    2476              :                                : off);
    2477              : 
    2478              :       /* If OFF is beyond the end of the current field continue.  */
    2479         1781 :       HOST_WIDE_INT fldend = fldpos + fldsize;
    2480         1781 :       if (fldend < off)
    2481          236 :         continue;
    2482              : 
    2483         1545 :       if (next_fld)
    2484              :         {
    2485              :           /* If OFF is equal to the offset of the next field continue
    2486              :              to it and skip the array/struct business below.  */
    2487         1439 :           tree pos = byte_position (next_fld);
    2488         1439 :           if (!tree_fits_shwi_p (pos))
    2489              :             /* Bail if NEXT_FLD is a variable length member.  */
    2490              :             return NULL_TREE;
    2491         1439 :           next_pos = tree_to_shwi (pos);
    2492         1439 :           *nextoff = *fldoff + next_pos;
    2493         1439 :           if (*nextoff == off && TREE_CODE (type) != UNION_TYPE)
    2494           19 :             continue;
    2495              :         }
    2496              :       else
    2497          106 :         *nextoff = HOST_WIDE_INT_MAX;
    2498              : 
    2499              :       /* OFF refers somewhere into the current field or just past its end,
    2500              :          which could mean it refers to the next field.  */
    2501         1526 :       if (TREE_CODE (fldtype) == ARRAY_TYPE)
    2502              :         {
    2503              :           /* Will be set to the offset of the first byte of the array
    2504              :              element (which may be an array) of FLDTYPE into which
    2505              :              OFF - FLDPOS points (which may be past ELTOFF).  */
    2506          549 :           HOST_WIDE_INT eltoff = 0;
    2507          549 :           if (tree ft = array_elt_at_offset (fldtype, off - fldpos, &eltoff))
    2508          549 :             fldtype = ft;
    2509              :           else
    2510            0 :             continue;
    2511              : 
    2512              :           /* Advance the position to include the array element above.
    2513              :              If OFF - FLPOS refers to a member of FLDTYPE, the member
    2514              :              will be determined below.  */
    2515          549 :           fldpos += eltoff;
    2516              :         }
    2517              : 
    2518         1526 :       *fldoff += fldpos;
    2519              : 
    2520         1526 :       if (TREE_CODE (fldtype) == RECORD_TYPE)
    2521              :         /* Drill down into the current field if it's a struct.  */
    2522          848 :         fld = field_at_offset (fldtype, start_after, off - fldpos,
    2523              :                                fldoff, nextoff);
    2524              : 
    2525         1526 :       last_fld = fld;
    2526              : 
    2527              :       /* Unless the offset is just past the end of the field return it.
    2528              :          Otherwise save it and return it only if the offset of the next
    2529              :          next field is greater (i.e., there is padding between the two)
    2530              :          or if there is no next field.  */
    2531         1526 :       if (off < fldend)
    2532              :         break;
    2533              :     }
    2534              : 
    2535         1540 :   if (*nextoff == HOST_WIDE_INT_MAX && next_fld)
    2536           35 :     *nextoff = next_pos;
    2537              : 
    2538              :   return last_fld;
    2539              : }
    2540              : 
    2541              : /* Determine the offset *ELTOFF of the first byte of the array element
    2542              :    of array ARTYPE into which the byte offset OFF points.  On success
    2543              :    set *ELTOFF to the offset of the first byte and return type.
    2544              :    Otherwise, if no such element can be found, return null.  */
    2545              : 
    2546              : tree
    2547          581 : array_elt_at_offset (tree artype, HOST_WIDE_INT off,
    2548              :                      HOST_WIDE_INT *eltoff /* = nullptr */,
    2549              :                      HOST_WIDE_INT *subar_size /* = nullptr */)
    2550              : {
    2551          581 :   gcc_assert (TREE_CODE (artype) == ARRAY_TYPE);
    2552              : 
    2553          581 :   HOST_WIDE_INT dummy;
    2554          581 :   if (!eltoff)
    2555            0 :     eltoff = &dummy;
    2556          581 :   if (!subar_size)
    2557          549 :     subar_size = &dummy;
    2558              : 
    2559          581 :   tree eltype = artype;
    2560          613 :   while (TREE_CODE (TREE_TYPE (eltype)) == ARRAY_TYPE)
    2561           32 :     eltype = TREE_TYPE (eltype);
    2562              : 
    2563          581 :   tree subartype = eltype;
    2564          581 :   if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (eltype))
    2565          565 :       || TYPE_MODE (TREE_TYPE (eltype)) != TYPE_MODE (char_type_node))
    2566           16 :     eltype = TREE_TYPE (eltype);
    2567              : 
    2568          581 :   *subar_size = int_size_in_bytes (subartype);
    2569              : 
    2570          581 :   if (eltype == artype)
    2571              :     {
    2572          533 :       *eltoff = 0;
    2573          533 :       return artype;
    2574              :     }
    2575              : 
    2576           48 :   HOST_WIDE_INT artype_size = int_size_in_bytes (artype);
    2577           48 :   HOST_WIDE_INT eltype_size = int_size_in_bytes (eltype);
    2578              : 
    2579           48 :   if (off < artype_size)// * eltype_size)
    2580              :     {
    2581           32 :       *eltoff = (off / eltype_size) * eltype_size;
    2582           32 :       return TREE_CODE (eltype) == ARRAY_TYPE ? TREE_TYPE (eltype) : eltype;
    2583              :     }
    2584              : 
    2585              :   return NULL_TREE;
    2586              : }
    2587              : 
    2588              : /* Wrapper around build_array_type_nelts that makes sure the array
    2589              :    can be created at all and handles zero sized arrays specially.  */
    2590              : 
    2591              : tree
    2592        12084 : build_printable_array_type (tree eltype, unsigned HOST_WIDE_INT nelts)
    2593              : {
    2594              :   /* Cannot build an array type of functions or methods without
    2595              :      an error diagnostic.  */
    2596        12084 :   if (FUNC_OR_METHOD_TYPE_P (eltype))
    2597              :     {
    2598            1 :       tree arrtype = make_node (ARRAY_TYPE);
    2599            1 :       TREE_TYPE (arrtype) = eltype;
    2600            1 :       TYPE_SIZE (arrtype) = bitsize_zero_node;
    2601            1 :       TYPE_SIZE_UNIT (arrtype) = size_zero_node;
    2602            1 :       return arrtype;
    2603              :     }
    2604              : 
    2605        12083 :   if (TYPE_SIZE_UNIT (eltype)
    2606        11809 :       && TREE_CODE (TYPE_SIZE_UNIT (eltype)) == INTEGER_CST
    2607        11793 :       && !integer_zerop (TYPE_SIZE_UNIT (eltype))
    2608        11703 :       && TYPE_ALIGN_UNIT (eltype) > 1
    2609        27573 :       && wi::zext (wi::to_wide (TYPE_SIZE_UNIT (eltype)),
    2610        27573 :                    ffs_hwi (TYPE_ALIGN_UNIT (eltype)) - 1) != 0)
    2611            3 :     eltype = TYPE_MAIN_VARIANT (eltype);
    2612              : 
    2613              :   /* Consider excessive NELTS an array of unknown bound.  */
    2614        12083 :   tree idxtype = NULL_TREE;
    2615        12083 :   if (nelts < HOST_WIDE_INT_MAX)
    2616              :     {
    2617        12050 :       if (nelts)
    2618        11750 :         return build_array_type_nelts (eltype, nelts);
    2619          300 :       idxtype = build_range_type (sizetype, size_zero_node, NULL_TREE);
    2620              :     }
    2621              : 
    2622          333 :   tree arrtype = build_array_type (eltype, idxtype);
    2623          333 :   arrtype = build_distinct_type_copy (TYPE_MAIN_VARIANT (arrtype));
    2624          333 :   TYPE_SIZE (arrtype) = bitsize_zero_node;
    2625          333 :   TYPE_SIZE_UNIT (arrtype) = size_zero_node;
    2626          333 :   return arrtype;
    2627              : }
        

Generated by: LCOV version 2.4-beta

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