LCOV - code coverage report
Current view: top level - gcc - gimple-ssa-warn-access.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.2 % 1952 1839
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 90 90
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Pass to detect and issue warnings for invalid accesses, including
       2              :    invalid or mismatched allocation/deallocation calls.
       3              : 
       4              :    Copyright (C) 2020-2026 Free Software Foundation, Inc.
       5              :    Contributed by Martin Sebor <msebor@redhat.com>.
       6              : 
       7              :    This file is part of GCC.
       8              : 
       9              :    GCC is free software; you can redistribute it and/or modify it under
      10              :    the terms of the GNU General Public License as published by the Free
      11              :    Software Foundation; either version 3, or (at your option) any later
      12              :    version.
      13              : 
      14              :    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      15              :    WARRANTY; without even the implied warranty of MERCHANTABILITY or
      16              :    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      17              :    for more details.
      18              : 
      19              :    You should have received a copy of the GNU General Public License
      20              :    along with GCC; see the file COPYING3.  If not see
      21              :    <http://www.gnu.org/licenses/>.  */
      22              : 
      23              : #define INCLUDE_STRING
      24              : #include "config.h"
      25              : #include "system.h"
      26              : #include "coretypes.h"
      27              : #include "backend.h"
      28              : #include "tree.h"
      29              : #include "gimple.h"
      30              : #include "tree-pass.h"
      31              : #include "builtins.h"
      32              : #include "diagnostic.h"
      33              : #include "ssa.h"
      34              : #include "gimple-pretty-print.h"
      35              : #include "gimple-ssa-warn-access.h"
      36              : #include "gimple-ssa-warn-restrict.h"
      37              : #include "diagnostic-core.h"
      38              : #include "fold-const.h"
      39              : #include "gimple-iterator.h"
      40              : #include "gimple-fold.h"
      41              : #include "langhooks.h"
      42              : #include "memmodel.h"
      43              : #include "target.h"
      44              : #include "tree-dfa.h"
      45              : #include "tree-ssa.h"
      46              : #include "tree-cfg.h"
      47              : #include "tree-object-size.h"
      48              : #include "tree-ssa-strlen.h"
      49              : #include "calls.h"
      50              : #include "cfganal.h"
      51              : #include "intl.h"
      52              : #include "gimple-range.h"
      53              : #include "stringpool.h"
      54              : #include "attribs.h"
      55              : #include "demangle.h"
      56              : #include "attr-fnspec.h"
      57              : #include "pointer-query.h"
      58              : #include "pretty-print-markup.h"
      59              : #include "gcc-urlifier.h"
      60              : #include "diagnostic-context-rich-location.h"
      61              : 
      62              : /* Return true if tree node X has an associated location.  */
      63              : 
      64              : static inline location_t
      65          117 : has_location (const_tree x)
      66              : {
      67          117 :   if (DECL_P (x))
      68           92 :     return DECL_SOURCE_LOCATION (x) != UNKNOWN_LOCATION;
      69              : 
      70           25 :   if (EXPR_P (x))
      71            0 :     return EXPR_HAS_LOCATION (x);
      72              : 
      73              :   return false;
      74              : }
      75              : 
      76              : /* Return the associated location of STMT.  */
      77              : 
      78              : static inline location_t
      79      2044106 : get_location (const gimple *stmt)
      80              : {
      81      1864723 :   return gimple_location (stmt);
      82              : }
      83              : 
      84              : /* Return the associated location of tree node X.  */
      85              : 
      86              : static inline location_t
      87         2047 : get_location (tree x)
      88              : {
      89         2047 :   if (DECL_P (x))
      90          981 :     return DECL_SOURCE_LOCATION (x);
      91              : 
      92         1066 :   if (EXPR_P (x))
      93         1066 :     return EXPR_LOCATION (x);
      94              : 
      95              :   return UNKNOWN_LOCATION;
      96              : }
      97              : 
      98              : /* Overload of the nascent tree function for GIMPLE STMT.  */
      99              : 
     100              : static inline tree
     101      1066692 : get_callee_fndecl (const gimple *stmt)
     102              : {
     103          623 :   return gimple_call_fndecl (stmt);
     104              : }
     105              : 
     106              : static inline unsigned
     107     27708782 : call_nargs (const gimple *stmt)
     108              : {
     109      2180319 :   return gimple_call_num_args (stmt);
     110              : }
     111              : 
     112              : static inline unsigned
     113          356 : call_nargs (const_tree expr)
     114              : {
     115          356 :   return call_expr_nargs (expr);
     116              : }
     117              : 
     118              : 
     119              : static inline tree
     120     10007957 : call_arg (const gimple *stmt, unsigned argno)
     121              : {
     122      1365552 :   return gimple_call_arg (stmt, argno);
     123              : }
     124              : 
     125              : static inline tree
     126          302 : call_arg (tree expr, unsigned argno)
     127              : {
     128          302 :   return CALL_EXPR_ARG (expr, argno);
     129              : }
     130              : 
     131              : /* For a call EXPR at LOC to a function FNAME that expects a string
     132              :    in the argument ARG, issue a diagnostic due to it being a called
     133              :    with an argument that is a character array with no terminating
     134              :    NUL.  SIZE is the EXACT size of the array, and BNDRNG the number
     135              :    of characters in which the NUL is expected.  Either EXPR or FNAME
     136              :    may be null but noth both.  SIZE may be null when BNDRNG is null.  */
     137              : 
     138              : template <class GimpleOrTree>
     139              : static void
     140         8080 : warn_string_no_nul (location_t loc, GimpleOrTree expr, const char *fname,
     141              :                     tree arg, tree decl, tree size, bool exact,
     142              :                     const wide_int bndrng[2] /* = NULL */)
     143              : {
     144         8080 :   const opt_code opt = OPT_Wstringop_overread;
     145         1390 :   if ((expr && warning_suppressed_p (expr, opt))
     146         8884 :       || warning_suppressed_p (arg, opt))
     147         1139 :     return;
     148              : 
     149         6941 :   loc = expansion_point_location_if_in_system_header (loc);
     150              :   bool warned;
     151              : 
     152              :   /* Format the bound range as a string to keep the number of messages
     153              :      from exploding.  */
     154              :   char bndstr[80];
     155         6941 :   *bndstr = 0;
     156         6941 :   if (bndrng)
     157              :     {
     158          144 :       if (bndrng[0] == bndrng[1])
     159          132 :         sprintf (bndstr, "%llu", (unsigned long long) bndrng[0].to_uhwi ());
     160              :       else
     161           12 :         sprintf (bndstr, "[%llu, %llu]",
     162           12 :                  (unsigned long long) bndrng[0].to_uhwi (),
     163           12 :                  (unsigned long long) bndrng[1].to_uhwi ());
     164              :     }
     165              : 
     166         6941 :   auto_diagnostic_group d;
     167              : 
     168         6941 :   const tree maxobjsize = max_object_size ();
     169         6941 :   const wide_int maxsiz = wi::to_wide (maxobjsize);
     170         6941 :   if (expr)
     171              :     {
     172          765 :       tree func = get_callee_fndecl (expr);
     173          765 :       rich_location_with_details richloc (loc, expr);
     174              : 
     175          765 :       if (bndrng)
     176              :         {
     177          144 :           if (wi::ltu_p (maxsiz, bndrng[0]))
     178            0 :             warned = warning_at (&richloc, opt,
     179              :                                  "%qD specified bound %s exceeds "
     180              :                                  "maximum object size %E",
     181              :                                  func, bndstr, maxobjsize);
     182              :           else
     183              :             {
     184          144 :               bool maybe = wi::to_wide (size) == bndrng[0];
     185          191 :               warned = warning_at (&richloc, opt,
     186              :                                    exact
     187              :                                    ? G_("%qD specified bound %s exceeds "
     188              :                                         "the size %E of unterminated array")
     189              :                                    : (maybe
     190           47 :                                       ? G_("%qD specified bound %s may "
     191              :                                            "exceed the size of at most %E "
     192              :                                            "of unterminated array")
     193              :                                       : G_("%qD specified bound %s exceeds "
     194              :                                            "the size of at most %E "
     195              :                                            "of unterminated array")),
     196              :                                    func, bndstr, size);
     197              :             }
     198              :         }
     199              :       else
     200          621 :         warned = warning_at (&richloc, opt,
     201              :                              "%qD argument missing terminating nul",
     202              :                              func);
     203          765 :     }
     204              :   else
     205              :     {
     206         6176 :       if (bndrng)
     207              :         {
     208            0 :           if (wi::ltu_p (maxsiz, bndrng[0]))
     209            0 :             warned = warning_at (loc, opt,
     210              :                                  "%qs specified bound %s exceeds "
     211              :                                  "maximum object size %E",
     212              :                                  fname, bndstr, maxobjsize);
     213              :           else
     214              :             {
     215            0 :               bool maybe = wi::to_wide (size) == bndrng[0];
     216            0 :               warned = warning_at (loc, opt,
     217              :                                    exact
     218              :                                    ? G_("%qs specified bound %s exceeds "
     219              :                                         "the size %E of unterminated array")
     220              :                                    : (maybe
     221            0 :                                       ? G_("%qs specified bound %s may "
     222              :                                            "exceed the size of at most %E "
     223              :                                            "of unterminated array")
     224              :                                       : G_("%qs specified bound %s exceeds "
     225              :                                            "the size of at most %E "
     226              :                                            "of unterminated array")),
     227              :                                    fname, bndstr, size);
     228              :             }
     229              :         }
     230              :       else
     231         6176 :         warned = warning_at (loc, opt,
     232              :                              "%qs argument missing terminating nul",
     233              :                              fname);
     234              :     }
     235              : 
     236         6941 :   if (warned)
     237              :     {
     238          521 :       inform (get_location (decl),
     239              :               "referenced argument declared here");
     240          521 :       suppress_warning (arg, opt);
     241          521 :       if (expr)
     242          441 :         suppress_warning (expr, opt);
     243              :     }
     244         6941 : }
     245              : 
     246              : void
     247          819 : warn_string_no_nul (location_t loc, gimple *stmt, const char *fname,
     248              :                     tree arg, tree decl, tree size /* = NULL_TREE */,
     249              :                     bool exact /* = false */,
     250              :                     const wide_int bndrng[2] /* = NULL */)
     251              : {
     252          819 :   return warn_string_no_nul<gimple *> (loc, stmt, fname,
     253          819 :                                        arg, decl, size, exact, bndrng);
     254              : }
     255              : 
     256              : void
     257         7232 : warn_string_no_nul (location_t loc, tree expr, const char *fname,
     258              :                     tree arg, tree decl, tree size /* = NULL_TREE */,
     259              :                     bool exact /* = false */,
     260              :                     const wide_int bndrng[2] /* = NULL */)
     261              : {
     262         7232 :   return warn_string_no_nul<tree> (loc, expr, fname,
     263         7232 :                                    arg, decl, size, exact, bndrng);
     264              : }
     265              : 
     266              : /* If EXP refers to an unterminated constant character array return
     267              :    the declaration of the object of which the array is a member or
     268              :    element and if SIZE is not null, set *SIZE to the size of
     269              :    the unterminated array and set *EXACT if the size is exact or
     270              :    clear it otherwise.  Otherwise return null.  */
     271              : 
     272              : tree
     273       623614 : unterminated_array (tree exp, tree *size /* = NULL */, bool *exact /* = NULL */)
     274              : {
     275              :   /* C_STRLEN will return NULL and set DECL in the info
     276              :      structure if EXP references a unterminated array.  */
     277       623614 :   c_strlen_data lendata = { };
     278       623614 :   tree len = c_strlen (exp, 1, &lendata);
     279       623614 :   if (len || !lendata.minlen || !lendata.decl)
     280              :     return NULL_TREE;
     281              : 
     282         1765 :   if (!size)
     283              :     return lendata.decl;
     284              : 
     285         1765 :   len = lendata.minlen;
     286         1765 :   if (lendata.off)
     287              :     {
     288              :       /* Constant offsets are already accounted for in LENDATA.MINLEN,
     289              :          but not in a SSA_NAME + CST expression.  */
     290         1765 :       if (TREE_CODE (lendata.off) == INTEGER_CST)
     291         1386 :         *exact = true;
     292          379 :       else if (TREE_CODE (lendata.off) == PLUS_EXPR
     293          379 :                && TREE_CODE (TREE_OPERAND (lendata.off, 1)) == INTEGER_CST)
     294              :         {
     295              :           /* Subtract the offset from the size of the array.  */
     296          113 :           *exact = false;
     297          113 :           tree temp = TREE_OPERAND (lendata.off, 1);
     298          113 :           temp = fold_convert (ssizetype, temp);
     299          113 :           len = fold_build2 (MINUS_EXPR, ssizetype, len, temp);
     300              :         }
     301              :       else
     302          266 :         *exact = false;
     303              :     }
     304              :   else
     305            0 :     *exact = true;
     306              : 
     307         1765 :   *size = len;
     308         1765 :   return lendata.decl;
     309              : }
     310              : 
     311              : /* For a call EXPR (which may be null) that expects a string argument
     312              :    SRC as an argument, returns false if SRC is a character array with
     313              :    no terminating NUL.  When nonnull, BOUND is the number of characters
     314              :    in which to expect the terminating NUL.  When EXPR is nonnull also
     315              :    issues a warning.  */
     316              : 
     317              : template <class GimpleOrTree>
     318              : static bool
     319       617377 : check_nul_terminated_array (GimpleOrTree expr, tree src, tree bound)
     320              : {
     321              :   /* The constant size of the array SRC points to.  The actual size
     322              :      may be less of EXACT is true, but not more.  */
     323              :   tree size;
     324              :   /* True if SRC involves a non-constant offset into the array.  */
     325              :   bool exact;
     326              :   /* The unterminated constant array SRC points to.  */
     327       617377 :   tree nonstr = unterminated_array (src, &size, &exact);
     328       617377 :   if (!nonstr)
     329              :     return true;
     330              : 
     331              :   /* NONSTR refers to the non-nul terminated constant array and SIZE
     332              :      is the constant size of the array in bytes.  EXACT is true when
     333              :      SIZE is exact.  */
     334              : 
     335         4990 :   wide_int bndrng[2];
     336          998 :   if (bound)
     337              :     {
     338          357 :       int_range_max r (TREE_TYPE (bound));
     339              : 
     340          714 :       get_range_query (cfun)->range_of_expr (r, bound);
     341              : 
     342          357 :       if (r.undefined_p () || r.varying_p ())
     343              :         return true;
     344              : 
     345          356 :       bndrng[0] = r.lower_bound ();
     346          356 :       bndrng[1] = r.upper_bound ();
     347              : 
     348          356 :       if (exact)
     349              :         {
     350          206 :           if (wi::leu_p (bndrng[0], wi::to_wide (size)))
     351              :             return true;
     352              :         }
     353          150 :       else if (wi::lt_p (bndrng[0], wi::to_wide (size), UNSIGNED))
     354              :         return true;
     355          357 :     }
     356              : 
     357          788 :   if (expr)
     358         1059 :     warn_string_no_nul (get_location (expr), expr, NULL, src, nonstr,
     359              :                         size, exact, bound ? bndrng : NULL);
     360              : 
     361              :   return false;
     362         2994 : }
     363              : 
     364              : bool
     365       322191 : check_nul_terminated_array (gimple *stmt, tree src, tree bound /* = NULL_TREE */)
     366              : {
     367       322191 :   return check_nul_terminated_array<gimple *>(stmt, src, bound);
     368              : }
     369              : 
     370              : bool
     371       282752 : check_nul_terminated_array (tree expr, tree src, tree bound /* = NULL_TREE */)
     372              : {
     373       282752 :   return check_nul_terminated_array<tree>(expr, src, bound);
     374              : }
     375              : 
     376              : /* Warn about passing a non-string array/pointer to a built-in function
     377              :    that expects a nul-terminated string argument.  Returns true if
     378              :    a warning has been issued.*/
     379              : 
     380              : template <class GimpleOrTree>
     381              : static bool
     382      7214333 : maybe_warn_nonstring_arg (tree fndecl, GimpleOrTree exp)
     383              : {
     384      7214333 :   if (!fndecl || !fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
     385              :     return false;
     386              : 
     387      2192442 :   if (!warn_stringop_overread
     388      2192442 :       || warning_suppressed_p (exp, OPT_Wstringop_overread))
     389        11767 :     return false;
     390              : 
     391              :   /* Avoid clearly invalid calls (more checking done below).  */
     392      2180675 :   unsigned nargs = call_nargs (exp);
     393      2180675 :   if (!nargs)
     394              :     return false;
     395              : 
     396              :   /* The bound argument to a bounded string function like strncpy.  */
     397      1864369 :   tree bound = NULL_TREE;
     398              : 
     399              :   /* The longest known or possible string argument to one of the comparison
     400              :      functions.  If the length is less than the bound it is used instead.
     401              :      Since the length is only used for warning and not for code generation
     402              :      disable strict mode in the calls to get_range_strlen below.  */
     403      1864369 :   tree maxlen = NULL_TREE;
     404              : 
     405              :   /* It's safe to call "bounded" string functions with a non-string
     406              :      argument since the functions provide an explicit bound for this
     407              :      purpose.  The exception is strncat where the bound may refer to
     408              :      either the destination or the source.  */
     409      1864369 :   int fncode = DECL_FUNCTION_CODE (fndecl);
     410      1864369 :   switch (fncode)
     411              :     {
     412              :     case BUILT_IN_STRCMP:
     413              :     case BUILT_IN_STRNCMP:
     414              :     case BUILT_IN_STRNCASECMP:
     415              :       {
     416              :         /* For these, if one argument refers to one or more of a set
     417              :            of string constants or arrays of known size, determine
     418              :            the range of their known or possible lengths and use it
     419              :            conservatively as the bound for the unbounded function,
     420              :            and to adjust the range of the bound of the bounded ones.  */
     421       392400 :         for (unsigned argno = 0;
     422       783878 :              argno < MIN (nargs, 2)
     423       783878 :                && !(maxlen && TREE_CODE (maxlen) == INTEGER_CST); argno++)
     424              :           {
     425       392400 :             tree arg = call_arg (exp, argno);
     426       392400 :             if (!get_attr_nonstring_decl (arg))
     427              :               {
     428       391460 :                 c_strlen_data lendata = { };
     429              :                 /* Set MAXBOUND to an arbitrary non-null non-integer
     430              :                    node as a request to have it set to the length of
     431              :                    the longest string in a PHI.  */
     432       391460 :                 lendata.maxbound = arg;
     433       391460 :                 get_range_strlen (arg, &lendata, /* eltsize = */ 1);
     434       391460 :                 maxlen = lendata.maxbound;
     435              :               }
     436              :           }
     437              :       }
     438              :       /* Fall through.  */
     439              : 
     440              :     case BUILT_IN_STRNCAT:
     441              :     case BUILT_IN_STPNCPY:
     442              :     case BUILT_IN_STRNCPY:
     443       397469 :       if (nargs > 2)
     444        11366 :         bound = call_arg (exp, 2);
     445              :       break;
     446              : 
     447          722 :     case BUILT_IN_STRNDUP:
     448          722 :       if (nargs < 2)
     449              :         return false;
     450          722 :       bound = call_arg (exp, 1);
     451          722 :       break;
     452              : 
     453         1471 :     case BUILT_IN_STRNLEN:
     454              :       {
     455         1471 :         tree arg = call_arg (exp, 0);
     456         1471 :         if (!get_attr_nonstring_decl (arg))
     457              :           {
     458         1333 :             c_strlen_data lendata = { };
     459              :             /* Set MAXBOUND to an arbitrary non-null non-integer
     460              :                node as a request to have it set to the length of
     461              :                the longest string in a PHI.  */
     462         1333 :             lendata.maxbound = arg;
     463         1333 :             get_range_strlen (arg, &lendata, /* eltsize = */ 1);
     464         1333 :             maxlen = lendata.maxbound;
     465              :           }
     466         1471 :         if (nargs > 1)
     467         1470 :           bound = call_arg (exp, 1);
     468              :         break;
     469              :       }
     470              : 
     471              :     default:
     472              :       break;
     473              :     }
     474              : 
     475              :   /* Determine the range of the bound argument (if specified).  */
     476      1864369 :   tree bndrng[2] = { NULL_TREE, NULL_TREE };
     477      1864369 :   if (bound)
     478              :     {
     479        13558 :       STRIP_NOPS (bound);
     480        13558 :       get_size_range (bound, bndrng);
     481              :     }
     482              : 
     483      1864369 :   location_t loc = get_location (exp);
     484              : 
     485      1864369 :   if (bndrng[0])
     486              :     {
     487              :       /* Diagnose excessive bound prior to the adjustment below and
     488              :          regardless of attribute nonstring.  */
     489        13538 :       tree maxobjsize = max_object_size ();
     490        13538 :       if (tree_int_cst_lt (maxobjsize, bndrng[0]))
     491              :         {
     492          131 :           rich_location_with_details richloc (loc, exp);
     493              : 
     494          131 :           bool warned = false;
     495          131 :           if (tree_int_cst_equal (bndrng[0], bndrng[1]))
     496          114 :             warned = warning_at (&richloc, OPT_Wstringop_overread,
     497              :                                  "%qD specified bound %E "
     498              :                                  "exceeds maximum object size %E",
     499              :                                  fndecl, bndrng[0], maxobjsize);
     500              :           else
     501           17 :             warned = warning_at (&richloc, OPT_Wstringop_overread,
     502              :                                  "%qD specified bound [%E, %E] "
     503              :                                  "exceeds maximum object size %E",
     504              :                                  fndecl, bndrng[0], bndrng[1],
     505              :                                  maxobjsize);
     506          131 :           if (warned)
     507           45 :             suppress_warning (exp, OPT_Wstringop_overread);
     508              : 
     509              :           return warned;
     510          131 :         }
     511              :     }
     512              : 
     513      1864238 :   if (maxlen && !integer_all_onesp (maxlen))
     514              :     {
     515              :       /* Add one for the nul.  */
     516         6954 :       maxlen = const_binop (PLUS_EXPR, TREE_TYPE (maxlen), maxlen,
     517              :                             size_one_node);
     518              : 
     519         6954 :       if (!bndrng[0])
     520              :         {
     521              :           /* Conservatively use the upper bound of the lengths for
     522              :              both the lower and the upper bound of the operation.  */
     523         4592 :           bndrng[0] = maxlen;
     524         4592 :           bndrng[1] = maxlen;
     525         4592 :           bound = void_type_node;
     526              :         }
     527         2362 :       else if (maxlen)
     528              :         {
     529              :           /* Replace the bound on the operation with the upper bound
     530              :              of the length of the string if the latter is smaller.  */
     531         2353 :           if (tree_int_cst_lt (maxlen, bndrng[0]))
     532          200 :             bndrng[0] = maxlen;
     533         2153 :           else if (tree_int_cst_lt (maxlen, bndrng[1]))
     534          527 :             bndrng[1] = maxlen;
     535              :         }
     536              :     }
     537              : 
     538      1864238 :   bool any_arg_warned = false;
     539              :   /* Iterate over the built-in function's formal arguments and check
     540              :      each const char* against the actual argument.  If the actual
     541              :      argument is declared attribute non-string issue a warning unless
     542              :      the argument's maximum length is bounded.  */
     543              :   function_args_iterator it;
     544      1864238 :   function_args_iter_init (&it, TREE_TYPE (fndecl));
     545              : 
     546      5906878 :   for (unsigned argno = 0; ; ++argno, function_args_iter_next (&it))
     547              :     {
     548              :       /* Avoid iterating past the declared argument in a call
     549              :          to function declared without a prototype.  */
     550      5903924 :       if (argno >= nargs)
     551              :         break;
     552              : 
     553      4198712 :       tree argtype = function_args_iter_cond (&it);
     554      4198712 :       if (!argtype)
     555              :         break;
     556              : 
     557      4039686 :       if (!POINTER_TYPE_P (argtype))
     558      4036732 :         continue;
     559              : 
     560      2477915 :       argtype = TREE_TYPE (argtype);
     561              : 
     562      3971488 :       if (TREE_CODE (argtype) != INTEGER_TYPE
     563      2477915 :           || !TYPE_READONLY (argtype))
     564      1493573 :         continue;
     565              : 
     566       984342 :       argtype = TYPE_MAIN_VARIANT (argtype);
     567       984342 :       if (argtype != char_type_node)
     568        11376 :         continue;
     569              : 
     570       972966 :       tree callarg = call_arg (exp, argno);
     571       972966 :       if (TREE_CODE (callarg) == ADDR_EXPR)
     572       537906 :         callarg = TREE_OPERAND (callarg, 0);
     573              : 
     574              :       /* See if the destination is declared with attribute "nonstring".  */
     575       972966 :       tree decl = get_attr_nonstring_decl (callarg);
     576       972966 :       if (!decl)
     577       970012 :         continue;
     578              : 
     579              :       /* The maximum number of array elements accessed.  */
     580         2954 :       offset_int wibnd = 0;
     581              : 
     582         2954 :       if (argno && fncode == BUILT_IN_STRNCAT)
     583              :         {
     584              :           /* See if the bound in strncat is derived from the length
     585              :              of the strlen of the destination (as it's expected to be).
     586              :              If so, reset BOUND and FNCODE to trigger a warning.  */
     587          488 :           tree dstarg = call_arg (exp, 0);
     588          488 :           if (is_strlen_related_p (dstarg, bound))
     589              :             {
     590              :               /* The bound applies to the destination, not to the source,
     591              :                  so reset these to trigger a warning without mentioning
     592              :                  the bound.  */
     593              :               bound = NULL;
     594              :               fncode = 0;
     595              :             }
     596          480 :           else if (bndrng[1])
     597              :             /* Use the upper bound of the range for strncat.  */
     598          480 :             wibnd = wi::to_offset (bndrng[1]);
     599              :         }
     600         2466 :       else if (bndrng[0])
     601              :         /* Use the lower bound of the range for functions other than
     602              :            strncat.  */
     603         2010 :         wibnd = wi::to_offset (bndrng[0]);
     604              : 
     605              :       /* Determine the size of the argument array if it is one.  */
     606         2954 :       offset_int asize = wibnd;
     607         2954 :       bool known_size = false;
     608         2954 :       tree type = TREE_TYPE (decl);
     609              : 
     610         2954 :       while (TREE_CODE (type) == ARRAY_TYPE
     611         4146 :              && TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
     612         1192 :         type = TREE_TYPE (type);
     613              : 
     614              :       /* Determine the array size.  For arrays of unknown bound and
     615              :          pointers reset BOUND to trigger the appropriate warning.  */
     616         2954 :       if (TREE_CODE (type) == ARRAY_TYPE)
     617              :         {
     618         2490 :           if (tree arrbnd = TYPE_DOMAIN (type))
     619              :             {
     620         2428 :               if ((arrbnd = TYPE_MAX_VALUE (arrbnd))
     621         2428 :                   && TREE_CODE (arrbnd) == INTEGER_CST)
     622              :                 {
     623         2426 :                   asize = wi::to_offset (arrbnd) + 1;
     624         2426 :                   known_size = true;
     625              :                 }
     626              :             }
     627           62 :           else if (bound == void_type_node)
     628         2954 :             bound = NULL_TREE;
     629              :         }
     630          464 :       else if (bound == void_type_node)
     631         2954 :         bound = NULL_TREE;
     632              : 
     633              :       /* In a call to strncat with a bound in a range whose lower but
     634              :          not upper bound is less than the array size, reset ASIZE to
     635              :          be the same as the bound and the other variable to trigger
     636              :          the appropriate warning below.  */
     637              :       if (fncode == BUILT_IN_STRNCAT
     638          480 :           && bndrng[0] != bndrng[1]
     639         3114 :           && wi::ltu_p (wi::to_offset (bndrng[0]), asize)
     640         3146 :           && (!known_size
     641          184 :               || wi::ltu_p (asize, wibnd)))
     642              :         {
     643           32 :           asize = wibnd;
     644           32 :           bound = NULL_TREE;
     645           32 :           fncode = 0;
     646              :         }
     647              : 
     648         2954 :       bool warned = false;
     649              : 
     650         2954 :       auto_diagnostic_group d;
     651         2954 :       if (wi::ltu_p (asize, wibnd))
     652              :         {
     653          369 :           rich_location_with_details richloc (loc, exp);
     654          369 :           if (bndrng[0] == bndrng[1])
     655          312 :             warned = warning_at (&richloc, OPT_Wstringop_overread,
     656              :                                  "%qD argument %i declared attribute "
     657              :                                  "%<nonstring%> is smaller than the specified "
     658              :                                  "bound %wu",
     659              :                                  fndecl, argno + 1, wibnd.to_uhwi ());
     660           57 :           else if (wi::ltu_p (asize, wi::to_offset (bndrng[0])))
     661           41 :             warned = warning_at (&richloc, OPT_Wstringop_overread,
     662              :                                  "%qD argument %i declared attribute "
     663              :                                  "%<nonstring%> is smaller than "
     664              :                                  "the specified bound [%E, %E]",
     665              :                                  fndecl, argno + 1, bndrng[0], bndrng[1]);
     666              :           else
     667           16 :             warned = warning_at (&richloc, OPT_Wstringop_overread,
     668              :                                  "%qD argument %i declared attribute "
     669              :                                  "%<nonstring%> may be smaller than "
     670              :                                  "the specified bound [%E, %E]",
     671              :                                  fndecl, argno + 1, bndrng[0], bndrng[1]);
     672          369 :         }
     673         2585 :       else if (fncode == BUILT_IN_STRNCAT)
     674              :         ; /* Avoid warning for calls to strncat() when the bound
     675              :              is equal to the size of the non-string argument.  */
     676         2177 :       else if (!bound)
     677          528 :         warned = warning_at (loc, OPT_Wstringop_overread,
     678              :                              "%qD argument %i declared attribute %<nonstring%>",
     679              :                              fndecl, argno + 1);
     680              : 
     681          897 :       if (warned)
     682              :         {
     683          897 :           inform (DECL_SOURCE_LOCATION (decl),
     684              :                   "argument %qD declared here", decl);
     685          897 :           any_arg_warned = true;
     686              :         }
     687              :     }
     688              : 
     689      1864238 :   if (any_arg_warned)
     690          897 :     suppress_warning (exp, OPT_Wstringop_overread);
     691              : 
     692              :   return any_arg_warned;
     693              : }
     694              : 
     695              : bool
     696       360332 : maybe_warn_nonstring_arg (tree fndecl, gimple *stmt)
     697              : {
     698       360332 :   return maybe_warn_nonstring_arg<gimple *>(fndecl, stmt);
     699              : }
     700              : 
     701              : 
     702              : bool
     703          356 : maybe_warn_nonstring_arg (tree fndecl, tree expr)
     704              : {
     705          356 :   return maybe_warn_nonstring_arg<tree>(fndecl, expr);
     706              : }
     707              : 
     708              : /* Issue a warning OPT for a bounded call EXP with a bound in RANGE
     709              :    accessing an object with SIZE.  */
     710              : 
     711              : template <class GimpleOrTree>
     712              : static bool
     713          464 : maybe_warn_for_bound (opt_code opt, location_t loc, GimpleOrTree exp, tree func,
     714              :                       tree bndrng[2], tree size, const access_data *pad)
     715              : {
     716          464 :   if (!bndrng[0] || warning_suppressed_p (exp, opt))
     717           91 :     return false;
     718              : 
     719          373 :   tree maxobjsize = max_object_size ();
     720              : 
     721          373 :   bool warned = false;
     722              : 
     723          373 :   if (opt == OPT_Wstringop_overread)
     724              :     {
     725          162 :       bool maybe = pad && pad->src.phi ();
     726              :       if (maybe)
     727              :         {
     728              :           /* Issue a "maybe" warning only if the PHI refers to objects
     729              :              at least one of which has more space remaining than the bound.
     730              :              Otherwise, if the bound is greater, use the definitive form.  */
     731            2 :           offset_int remmax = pad->src.size_remaining ();
     732            2 :           if (remmax < wi::to_offset (bndrng[0]))
     733            2 :             maybe = false;
     734              :         }
     735              : 
     736          162 :       auto_diagnostic_group d;
     737          162 :       if (tree_int_cst_lt (maxobjsize, bndrng[0]))
     738              :         {
     739           75 :           rich_location_with_details richloc (loc, exp);
     740           75 :           if (bndrng[0] == bndrng[1])
     741           73 :             warned = (func
     742          146 :                       ? warning_at (&richloc, opt,
     743              :                                     (maybe
     744              :                                      ? G_("%qD specified bound %E may "
     745              :                                           "exceed maximum object size %E")
     746              :                                      : G_("%qD specified bound %E "
     747              :                                           "exceeds maximum object size %E")),
     748              :                                     func, bndrng[0], maxobjsize)
     749           73 :                       : warning_at (&richloc, opt,
     750              :                                     (maybe
     751              :                                      ? G_("specified bound %E may "
     752              :                                           "exceed maximum object size %E")
     753              :                                      : G_("specified bound %E "
     754              :                                           "exceeds maximum object size %E")),
     755              :                                     bndrng[0], maxobjsize));
     756              :           else
     757            2 :             warned = (func
     758            4 :                       ? warning_at (&richloc, opt,
     759              :                                     (maybe
     760              :                                      ? G_("%qD specified bound [%E, %E] may "
     761              :                                           "exceed maximum object size %E")
     762              :                                      : G_("%qD specified bound [%E, %E] "
     763              :                                           "exceeds maximum object size %E")),
     764              :                                     func,
     765              :                                     bndrng[0], bndrng[1], maxobjsize)
     766            2 :                       : warning_at (&richloc, opt,
     767              :                                     (maybe
     768              :                                      ? G_("specified bound [%E, %E] may "
     769              :                                           "exceed maximum object size %E")
     770              :                                      : G_("specified bound [%E, %E] "
     771              :                                           "exceeds maximum object size %E")),
     772              :                                     bndrng[0], bndrng[1], maxobjsize));
     773           75 :         }
     774           87 :       else if (!size || tree_int_cst_le (bndrng[0], size))
     775            4 :         return false;
     776           83 :       else if (tree_int_cst_equal (bndrng[0], bndrng[1]))
     777              :         {
     778           73 :           rich_location_with_details richloc (loc, exp);
     779           73 :           warned = (func
     780          146 :                   ? warning_at (&richloc, opt,
     781              :                                 (maybe
     782              :                                  ? G_("%qD specified bound %E may exceed "
     783              :                                       "source size %E")
     784              :                                  : G_("%qD specified bound %E exceeds "
     785              :                                       "source size %E")),
     786              :                                 func, bndrng[0], size)
     787            0 :                   : warning_at (&richloc, opt,
     788              :                                 (maybe
     789              :                                  ? G_("specified bound %E may exceed "
     790              :                                       "source size %E")
     791              :                                  : G_("specified bound %E exceeds "
     792              :                                       "source size %E")),
     793              :                                 bndrng[0], size));
     794           73 :         }
     795              :       else
     796              :         {
     797           10 :           rich_location_with_details richloc (loc, exp);
     798           10 :           warned = (func
     799           20 :                   ? warning_at (&richloc, opt,
     800              :                                 (maybe
     801              :                                  ? G_("%qD specified bound [%E, %E] may "
     802              :                                       "exceed source size %E")
     803              :                                  : G_("%qD specified bound [%E, %E] exceeds "
     804              :                                       "source size %E")),
     805              :                                 func, bndrng[0], bndrng[1], size)
     806            0 :                   : warning_at (&richloc, opt,
     807              :                                 (maybe
     808              :                                  ? G_("specified bound [%E, %E] may exceed "
     809              :                                       "source size %E")
     810              :                                  : G_("specified bound [%E, %E] exceeds "
     811              :                                       "source size %E")),
     812              :                                 bndrng[0], bndrng[1], size));
     813           10 :         }
     814          158 :       if (warned)
     815              :         {
     816           77 :           if (pad && pad->src.ref
     817          150 :               && has_location (pad->src.ref))
     818           49 :             inform (get_location (pad->src.ref),
     819              :                     "source object allocated here");
     820           78 :           suppress_warning (exp, opt);
     821              :         }
     822              : 
     823          158 :       return warned;
     824          162 :     }
     825              : 
     826          414 :   bool maybe = pad && pad->dst.phi ();
     827          211 :   rich_location_with_details richloc (loc, exp);
     828          211 :   if (maybe)
     829              :     {
     830              :       /* Issue a "maybe" warning only if the PHI refers to objects
     831              :          at least one of which has more space remaining than the bound.
     832              :          Otherwise, if the bound is greater, use the definitive form.  */
     833            8 :       offset_int remmax = pad->dst.size_remaining ();
     834            8 :       if (remmax < wi::to_offset (bndrng[0]))
     835            8 :         maybe = false;
     836              :     }
     837          211 :   if (tree_int_cst_lt (maxobjsize, bndrng[0]))
     838              :     {
     839          100 :       if (bndrng[0] == bndrng[1])
     840           81 :         warned = (func
     841          162 :                   ? warning_at (&richloc, opt,
     842              :                                 (maybe
     843              :                                  ? G_("%qD specified size %E may "
     844              :                                       "exceed maximum object size %E")
     845              :                                  : G_("%qD specified size %E "
     846              :                                       "exceeds maximum object size %E")),
     847              :                                 func, bndrng[0], maxobjsize)
     848           81 :                   : warning_at (&richloc, opt,
     849              :                                 (maybe
     850              :                                  ? G_("specified size %E may exceed "
     851              :                                       "maximum object size %E")
     852              :                                  : G_("specified size %E exceeds "
     853              :                                       "maximum object size %E")),
     854              :                                 bndrng[0], maxobjsize));
     855              :       else
     856           19 :         warned = (func
     857           38 :                   ? warning_at (&richloc, opt,
     858              :                                 (maybe
     859              :                                  ? G_("%qD specified size between %E and %E "
     860              :                                       "may exceed maximum object size %E")
     861              :                                  : G_("%qD specified size between %E and %E "
     862              :                                       "exceeds maximum object size %E")),
     863              :                                 func, bndrng[0], bndrng[1], maxobjsize)
     864           19 :                   : warning_at (&richloc, opt,
     865              :                                 (maybe
     866              :                                  ? G_("specified size between %E and %E "
     867              :                                       "may exceed maximum object size %E")
     868              :                                  : G_("specified size between %E and %E "
     869              :                                       "exceeds maximum object size %E")),
     870              :                                 bndrng[0], bndrng[1], maxobjsize));
     871              :     }
     872          111 :   else if (!size || tree_int_cst_le (bndrng[0], size))
     873            0 :     return false;
     874          111 :   else if (tree_int_cst_equal (bndrng[0], bndrng[1]))
     875          102 :     warned = (func
     876          204 :               ? warning_at (&richloc, opt,
     877              :                             (maybe
     878              :                              ? G_("%qD specified bound %E may exceed "
     879              :                                   "destination size %E")
     880              :                              : G_("%qD specified bound %E exceeds "
     881              :                                   "destination size %E")),
     882              :                             func, bndrng[0], size)
     883          102 :               : warning_at (&richloc, opt,
     884              :                             (maybe
     885              :                              ? G_("specified bound %E may exceed "
     886              :                                   "destination size %E")
     887              :                              : G_("specified bound %E exceeds "
     888              :                                   "destination size %E")),
     889              :                             bndrng[0], size));
     890              :   else
     891            9 :     warned = (func
     892           18 :               ? warning_at (&richloc, opt,
     893              :                             (maybe
     894              :                              ? G_("%qD specified bound [%E, %E] may exceed "
     895              :                                   "destination size %E")
     896              :                              : G_("%qD specified bound [%E, %E] exceeds "
     897              :                                   "destination size %E")),
     898              :                             func, bndrng[0], bndrng[1], size)
     899            9 :               : warning_at (&richloc, opt,
     900              :                             (maybe
     901              :                              ? G_("specified bound [%E, %E] exceeds "
     902              :                                   "destination size %E")
     903              :                              : G_("specified bound [%E, %E] exceeds "
     904              :                                   "destination size %E")),
     905              :                             bndrng[0], bndrng[1], size));
     906              : 
     907          211 :   if (warned)
     908              :     {
     909           48 :       if (pad && pad->dst.ref
     910           97 :           && has_location (pad->dst.ref))
     911           43 :         inform (get_location (pad->dst.ref),
     912              :                 "destination object allocated here");
     913           52 :       suppress_warning (exp, opt);
     914              :     }
     915              : 
     916              :   return warned;
     917          211 : }
     918              : 
     919              : bool
     920          276 : maybe_warn_for_bound (opt_code opt, location_t loc, gimple *stmt, tree func,
     921              :                       tree bndrng[2], tree size,
     922              :                       const access_data *pad /* = NULL */)
     923              : {
     924          276 :   return maybe_warn_for_bound<gimple *> (opt, loc, stmt, func, bndrng, size,
     925          276 :                                          pad);
     926              : }
     927              : 
     928              : bool
     929           73 : maybe_warn_for_bound (opt_code opt, location_t loc, tree expr, tree func,
     930              :                       tree bndrng[2], tree size,
     931              :                       const access_data *pad /* = NULL */)
     932              : {
     933           73 :   return maybe_warn_for_bound<tree> (opt, loc, expr, func, bndrng, size, pad);
     934              : }
     935              : 
     936              : /* For an expression EXP issue an access warning controlled by option OPT
     937              :    with access to a region SIZE bytes in size in the RANGE of sizes.
     938              :    WRITE is true for a write access, READ for a read access, neither for
     939              :    call that may or may not perform an access but for which the range
     940              :    is expected to valid.
     941              :    Returns true when a warning has been issued.  */
     942              : 
     943              : template <class GimpleOrTree>
     944              : static bool
     945         1898 : warn_for_access (location_t loc, tree func, GimpleOrTree exp, int opt,
     946              :                  tree range[2], tree size, bool write, bool read, bool maybe)
     947              : {
     948         1898 :   bool warned = false;
     949              : 
     950         1898 :   rich_location_with_details richloc (loc, exp);
     951              : 
     952         1898 :   if (write && read)
     953              :     {
     954          138 :       if (tree_int_cst_equal (range[0], range[1]))
     955          138 :         warned = (func
     956          264 :                   ? warning_n (&richloc, opt, tree_to_uhwi (range[0]),
     957              :                                (maybe
     958              :                                 ? G_("%qD may access %E byte in a region "
     959              :                                      "of size %E")
     960              :                                 : G_("%qD accessing %E byte in a region "
     961              :                                      "of size %E")),
     962              :                                 (maybe
     963              :                                  ? G_ ("%qD may access %E bytes in a region "
     964              :                                        "of size %E")
     965              :                                  : G_ ("%qD accessing %E bytes in a region "
     966              :                                        "of size %E")),
     967              :                                func, range[0], size)
     968          150 :                   : warning_n (&richloc, opt, tree_to_uhwi (range[0]),
     969              :                                (maybe
     970              :                                 ? G_("may access %E byte in a region "
     971              :                                      "of size %E")
     972              :                                 : G_("accessing %E byte in a region "
     973              :                                      "of size %E")),
     974              :                                (maybe
     975              :                                 ? G_("may access %E bytes in a region "
     976              :                                      "of size %E")
     977              :                                 : G_("accessing %E bytes in a region "
     978              :                                      "of size %E")),
     979              :                                range[0], size));
     980            0 :       else if (tree_int_cst_sign_bit (range[1]))
     981              :         {
     982              :           /* Avoid printing the upper bound if it's invalid.  */
     983            0 :           warned = (func
     984            0 :                     ? warning_at (&richloc, opt,
     985              :                                   (maybe
     986              :                                    ? G_("%qD may access %E or more bytes "
     987              :                                         "in a region of size %E")
     988              :                                    : G_("%qD accessing %E or more bytes "
     989              :                                         "in a region of size %E")),
     990              :                                   func, range[0], size)
     991            0 :                     : warning_at (&richloc, opt,
     992              :                                   (maybe
     993              :                                    ? G_("may access %E or more bytes "
     994              :                                         "in a region of size %E")
     995              :                                    : G_("accessing %E or more bytes "
     996              :                                         "in a region of size %E")),
     997              :                                   range[0], size));
     998              :         }
     999              :       else
    1000            0 :         warned = (func
    1001            0 :                   ? warning_at (&richloc, opt,
    1002              :                                 (maybe
    1003              :                                  ? G_("%qD may access between %E and %E "
    1004              :                                       "bytes in a region of size %E")
    1005              :                                  : G_("%qD accessing between %E and %E "
    1006              :                                       "bytes in a region of size %E")),
    1007              :                                 func, range[0], range[1], size)
    1008            0 :                   : warning_at (&richloc, opt,
    1009              :                                 (maybe
    1010              :                                  ? G_("may access between %E and %E bytes "
    1011              :                                       "in a region of size %E")
    1012              :                                  : G_("accessing between %E and %E bytes "
    1013              :                                       "in a region of size %E")),
    1014              :                                 range[0], range[1], size));
    1015          138 :       return warned;
    1016              :     }
    1017              : 
    1018         1760 :   if (write)
    1019              :     {
    1020         1177 :       if (tree_int_cst_equal (range[0], range[1]))
    1021         1066 :         warned = (func
    1022         2130 :                   ? warning_n (&richloc, opt, tree_to_uhwi (range[0]),
    1023              :                                (maybe
    1024              :                                 ? G_("%qD may write %E byte into a region "
    1025              :                                      "of size %E")
    1026              :                                 : G_("%qD writing %E byte into a region "
    1027              :                                      "of size %E overflows the destination")),
    1028              :                                (maybe
    1029              :                                 ? G_("%qD may write %E bytes into a region "
    1030              :                                      "of size %E")
    1031              :                                 : G_("%qD writing %E bytes into a region "
    1032              :                                      "of size %E overflows the destination")),
    1033              :                                func, range[0], size)
    1034         1068 :                   : warning_n (&richloc, opt, tree_to_uhwi (range[0]),
    1035              :                                (maybe
    1036              :                                 ? G_("may write %E byte into a region "
    1037              :                                      "of size %E")
    1038              :                                 : G_("writing %E byte into a region "
    1039              :                                      "of size %E overflows the destination")),
    1040              :                                (maybe
    1041              :                                 ? G_("may write %E bytes into a region "
    1042              :                                      "of size %E")
    1043              :                                 : G_("writing %E bytes into a region "
    1044              :                                      "of size %E overflows the destination")),
    1045              :                                range[0], size));
    1046          111 :       else if (tree_int_cst_sign_bit (range[1]))
    1047              :         {
    1048              :           /* Avoid printing the upper bound if it's invalid.  */
    1049           51 :           warned = (func
    1050          102 :                     ? warning_at (&richloc, opt,
    1051              :                                   (maybe
    1052              :                                    ? G_("%qD may write %E or more bytes "
    1053              :                                         "into a region of size %E")
    1054              :                                    : G_("%qD writing %E or more bytes "
    1055              :                                         "into a region of size %E overflows "
    1056              :                                         "the destination")),
    1057              :                                   func, range[0], size)
    1058           51 :                     : warning_at (&richloc, opt,
    1059              :                                   (maybe
    1060              :                                    ? G_("may write %E or more bytes into "
    1061              :                                         "a region of size %E")
    1062              :                                    : G_("writing %E or more bytes into "
    1063              :                                         "a region of size %E overflows "
    1064              :                                         "the destination")),
    1065              :                                   range[0], size));
    1066              :         }
    1067              :       else
    1068           60 :         warned = (func
    1069          120 :                   ? warning_at (&richloc, opt,
    1070              :                                 (maybe
    1071              :                                  ? G_("%qD may write between %E and %E bytes "
    1072              :                                       "into a region of size %E")
    1073              :                                  : G_("%qD writing between %E and %E bytes "
    1074              :                                       "into a region of size %E overflows "
    1075              :                                       "the destination")),
    1076              :                                 func, range[0], range[1], size)
    1077           60 :                   : warning_at (&richloc, opt,
    1078              :                                 (maybe
    1079              :                                  ? G_("may write between %E and %E bytes "
    1080              :                                       "into a region of size %E")
    1081              :                                  : G_("writing between %E and %E bytes "
    1082              :                                       "into a region of size %E overflows "
    1083              :                                       "the destination")),
    1084              :                                 range[0], range[1], size));
    1085         1177 :       return warned;
    1086              :     }
    1087              : 
    1088          583 :   if (read)
    1089              :     {
    1090          580 :       if (tree_int_cst_equal (range[0], range[1]))
    1091          248 :         warned = (func
    1092          494 :                   ? warning_n (&richloc, OPT_Wstringop_overread,
    1093              :                                tree_to_uhwi (range[0]),
    1094              :                                (maybe
    1095              :                                 ? G_("%qD may read %E byte from a region "
    1096              :                                      "of size %E")
    1097              :                                 : G_("%qD reading %E byte from a region "
    1098              :                                      "of size %E")),
    1099              :                                (maybe
    1100              :                                 ? G_("%qD may read %E bytes from a region "
    1101              :                                      "of size %E")
    1102              :                                 : G_("%qD reading %E bytes from a region "
    1103              :                                      "of size %E")),
    1104              :                                func, range[0], size)
    1105          250 :                   : warning_n (&richloc, OPT_Wstringop_overread,
    1106              :                                tree_to_uhwi (range[0]),
    1107              :                                (maybe
    1108              :                                 ? G_("may read %E byte from a region "
    1109              :                                      "of size %E")
    1110              :                                 : G_("reading %E byte from a region "
    1111              :                                      "of size %E")),
    1112              :                                (maybe
    1113              :                                 ? G_("may read %E bytes from a region "
    1114              :                                      "of size %E")
    1115              :                                 : G_("reading %E bytes from a region "
    1116              :                                      "of size %E")),
    1117              :                                range[0], size));
    1118          332 :       else if (tree_int_cst_sign_bit (range[1]))
    1119              :         {
    1120              :           /* Avoid printing the upper bound if it's invalid.  */
    1121          306 :           warned = (func
    1122          612 :                     ? warning_at (&richloc, OPT_Wstringop_overread,
    1123              :                                   (maybe
    1124              :                                    ? G_("%qD may read %E or more bytes "
    1125              :                                         "from a region of size %E")
    1126              :                                    : G_("%qD reading %E or more bytes "
    1127              :                                         "from a region of size %E")),
    1128              :                                   func, range[0], size)
    1129          306 :                     : warning_at (&richloc, OPT_Wstringop_overread,
    1130              :                                   (maybe
    1131              :                                    ? G_("may read %E or more bytes "
    1132              :                                         "from a region of size %E")
    1133              :                                    : G_("reading %E or more bytes "
    1134              :                                         "from a region of size %E")),
    1135              :                                   range[0], size));
    1136              :         }
    1137              :       else
    1138           26 :         warned = (func
    1139           52 :                   ? warning_at (&richloc, OPT_Wstringop_overread,
    1140              :                                 (maybe
    1141              :                                  ? G_("%qD may read between %E and %E bytes "
    1142              :                                       "from a region of size %E")
    1143              :                                  : G_("%qD reading between %E and %E bytes "
    1144              :                                       "from a region of size %E")),
    1145              :                                 func, range[0], range[1], size)
    1146           26 :                   : warning_at (&richloc, opt,
    1147              :                                 (maybe
    1148              :                                  ? G_("may read between %E and %E bytes "
    1149              :                                       "from a region of size %E")
    1150              :                                  : G_("reading between %E and %E bytes "
    1151              :                                       "from a region of size %E")),
    1152              :                                 range[0], range[1], size));
    1153              : 
    1154          580 :       if (warned)
    1155          401 :         suppress_warning (exp, OPT_Wstringop_overread);
    1156              : 
    1157          580 :       return warned;
    1158              :     }
    1159              : 
    1160            3 :   if (tree_int_cst_equal (range[0], range[1])
    1161            3 :       || tree_int_cst_sign_bit (range[1]))
    1162            3 :     warned = (func
    1163            3 :               ? warning_n (&richloc, OPT_Wstringop_overread,
    1164              :                            tree_to_uhwi (range[0]),
    1165              :                            "%qD expecting %E byte in a region of size %E",
    1166              :                            "%qD expecting %E bytes in a region of size %E",
    1167              :                            func, range[0], size)
    1168            3 :               : warning_n (&richloc, OPT_Wstringop_overread,
    1169              :                            tree_to_uhwi (range[0]),
    1170              :                            "expecting %E byte in a region of size %E",
    1171              :                            "expecting %E bytes in a region of size %E",
    1172              :                            range[0], size));
    1173            0 :   else if (tree_int_cst_sign_bit (range[1]))
    1174              :     {
    1175              :       /* Avoid printing the upper bound if it's invalid.  */
    1176            0 :       warned = (func
    1177            0 :                 ? warning_at (&richloc, OPT_Wstringop_overread,
    1178              :                               "%qD expecting %E or more bytes in a region "
    1179              :                               "of size %E",
    1180              :                               func, range[0], size)
    1181            0 :                 : warning_at (&richloc, OPT_Wstringop_overread,
    1182              :                               "expecting %E or more bytes in a region "
    1183              :                               "of size %E",
    1184              :                               range[0], size));
    1185              :     }
    1186              :   else
    1187            0 :     warned = (func
    1188            0 :               ? warning_at (&richloc, OPT_Wstringop_overread,
    1189              :                             "%qD expecting between %E and %E bytes in "
    1190              :                             "a region of size %E",
    1191              :                             func, range[0], range[1], size)
    1192            0 :               : warning_at (&richloc, OPT_Wstringop_overread,
    1193              :                             "expecting between %E and %E bytes in "
    1194              :                             "a region of size %E",
    1195              :                             range[0], range[1], size));
    1196              : 
    1197            3 :   if (warned)
    1198            3 :     suppress_warning (exp, OPT_Wstringop_overread);
    1199              : 
    1200              :   return warned;
    1201         1898 : }
    1202              : 
    1203              : static bool
    1204         1443 : warn_for_access (location_t loc, tree func, gimple *stmt, int opt,
    1205              :                  tree range[2], tree size, bool write, bool read, bool maybe)
    1206              : {
    1207            0 :   return warn_for_access<gimple *>(loc, func, stmt, opt, range, size,
    1208            0 :                                    write, read, maybe);
    1209              : }
    1210              : 
    1211              : static bool
    1212          275 : warn_for_access (location_t loc, tree func, tree expr, int opt,
    1213              :                  tree range[2], tree size, bool write, bool read, bool maybe)
    1214              : {
    1215            0 :   return warn_for_access<tree>(loc, func, expr, opt, range, size,
    1216            0 :                                write, read, maybe);
    1217              : }
    1218              : 
    1219              : /* Helper to set RANGE to the range of BOUND if it's nonnull, bounded
    1220              :    by BNDRNG if nonnull and valid.  */
    1221              : 
    1222              : static void
    1223      1274046 : get_size_range (range_query *query, tree bound, gimple *stmt, tree range[2],
    1224              :                 int flags, const offset_int bndrng[2])
    1225              : {
    1226      1274046 :   if (bound)
    1227       495400 :     get_size_range (query, bound, stmt, range, flags);
    1228              : 
    1229      1274046 :   if (!bndrng || (bndrng[0] == 0 && bndrng[1] == HOST_WIDE_INT_M1U))
    1230       908707 :     return;
    1231              : 
    1232       365339 :   if (range[0] && TREE_CODE (range[0]) == INTEGER_CST)
    1233              :     {
    1234       365303 :       offset_int r[] =
    1235       365303 :         { wi::to_offset (range[0]), wi::to_offset (range[1]) };
    1236       365303 :       if (r[0] < bndrng[0])
    1237            0 :         range[0] = wide_int_to_tree (sizetype, bndrng[0]);
    1238       365303 :       if (bndrng[1] < r[1])
    1239            3 :         range[1] = wide_int_to_tree (sizetype, bndrng[1]);
    1240       365303 :     }
    1241              :   else
    1242              :     {
    1243           36 :       range[0] = wide_int_to_tree (sizetype, bndrng[0]);
    1244           36 :       range[1] = wide_int_to_tree (sizetype, bndrng[1]);
    1245              :     }
    1246              : }
    1247              : 
    1248              : /* Try to verify that the sizes and lengths of the arguments to a string
    1249              :    manipulation function given by EXP are within valid bounds and that
    1250              :    the operation does not lead to buffer overflow or read past the end.
    1251              :    Arguments other than EXP may be null.  When non-null, the arguments
    1252              :    have the following meaning:
    1253              :    DST is the destination of a copy call or NULL otherwise.
    1254              :    SRC is the source of a copy call or NULL otherwise.
    1255              :    DSTWRITE is the number of bytes written into the destination obtained
    1256              :    from the user-supplied size argument to the function (such as in
    1257              :    memcpy(DST, SRCs, DSTWRITE) or strncpy(DST, DRC, DSTWRITE).
    1258              :    MAXREAD is the user-supplied bound on the length of the source sequence
    1259              :    (such as in strncat(d, s, N).  It specifies the upper limit on the number
    1260              :    of bytes to write.  If NULL, it's taken to be the same as DSTWRITE.
    1261              :    SRCSTR is the source string (such as in strcpy(DST, SRC)) when the
    1262              :    expression EXP is a string function call (as opposed to a memory call
    1263              :    like memcpy).  As an exception, SRCSTR can also be an integer denoting
    1264              :    the precomputed size of the source string or object (for functions like
    1265              :    memcpy).
    1266              :    DSTSIZE is the size of the destination object.
    1267              : 
    1268              :    When DSTWRITE is null LEN is checked to verify that it doesn't exceed
    1269              :    SIZE_MAX.
    1270              : 
    1271              :    WRITE is true for write accesses, READ is true for reads.  Both are
    1272              :    false for simple size checks in calls to functions that neither read
    1273              :    from nor write to the region.
    1274              : 
    1275              :    When nonnull, PAD points to a more detailed description of the access.
    1276              : 
    1277              :    If the call is successfully verified as safe return true, otherwise
    1278              :    return false.  */
    1279              : 
    1280              : template <class GimpleOrTree>
    1281              : static bool
    1282       741145 : check_access (GimpleOrTree exp, tree dstwrite,
    1283              :               tree maxread, tree srcstr, tree dstsize,
    1284              :               access_mode mode, const access_data *pad,
    1285              :               range_query *rvals)
    1286              : {
    1287              :   /* The size of the largest object is half the address space, or
    1288              :      PTRDIFF_MAX.  (This is way too permissive.)  */
    1289       741145 :   tree maxobjsize = max_object_size ();
    1290              : 
    1291              :   /* Either an approximate/minimum the length of the source string for
    1292              :      string functions or the size of the source object for raw memory
    1293              :      functions.  */
    1294       741145 :   tree slen = NULL_TREE;
    1295              : 
    1296              :   /* The range of the access in bytes; first set to the write access
    1297              :      for functions that write and then read for those that also (or
    1298              :      just) read.  */
    1299       741145 :   tree range[2] = { NULL_TREE, NULL_TREE };
    1300              : 
    1301              :   /* Set to true when the exact number of bytes written by a string
    1302              :      function like strcpy is not known and the only thing that is
    1303              :      known is that it must be at least one (for the terminating nul).  */
    1304       741145 :   bool at_least_one = false;
    1305       741145 :   if (srcstr)
    1306              :     {
    1307              :       /* SRCSTR is normally a pointer to string but as a special case
    1308              :          it can be an integer denoting the length of a string.  */
    1309       446091 :       if (POINTER_TYPE_P (TREE_TYPE (srcstr)))
    1310              :         {
    1311       328834 :           if (!check_nul_terminated_array (exp, srcstr, maxread))
    1312              :             /* Return if the array is not nul-terminated and a warning
    1313              :                has been issued.  */
    1314          550 :             return false;
    1315              : 
    1316              :           /* Try to determine the range of lengths the source string
    1317              :              refers to.  If it can be determined and is less than
    1318              :              the upper bound given by MAXREAD add one to it for
    1319              :              the terminating nul.  Otherwise, set it to one for
    1320              :              the same reason, or to MAXREAD as appropriate.  */
    1321       328284 :           c_strlen_data lendata = { };
    1322       328284 :           get_range_strlen (srcstr, &lendata, /* eltsize = */ 1);
    1323       328284 :           range[0] = lendata.minlen;
    1324       328284 :           range[1] = lendata.maxbound ? lendata.maxbound : lendata.maxlen;
    1325       328284 :           if (range[0]
    1326       328284 :               && TREE_CODE (range[0]) == INTEGER_CST
    1327       328279 :               && TREE_CODE (range[1]) == INTEGER_CST
    1328       328279 :               && (!maxread || TREE_CODE (maxread) == INTEGER_CST))
    1329              :             {
    1330        29387 :               if (maxread && tree_int_cst_le (maxread, range[0]))
    1331          364 :                 range[0] = range[1] = maxread;
    1332              :               else
    1333       316413 :                 range[0] = fold_build2 (PLUS_EXPR, size_type_node,
    1334              :                                         range[0], size_one_node);
    1335              : 
    1336       316777 :               if (maxread && tree_int_cst_le (maxread, range[1]))
    1337        12357 :                 range[1] = maxread;
    1338       304420 :               else if (!integer_all_onesp (range[1]))
    1339       158189 :                 range[1] = fold_build2 (PLUS_EXPR, size_type_node,
    1340              :                                         range[1], size_one_node);
    1341              : 
    1342       316777 :               slen = range[0];
    1343              :             }
    1344              :           else
    1345              :             {
    1346        11507 :               at_least_one = true;
    1347        11507 :               slen = size_one_node;
    1348              :             }
    1349              :         }
    1350              :       else
    1351              :         slen = srcstr;
    1352              :     }
    1353              : 
    1354       740595 :   if (!dstwrite && !maxread)
    1355              :     {
    1356              :       /* When the only available piece of data is the object size
    1357              :          there is nothing to do.  */
    1358       287534 :       if (!slen)
    1359              :         return true;
    1360              : 
    1361              :       /* Otherwise, when the length of the source sequence is known
    1362              :          (as with strlen), set DSTWRITE to it.  */
    1363       287215 :       if (!range[0])
    1364           67 :         dstwrite = slen;
    1365              :     }
    1366              : 
    1367       740276 :   if (!dstsize)
    1368       322937 :     dstsize = maxobjsize;
    1369              : 
    1370              :   /* Set RANGE to that of DSTWRITE if non-null, bounded by PAD->DST_BNDRNG
    1371              :      if valid.  */
    1372       740276 :   gimple *stmt = pad ? pad->stmt : nullptr;
    1373      2218361 :   get_size_range (rvals, dstwrite, stmt, range,
    1374              :                   /* If the destination has known zero size prefer a zero
    1375              :                      size range to avoid false positives if that's a
    1376              :                      possibility.  */
    1377       740276 :                   integer_zerop (dstsize) ? SR_ALLOW_ZERO : 0,
    1378              :                   pad ? pad->dst_bndrng : NULL);
    1379              : 
    1380       740276 :   tree func = get_callee_fndecl (exp);
    1381              :   /* Read vs write access by built-ins can be determined from the const
    1382              :      qualifiers on the pointer argument.  In the absence of attribute
    1383              :      access, non-const qualified pointer arguments to user-defined
    1384              :      functions are assumed to both read and write the objects.  */
    1385       740276 :   const bool builtin = func ? fndecl_built_in_p (func) : false;
    1386              : 
    1387              :   /* First check the number of bytes to be written against the maximum
    1388              :      object size.  */
    1389       740276 :   if (range[0]
    1390       739116 :       && TREE_CODE (range[0]) == INTEGER_CST
    1391      1479388 :       && tree_int_cst_lt (maxobjsize, range[0]))
    1392              :     {
    1393          138 :       location_t loc = get_location (exp);
    1394          138 :       maybe_warn_for_bound (OPT_Wstringop_overflow_, loc, exp, func, range,
    1395              :                             NULL_TREE, pad);
    1396          138 :       return false;
    1397              :     }
    1398              : 
    1399              :   /* The number of bytes to write is "exact" if DSTWRITE is non-null,
    1400              :      constant, and in range of unsigned HOST_WIDE_INT.  */
    1401       740138 :   bool exactwrite = dstwrite && tree_fits_uhwi_p (dstwrite);
    1402              : 
    1403              :   /* Next check the number of bytes to be written against the destination
    1404              :      object size.  */
    1405       740138 :   if (range[0] || !exactwrite || integer_all_onesp (dstwrite))
    1406              :     {
    1407       740138 :       if (range[0]
    1408       738978 :           && TREE_CODE (range[0]) == INTEGER_CST
    1409      1479112 :           && ((tree_fits_uhwi_p (dstsize)
    1410       738657 :                && tree_int_cst_lt (dstsize, range[0]))
    1411       737367 :               || (dstwrite
    1412       411929 :                   && tree_fits_uhwi_p (dstwrite)
    1413       326902 :                   && tree_int_cst_lt (dstwrite, range[0]))))
    1414              :         {
    1415         1607 :           const opt_code opt = OPT_Wstringop_overflow_;
    1416         1607 :           if (warning_suppressed_p (exp, opt)
    1417         1607 :               || (pad && pad->dst.ref
    1418          902 :                   && warning_suppressed_p (pad->dst.ref, opt)))
    1419          281 :             return false;
    1420              : 
    1421         1326 :           auto_diagnostic_group d;
    1422         1326 :           location_t loc = get_location (exp);
    1423         1326 :           rich_location_with_details richloc (loc, exp);
    1424              : 
    1425         1326 :           bool warned = false;
    1426         1326 :           if (dstwrite == slen && at_least_one)
    1427              :             {
    1428              :               /* This is a call to strcpy with a destination of 0 size
    1429              :                  and a source of unknown length.  The call will write
    1430              :                  at least one byte past the end of the destination.  */
    1431            0 :               warned = (func
    1432            0 :                         ? warning_at (&richloc, opt,
    1433              :                                       "%qD writing %E or more bytes into "
    1434              :                                       "a region of size %E overflows "
    1435              :                                       "the destination",
    1436              :                                       func, range[0], dstsize)
    1437            0 :                         : warning_at (&richloc, opt,
    1438              :                                       "writing %E or more bytes into "
    1439              :                                       "a region of size %E overflows "
    1440              :                                       "the destination",
    1441              :                                       range[0], dstsize));
    1442              :             }
    1443              :           else
    1444              :             {
    1445         1326 :               const bool read
    1446         1326 :                 = mode == access_read_only || mode == access_read_write;
    1447         1326 :               const bool write
    1448         1326 :                 = mode == access_write_only || mode == access_read_write;
    1449         1326 :               const bool maybe = pad && pad->dst.parmarray;
    1450         1326 :               warned = warn_for_access (loc, func, exp,
    1451              :                                         OPT_Wstringop_overflow_,
    1452              :                                         range, dstsize,
    1453         1326 :                                         write, read && !builtin, maybe);
    1454              :             }
    1455              : 
    1456         1326 :           if (warned)
    1457              :             {
    1458          926 :               suppress_warning (exp, OPT_Wstringop_overflow_);
    1459          926 :               if (pad)
    1460          837 :                 pad->dst.inform_access (pad->mode);
    1461              :             }
    1462              : 
    1463              :           /* Return error when an overflow has been detected.  */
    1464              :           return false;
    1465         1326 :         }
    1466              :     }
    1467              : 
    1468              :   /* Check the maximum length of the source sequence against the size
    1469              :      of the destination object if known, or against the maximum size
    1470              :      of an object.  */
    1471       738531 :   if (maxread)
    1472              :     {
    1473              :       /* Set RANGE to that of MAXREAD, bounded by PAD->SRC_BNDRNG if
    1474              :          PAD is nonnull and BNDRNG is valid.  */
    1475        41938 :       get_size_range (rvals, maxread, stmt, range, 0,
    1476              :                       pad ? pad->src_bndrng : NULL);
    1477              : 
    1478        41938 :       location_t loc = get_location (exp);
    1479        41938 :       tree size = dstsize;
    1480        41938 :       if (pad && pad->mode == access_read_only)
    1481        38321 :         size = wide_int_to_tree (sizetype, pad->src.size_remaining ());
    1482              : 
    1483        41938 :       if (range[0] && maxread && tree_fits_uhwi_p (size))
    1484              :         {
    1485        41894 :           if (tree_int_cst_lt (maxobjsize, range[0]))
    1486              :             {
    1487           87 :               maybe_warn_for_bound (OPT_Wstringop_overread, loc, exp, func,
    1488              :                                     range, size, pad);
    1489           87 :               return false;
    1490              :             }
    1491              : 
    1492        41807 :           if (size != maxobjsize && tree_int_cst_lt (size, range[0]))
    1493              :             {
    1494          107 :               opt_code opt = (dstwrite || mode != access_read_only
    1495          218 :                               ? OPT_Wstringop_overflow_
    1496              :                               : OPT_Wstringop_overread);
    1497          218 :               maybe_warn_for_bound (opt, loc, exp, func, range, size, pad);
    1498          218 :               return false;
    1499              :             }
    1500              :         }
    1501              : 
    1502        41633 :       maybe_warn_nonstring_arg (func, exp);
    1503              :     }
    1504              : 
    1505              :   /* Check for reading past the end of SRC.  */
    1506      1476452 :   bool overread = (slen
    1507       738226 :                    && slen == srcstr
    1508       116643 :                    && dstwrite
    1509       115824 :                    && range[0]
    1510       115824 :                    && TREE_CODE (slen) == INTEGER_CST
    1511       854050 :                    && tree_int_cst_lt (slen, range[0]));
    1512              :   /* If none is determined try to get a better answer based on the details
    1513              :      in PAD.  */
    1514       738226 :   if (!overread
    1515       738226 :       && pad
    1516       736376 :       && pad->src.sizrng[1] >= 0
    1517       501802 :       && pad->src.offrng[0] >= 0
    1518      1474602 :       && (pad->src.offrng[1] < 0
    1519       489284 :           || pad->src.offrng[0] <= pad->src.offrng[1]))
    1520              :     {
    1521              :       /* Set RANGE to that of MAXREAD, bounded by PAD->SRC_BNDRNG if
    1522              :          PAD is nonnull and BNDRNG is valid.  */
    1523       489284 :       get_size_range (rvals, maxread, stmt, range, 0,
    1524              :                       pad ? pad->src_bndrng : NULL);
    1525              :       /* Set OVERREAD for reads starting just past the end of an object.  */
    1526       489284 :       overread = pad->src.sizrng[1] - pad->src.offrng[0] < pad->src_bndrng[0];
    1527       489284 :       range[0] = wide_int_to_tree (sizetype, pad->src_bndrng[0]);
    1528       489284 :       slen = size_zero_node;
    1529              :     }
    1530              : 
    1531       738226 :   if (overread)
    1532              :     {
    1533          667 :       const opt_code opt = OPT_Wstringop_overread;
    1534          667 :       if (warning_suppressed_p (exp, opt)
    1535          600 :           || (srcstr && warning_suppressed_p (srcstr, opt))
    1536         1239 :           || (pad && pad->src.ref
    1537          572 :               && warning_suppressed_p (pad->src.ref, opt)))
    1538           95 :         return false;
    1539              : 
    1540          572 :       location_t loc = get_location (exp);
    1541          572 :       const bool read
    1542          572 :         = mode == access_read_only || mode == access_read_write;
    1543          572 :       const bool maybe = pad && pad->dst.parmarray;
    1544          572 :       auto_diagnostic_group d;
    1545          572 :       if (warn_for_access (loc, func, exp, opt, range, slen, false, read,
    1546              :                            maybe))
    1547              :         {
    1548          393 :           suppress_warning (exp, opt);
    1549          393 :           if (pad)
    1550          393 :             pad->src.inform_access (access_read_only);
    1551              :         }
    1552              :       return false;
    1553          572 :     }
    1554              : 
    1555              :   return true;
    1556              : }
    1557              : 
    1558              : static bool
    1559       732436 : check_access (gimple *stmt, tree dstwrite,
    1560              :               tree maxread, tree srcstr, tree dstsize,
    1561              :               access_mode mode, const access_data *pad,
    1562              :               range_query *rvals)
    1563              : {
    1564            0 :   return check_access<gimple *> (stmt, dstwrite, maxread, srcstr, dstsize,
    1565            0 :                                  mode, pad, rvals);
    1566              : }
    1567              : 
    1568              : bool
    1569         1983 : check_access (tree expr, tree dstwrite,
    1570              :               tree maxread, tree srcstr, tree dstsize,
    1571              :               access_mode mode, const access_data *pad /* = NULL */)
    1572              : {
    1573         1983 :   return check_access<tree> (expr, dstwrite, maxread, srcstr, dstsize,
    1574         1983 :                              mode, pad, nullptr);
    1575              : }
    1576              : 
    1577              : /* Return true if STMT is a call to an allocation function.  Unless
    1578              :    ALL_ALLOC is set, consider only functions that return dynamically
    1579              :    allocated objects.  Otherwise return true even for all forms of
    1580              :    alloca (including VLA).  */
    1581              : 
    1582              : static bool
    1583        45959 : fndecl_alloc_p (tree fndecl, bool all_alloc)
    1584              : {
    1585        45959 :   if (!fndecl)
    1586              :     return false;
    1587              : 
    1588              :   /* A call to operator new isn't recognized as one to a built-in.  */
    1589        45854 :   if (DECL_IS_OPERATOR_NEW_P (fndecl))
    1590              :     return true;
    1591              : 
    1592        33893 :   if (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
    1593              :     {
    1594        29416 :       switch (DECL_FUNCTION_CODE (fndecl))
    1595              :         {
    1596              :         case BUILT_IN_ALLOCA:
    1597              :         case BUILT_IN_ALLOCA_WITH_ALIGN:
    1598              :           return all_alloc;
    1599              :         case BUILT_IN_ALIGNED_ALLOC:
    1600              :         case BUILT_IN_CALLOC:
    1601              :         case BUILT_IN_GOMP_ALLOC:
    1602              :         case BUILT_IN_GOMP_REALLOC:
    1603              :         case BUILT_IN_MALLOC:
    1604              :         case BUILT_IN_REALLOC:
    1605              :         case BUILT_IN_STRDUP:
    1606              :         case BUILT_IN_STRNDUP:
    1607              :           return true;
    1608              :         default:
    1609              :           break;
    1610              :         }
    1611              :     }
    1612              : 
    1613              :   /* A function is considered an allocation function if it's declared
    1614              :      with attribute malloc with an argument naming its associated
    1615              :      deallocation function.  */
    1616         4488 :   tree attrs = DECL_ATTRIBUTES (fndecl);
    1617         4488 :   if (!attrs)
    1618              :     return false;
    1619              : 
    1620          103 :   for (tree allocs = attrs;
    1621         1837 :        (allocs = lookup_attribute ("malloc", allocs));
    1622          103 :        allocs = TREE_CHAIN (allocs))
    1623              :     {
    1624         1005 :       tree args = TREE_VALUE (allocs);
    1625         1005 :       if (!args)
    1626          103 :         continue;
    1627              : 
    1628          902 :       if (TREE_VALUE (args))
    1629              :         return true;
    1630              :     }
    1631              : 
    1632              :   return false;
    1633              : }
    1634              : 
    1635              : /* Return true if STMT is a call to an allocation function.  A wrapper
    1636              :    around fndecl_alloc_p.  */
    1637              : 
    1638              : static bool
    1639        45959 : gimple_call_alloc_p (gimple *stmt, bool all_alloc = false)
    1640              : {
    1641        45959 :   return fndecl_alloc_p (gimple_call_fndecl (stmt), all_alloc);
    1642              : }
    1643              : 
    1644              : /* Return true if DELC doesn't refer to an operator delete that's
    1645              :    suitable to call with a pointer returned from the operator new
    1646              :    described by NEWC.  */
    1647              : 
    1648              : static bool
    1649         2438 : new_delete_mismatch_p (const demangle_component &newc,
    1650              :                        const demangle_component &delc)
    1651              : {
    1652         3752 :   if (newc.type != delc.type)
    1653              :     return true;
    1654              : 
    1655         3636 :   switch (newc.type)
    1656              :     {
    1657         1015 :     case DEMANGLE_COMPONENT_NAME:
    1658         1015 :       {
    1659         1015 :         int len = newc.u.s_name.len;
    1660         1015 :         const char *news = newc.u.s_name.s;
    1661         1015 :         const char *dels = delc.u.s_name.s;
    1662         1015 :         if (len != delc.u.s_name.len || memcmp (news, dels, len))
    1663              :           return true;
    1664              : 
    1665         1000 :         if (news[len] == 'n')
    1666              :           {
    1667          369 :             if (news[len + 1] == 'a')
    1668          126 :               return dels[len] != 'd' || dels[len + 1] != 'a';
    1669          264 :             if (news[len + 1] == 'w')
    1670          276 :               return dels[len] != 'd' || dels[len + 1] != 'l';
    1671              :           }
    1672              :         return false;
    1673              :       }
    1674              : 
    1675              :     case DEMANGLE_COMPONENT_OPERATOR:
    1676              :       /* Operator mismatches are handled above.  */
    1677              :       return false;
    1678              : 
    1679            0 :     case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
    1680            0 :       if (newc.u.s_extended_operator.args != delc.u.s_extended_operator.args)
    1681              :         return true;
    1682            0 :       return new_delete_mismatch_p (*newc.u.s_extended_operator.name,
    1683            0 :                                     *delc.u.s_extended_operator.name);
    1684              : 
    1685            0 :     case DEMANGLE_COMPONENT_FIXED_TYPE:
    1686            0 :       if (newc.u.s_fixed.accum != delc.u.s_fixed.accum
    1687            0 :           || newc.u.s_fixed.sat != delc.u.s_fixed.sat)
    1688              :         return true;
    1689            0 :       return new_delete_mismatch_p (*newc.u.s_fixed.length,
    1690            0 :                                     *delc.u.s_fixed.length);
    1691              : 
    1692            0 :     case DEMANGLE_COMPONENT_CTOR:
    1693            0 :       if (newc.u.s_ctor.kind != delc.u.s_ctor.kind)
    1694              :         return true;
    1695            0 :       return new_delete_mismatch_p (*newc.u.s_ctor.name,
    1696            0 :                                     *delc.u.s_ctor.name);
    1697              : 
    1698            0 :     case DEMANGLE_COMPONENT_DTOR:
    1699            0 :       if (newc.u.s_dtor.kind != delc.u.s_dtor.kind)
    1700              :         return true;
    1701            0 :       return new_delete_mismatch_p (*newc.u.s_dtor.name,
    1702            0 :                                     *delc.u.s_dtor.name);
    1703              : 
    1704          327 :     case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE:
    1705          327 :     case DEMANGLE_COMPONENT_BUILTIN_TYPE:
    1706          327 :       {
    1707              :         /* The demangler API provides no better way to compare built-in
    1708              :            types except to by comparing their demangled names. */
    1709          327 :         size_t nsz, dsz;
    1710          327 :         demangle_component *pnc = const_cast<demangle_component *>(&newc);
    1711          327 :         demangle_component *pdc = const_cast<demangle_component *>(&delc);
    1712          327 :         char *nts = cplus_demangle_print (0, pnc, 16, &nsz);
    1713          327 :         char *dts = cplus_demangle_print (0, pdc, 16, &dsz);
    1714          327 :         if (!nts != !dts)
    1715              :           return true;
    1716          327 :         bool mismatch = strcmp (nts, dts);
    1717          327 :         free (nts);
    1718          327 :         free (dts);
    1719          327 :         return mismatch;
    1720              :       }
    1721              : 
    1722            0 :     case DEMANGLE_COMPONENT_SUB_STD:
    1723            0 :       if (newc.u.s_string.len != delc.u.s_string.len)
    1724              :         return true;
    1725            0 :       return memcmp (newc.u.s_string.string, delc.u.s_string.string,
    1726            0 :                      newc.u.s_string.len);
    1727              : 
    1728            6 :     case DEMANGLE_COMPONENT_FUNCTION_PARAM:
    1729            6 :     case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
    1730            6 :     case DEMANGLE_COMPONENT_UNNAMED_TYPE:
    1731            6 :       return newc.u.s_number.number != delc.u.s_number.number;
    1732              : 
    1733            0 :     case DEMANGLE_COMPONENT_CHARACTER:
    1734            0 :       return newc.u.s_character.character != delc.u.s_character.character;
    1735              : 
    1736            0 :     case DEMANGLE_COMPONENT_DEFAULT_ARG:
    1737            0 :     case DEMANGLE_COMPONENT_LAMBDA:
    1738            0 :       if (newc.u.s_unary_num.num != delc.u.s_unary_num.num)
    1739              :         return true;
    1740            0 :       return new_delete_mismatch_p (*newc.u.s_unary_num.sub,
    1741            0 :                                     *delc.u.s_unary_num.sub);
    1742         1753 :     default:
    1743         1753 :       break;
    1744              :     }
    1745              : 
    1746         1753 :   if (!newc.u.s_binary.left != !delc.u.s_binary.left)
    1747              :     return true;
    1748              : 
    1749         1753 :   if (!newc.u.s_binary.left)
    1750              :     return false;
    1751              : 
    1752         1727 :   if (new_delete_mismatch_p (*newc.u.s_binary.left, *delc.u.s_binary.left)
    1753         1727 :       || !newc.u.s_binary.right != !delc.u.s_binary.right)
    1754              :     return true;
    1755              : 
    1756         1613 :   if (newc.u.s_binary.right)
    1757              :     return new_delete_mismatch_p (*newc.u.s_binary.right,
    1758              :                                   *delc.u.s_binary.right);
    1759              :   return false;
    1760              : }
    1761              : 
    1762              : /* Return true if DELETE_DECL is an operator delete that's not suitable
    1763              :    to call with a pointer returned from NEW_DECL.  */
    1764              : 
    1765              : static bool
    1766        11932 : new_delete_mismatch_p (tree new_decl, tree delete_decl)
    1767              : {
    1768        11932 :   tree new_name = DECL_ASSEMBLER_NAME (new_decl);
    1769        11932 :   tree delete_name = DECL_ASSEMBLER_NAME (delete_decl);
    1770              : 
    1771              :   /* valid_new_delete_pair_p() returns a conservative result (currently
    1772              :      it only handles global operators).  A true result is reliable but
    1773              :      a false result doesn't necessarily mean the operators don't match
    1774              :      unless CERTAIN is set.  */
    1775        11932 :   bool certain;
    1776        11932 :   if (valid_new_delete_pair_p (new_name, delete_name, &certain))
    1777              :     return false;
    1778              :   /* CERTAIN is set when the negative result is certain.  */
    1779          760 :   if (certain)
    1780              :     return true;
    1781              : 
    1782              :   /* For anything not handled by valid_new_delete_pair_p() such as member
    1783              :      operators compare the individual demangled components of the mangled
    1784              :      name.  */
    1785          717 :   const char *new_str = IDENTIFIER_POINTER (new_name);
    1786          717 :   const char *del_str = IDENTIFIER_POINTER (delete_name);
    1787              : 
    1788          717 :   void *np = NULL, *dp = NULL;
    1789          717 :   demangle_component *ndc = cplus_demangle_v3_components (new_str, 0, &np);
    1790          717 :   demangle_component *ddc = cplus_demangle_v3_components (del_str, 0, &dp);
    1791              : 
    1792              :   /* Sometimes, notably quite often with coroutines, 'operator new' is
    1793              :      templated.  However, template arguments can't change whether a given
    1794              :      new/delete is a singleton or array one, nor what it is a member of, so
    1795              :      the template arguments can be safely ignored for the purposes of checking
    1796              :      for mismatches.   */
    1797              : 
    1798         2139 :   auto strip_dc_template = [] (demangle_component* dc)
    1799              :   {
    1800          711 :     if (dc->type == DEMANGLE_COMPONENT_TEMPLATE)
    1801           57 :       dc = dc->u.s_binary.left;
    1802         1422 :     return dc;
    1803              :   };
    1804              : 
    1805          717 :   bool mismatch = (ndc && ddc
    1806         1428 :                    && new_delete_mismatch_p (*strip_dc_template (ndc),
    1807          711 :                                              *strip_dc_template (ddc)));
    1808          717 :   free (np);
    1809          717 :   free (dp);
    1810          717 :   return mismatch;
    1811              : }
    1812              : 
    1813              : /* ALLOC_DECL and DEALLOC_DECL are pair of allocation and deallocation
    1814              :    functions.  Return true if the latter is suitable to deallocate objects
    1815              :    allocated by calls to the former.  */
    1816              : 
    1817              : static bool
    1818        44590 : matching_alloc_calls_p (tree alloc_decl, tree dealloc_decl)
    1819              : {
    1820              :   /* Set to alloc_kind_t::builtin if ALLOC_DECL is associated with
    1821              :      a built-in deallocator.  */
    1822        44590 :   enum class alloc_kind_t { none, builtin, user }
    1823        44590 :   alloc_dealloc_kind = alloc_kind_t::none;
    1824              : 
    1825        44590 :   if (DECL_IS_OPERATOR_NEW_P (alloc_decl))
    1826              :     {
    1827        11961 :       if (DECL_IS_OPERATOR_DELETE_P (dealloc_decl))
    1828              :         /* Return true iff both functions are of the same array or
    1829              :            singleton form and false otherwise.  */
    1830        11932 :         return !new_delete_mismatch_p (alloc_decl, dealloc_decl);
    1831              : 
    1832              :       /* Return false for deallocation functions that are known not
    1833              :          to match.  */
    1834           29 :       if (fndecl_built_in_p (dealloc_decl, BUILT_IN_FREE, BUILT_IN_REALLOC))
    1835              :         return false;
    1836              :       /* Otherwise proceed below to check the deallocation function's
    1837              :          "*dealloc" attributes to look for one that mentions this operator
    1838              :          new.  */
    1839              :     }
    1840        32629 :   else if (fndecl_built_in_p (alloc_decl, BUILT_IN_NORMAL))
    1841              :     {
    1842        31715 :       switch (DECL_FUNCTION_CODE (alloc_decl))
    1843              :         {
    1844              :         case BUILT_IN_ALLOCA:
    1845              :         case BUILT_IN_ALLOCA_WITH_ALIGN:
    1846              :           return false;
    1847              : 
    1848         1223 :         case BUILT_IN_GOMP_ALLOC:
    1849         1223 :         case BUILT_IN_GOMP_REALLOC:
    1850         1223 :           if (DECL_IS_OPERATOR_DELETE_P (dealloc_decl))
    1851              :             return false;
    1852              : 
    1853         1223 :           if (fndecl_built_in_p (dealloc_decl, BUILT_IN_GOMP_FREE,
    1854              :                                                BUILT_IN_GOMP_REALLOC))
    1855              :             return true;
    1856              : 
    1857              :           alloc_dealloc_kind = alloc_kind_t::builtin;
    1858              :           break;
    1859              : 
    1860        30492 :         case BUILT_IN_ALIGNED_ALLOC:
    1861        30492 :         case BUILT_IN_CALLOC:
    1862        30492 :         case BUILT_IN_MALLOC:
    1863        30492 :         case BUILT_IN_REALLOC:
    1864        30492 :         case BUILT_IN_STRDUP:
    1865        30492 :         case BUILT_IN_STRNDUP:
    1866        30492 :           if (DECL_IS_OPERATOR_DELETE_P (dealloc_decl))
    1867              :             return false;
    1868              : 
    1869        30417 :           if (fndecl_built_in_p (dealloc_decl, BUILT_IN_FREE,
    1870              :                                                BUILT_IN_REALLOC))
    1871              :             return true;
    1872              : 
    1873              :           alloc_dealloc_kind = alloc_kind_t::builtin;
    1874              :           break;
    1875              : 
    1876              :         default:
    1877              :           break;
    1878              :         }
    1879              :     }
    1880              : 
    1881              :   /* Set if DEALLOC_DECL both allocates and deallocates.  */
    1882          953 :   alloc_kind_t realloc_kind = alloc_kind_t::none;
    1883              : 
    1884          953 :   if (fndecl_built_in_p (dealloc_decl, BUILT_IN_NORMAL))
    1885              :     {
    1886          129 :       built_in_function dealloc_code = DECL_FUNCTION_CODE (dealloc_decl);
    1887          129 :       if (dealloc_code == BUILT_IN_REALLOC
    1888          129 :           || dealloc_code == BUILT_IN_GOMP_REALLOC)
    1889           26 :         realloc_kind = alloc_kind_t::builtin;
    1890              : 
    1891          129 :       for (tree amats = DECL_ATTRIBUTES (alloc_decl);
    1892          224 :            (amats = lookup_attribute ("malloc", amats));
    1893           95 :            amats = TREE_CHAIN (amats))
    1894              :         {
    1895          163 :           tree args = TREE_VALUE (amats);
    1896          163 :           if (!args)
    1897            0 :             continue;
    1898              : 
    1899          163 :           tree fndecl = TREE_VALUE (args);
    1900          163 :           if (!fndecl || !DECL_P (fndecl))
    1901            0 :             continue;
    1902              : 
    1903          163 :           if (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
    1904          163 :               && dealloc_code == DECL_FUNCTION_CODE (fndecl))
    1905              :             return true;
    1906              :         }
    1907              :     }
    1908              : 
    1909          885 :   const bool alloc_builtin = fndecl_built_in_p (alloc_decl, BUILT_IN_NORMAL);
    1910          885 :   alloc_kind_t realloc_dealloc_kind = alloc_kind_t::none;
    1911              : 
    1912              :   /* If DEALLOC_DECL has an internal "*dealloc" attribute scan the list
    1913              :      of its associated allocation functions for ALLOC_DECL.
    1914              :      If the corresponding ALLOC_DECL is found they're a matching pair,
    1915              :      otherwise they're not.
    1916              :      With DDATS set to the Deallocator's *Dealloc ATtributes...  */
    1917          885 :   for (tree ddats = DECL_ATTRIBUTES (dealloc_decl);
    1918         3131 :        (ddats = lookup_attribute ("*dealloc", ddats));
    1919         2246 :        ddats = TREE_CHAIN (ddats))
    1920              :     {
    1921         2964 :       tree args = TREE_VALUE (ddats);
    1922         2964 :       if (!args)
    1923            0 :         continue;
    1924              : 
    1925         2964 :       tree alloc = TREE_VALUE (args);
    1926         2964 :       if (!alloc)
    1927            0 :         continue;
    1928              : 
    1929         2964 :       if (alloc == DECL_NAME (dealloc_decl))
    1930           44 :         realloc_kind = alloc_kind_t::user;
    1931              : 
    1932         2964 :       if (DECL_P (alloc))
    1933              :         {
    1934            0 :           gcc_checking_assert (fndecl_built_in_p (alloc, BUILT_IN_NORMAL));
    1935              : 
    1936            0 :           switch (DECL_FUNCTION_CODE (alloc))
    1937              :             {
    1938            0 :             case BUILT_IN_ALIGNED_ALLOC:
    1939            0 :             case BUILT_IN_CALLOC:
    1940            0 :             case BUILT_IN_GOMP_ALLOC:
    1941            0 :             case BUILT_IN_GOMP_REALLOC:
    1942            0 :             case BUILT_IN_MALLOC:
    1943            0 :             case BUILT_IN_REALLOC:
    1944            0 :             case BUILT_IN_STRDUP:
    1945            0 :             case BUILT_IN_STRNDUP:
    1946            0 :               realloc_dealloc_kind = alloc_kind_t::builtin;
    1947            0 :               break;
    1948              :             default:
    1949              :               break;
    1950              :             }
    1951              : 
    1952            0 :           if (!alloc_builtin)
    1953            0 :             continue;
    1954              : 
    1955            0 :           if (DECL_FUNCTION_CODE (alloc) != DECL_FUNCTION_CODE (alloc_decl))
    1956            0 :             continue;
    1957              : 
    1958              :           return true;
    1959              :         }
    1960              : 
    1961         2964 :       if (alloc == DECL_NAME (alloc_decl))
    1962              :         return true;
    1963              :     }
    1964              : 
    1965          167 :   if (realloc_kind == alloc_kind_t::none)
    1966              :     return false;
    1967              : 
    1968          108 :   hash_set<tree> common_deallocs;
    1969              :   /* Special handling for deallocators.  Iterate over both the allocator's
    1970              :      and the reallocator's associated deallocator functions looking for
    1971              :      the first one in common.  If one is found, the de/reallocator is
    1972              :      a match for the allocator even though the latter isn't directly
    1973              :      associated with the former.  This simplifies declarations in system
    1974              :      headers.
    1975              :      With AMATS set to the Allocator's Malloc ATtributes,
    1976              :      and  RMATS set to Reallocator's Malloc ATtributes...  */
    1977          114 :   for (tree amats = DECL_ATTRIBUTES (alloc_decl);
    1978          114 :        (amats = lookup_attribute ("malloc", amats));
    1979           60 :        amats = amats ? TREE_CHAIN (amats) : NULL_TREE)
    1980           68 :     if (tree args = amats ? TREE_VALUE (amats) : NULL_TREE)
    1981           58 :       if (tree adealloc = TREE_VALUE (args))
    1982              :         {
    1983           58 :           if (DECL_P (adealloc)
    1984           58 :               && fndecl_built_in_p (adealloc, BUILT_IN_NORMAL))
    1985              :             {
    1986           12 :               built_in_function fncode = DECL_FUNCTION_CODE (adealloc);
    1987           12 :               if (fncode == BUILT_IN_FREE || fncode == BUILT_IN_REALLOC)
    1988              :                 {
    1989           12 :                   if (realloc_kind == alloc_kind_t::builtin)
    1990            8 :                     return true;
    1991              :                   alloc_dealloc_kind = alloc_kind_t::builtin;
    1992              :                 }
    1993            4 :               continue;
    1994            4 :             }
    1995              : 
    1996           46 :           common_deallocs.add (adealloc);
    1997              :         }
    1998           82 :   for (tree rmats = DECL_ATTRIBUTES (dealloc_decl);
    1999           82 :        (rmats = lookup_attribute ("malloc", rmats));
    2000           36 :        rmats = rmats ? TREE_CHAIN (rmats) : NULL_TREE)
    2001           56 :     if (tree args = rmats ? TREE_VALUE (rmats) : NULL_TREE)
    2002           56 :       if (tree ddealloc = TREE_VALUE (args))
    2003              :         {
    2004           56 :           if (DECL_P (ddealloc)
    2005           56 :               && fndecl_built_in_p (ddealloc, BUILT_IN_NORMAL))
    2006              :             {
    2007           16 :               built_in_function fncode = DECL_FUNCTION_CODE (ddealloc);
    2008           16 :               if (fncode == BUILT_IN_FREE || fncode == BUILT_IN_REALLOC)
    2009              :                 {
    2010           16 :                   if (alloc_dealloc_kind == alloc_kind_t::builtin)
    2011           20 :                     return true;
    2012              :                   realloc_dealloc_kind = alloc_kind_t::builtin;
    2013              :                 }
    2014            1 :               continue;
    2015            1 :             }
    2016              : 
    2017           40 :           if (common_deallocs.contains (ddealloc))
    2018              :             return true;
    2019              :         }
    2020              : 
    2021              :   /* Succeed only if ALLOC_DECL and the reallocator DEALLOC_DECL share
    2022              :      a built-in deallocator.  */
    2023           26 :   return  (alloc_dealloc_kind == alloc_kind_t::builtin
    2024           26 :            && realloc_dealloc_kind == alloc_kind_t::builtin);
    2025              : }
    2026              : 
    2027              : /* Return true if DEALLOC_DECL is a function suitable to deallocate
    2028              :    objects allocated by the ALLOC call.  */
    2029              : 
    2030              : static bool
    2031        44590 : matching_alloc_calls_p (gimple *alloc, tree dealloc_decl)
    2032              : {
    2033        44590 :   tree alloc_decl = gimple_call_fndecl (alloc);
    2034        44590 :   if (!alloc_decl)
    2035              :     return true;
    2036              : 
    2037        44590 :   return matching_alloc_calls_p (alloc_decl, dealloc_decl);
    2038              : }
    2039              : 
    2040              : /* Diagnose a call EXP to deallocate a pointer referenced by AREF if it
    2041              :    includes a nonzero offset.  Such a pointer cannot refer to the beginning
    2042              :    of an allocated object.  A negative offset may refer to it only if
    2043              :    the target pointer is unknown.  */
    2044              : 
    2045              : static bool
    2046       164137 : warn_dealloc_offset (location_t loc, gimple *call, const access_ref &aref)
    2047              : {
    2048       164137 :   if (aref.deref || aref.offrng[0] <= 0 || aref.offrng[1] <= 0)
    2049       164062 :     return false;
    2050              : 
    2051           75 :   tree dealloc_decl = gimple_call_fndecl (call);
    2052           75 :   if (!dealloc_decl)
    2053              :     return false;
    2054              : 
    2055           75 :   if (DECL_IS_OPERATOR_DELETE_P (dealloc_decl)
    2056           75 :       && !DECL_IS_REPLACEABLE_OPERATOR (dealloc_decl))
    2057              :     {
    2058              :       /* A call to a user-defined operator delete with a pointer plus offset
    2059              :          may be valid if it's returned from an unknown function (i.e., one
    2060              :          that's not operator new).  */
    2061            6 :       if (TREE_CODE (aref.ref) == SSA_NAME)
    2062              :         {
    2063            6 :           gimple *def_stmt = SSA_NAME_DEF_STMT (aref.ref);
    2064            6 :           if (is_gimple_call (def_stmt))
    2065              :             {
    2066            6 :               tree alloc_decl = gimple_call_fndecl (def_stmt);
    2067            9 :               if (!alloc_decl || !DECL_IS_OPERATOR_NEW_P (alloc_decl))
    2068              :                 return false;
    2069              :             }
    2070              :         }
    2071              :     }
    2072              : 
    2073           69 :   char offstr[80];
    2074           69 :   offstr[0] = '\0';
    2075           69 :   if (wi::fits_shwi_p (aref.offrng[0]))
    2076              :     {
    2077           69 :       if (aref.offrng[0] == aref.offrng[1]
    2078           69 :           || !wi::fits_shwi_p (aref.offrng[1]))
    2079           55 :         sprintf (offstr, " %lli",
    2080           55 :                  (long long)aref.offrng[0].to_shwi ());
    2081              :       else
    2082           14 :         sprintf (offstr, " [%lli, %lli]",
    2083           14 :                  (long long)aref.offrng[0].to_shwi (),
    2084           14 :                  (long long)aref.offrng[1].to_shwi ());
    2085              :     }
    2086              : 
    2087           69 :   auto_diagnostic_group d;
    2088           69 :   if (!warning_at (loc, OPT_Wfree_nonheap_object,
    2089              :                    "%qD called on pointer %qE with nonzero offset%s",
    2090           69 :                    dealloc_decl, aref.ref, offstr))
    2091              :     return false;
    2092              : 
    2093           69 :   if (DECL_P (aref.ref))
    2094            8 :     inform (get_location (aref.ref), "declared here");
    2095           61 :   else if (TREE_CODE (aref.ref) == SSA_NAME)
    2096              :     {
    2097           59 :       gimple *def_stmt = SSA_NAME_DEF_STMT (aref.ref);
    2098           59 :       if (is_gimple_call (def_stmt))
    2099              :         {
    2100           53 :           location_t def_loc = get_location (def_stmt);
    2101           53 :           tree alloc_decl = gimple_call_fndecl (def_stmt);
    2102           53 :           if (alloc_decl)
    2103           53 :             inform (def_loc,
    2104              :                     "returned from %qD", alloc_decl);
    2105            0 :           else if (tree alloc_fntype = gimple_call_fntype (def_stmt))
    2106            0 :             inform (def_loc,
    2107              :                     "returned from %qT", alloc_fntype);
    2108              :           else
    2109            0 :             inform (def_loc,  "obtained here");
    2110              :         }
    2111              :     }
    2112              : 
    2113              :   return true;
    2114           69 : }
    2115              : 
    2116              : namespace {
    2117              : 
    2118              : const pass_data pass_data_waccess = {
    2119              :   GIMPLE_PASS,
    2120              :   "waccess",
    2121              :   OPTGROUP_NONE,
    2122              :   TV_WARN_ACCESS, /* timer variable */
    2123              :   PROP_cfg, /* properties_required  */
    2124              :   0,        /* properties_provided  */
    2125              :   0,        /* properties_destroyed  */
    2126              :   0,        /* properties_start */
    2127              :   0,        /* properties_finish */
    2128              : };
    2129              : 
    2130              : /* Pass to detect invalid accesses.  */
    2131              : class pass_waccess : public gimple_opt_pass
    2132              : {
    2133              :  public:
    2134              :   pass_waccess (gcc::context *);
    2135              : 
    2136              :   ~pass_waccess ();
    2137              : 
    2138              :   opt_pass *clone () final override;
    2139              : 
    2140              :   bool gate (function *) final override;
    2141              : 
    2142              :   void set_pass_param (unsigned, bool) final override;
    2143              : 
    2144              :   unsigned int execute (function *) final override;
    2145              : 
    2146              : private:
    2147              :   /* Not copyable or assignable.  */
    2148              :   pass_waccess (pass_waccess &) = delete;
    2149              :   void operator= (pass_waccess &) = delete;
    2150              : 
    2151              :   /* Check a call to an atomic built-in function.  */
    2152              :   bool check_atomic_builtin (gcall *);
    2153              : 
    2154              :   /* Check a call to a built-in function.  */
    2155              :   bool check_builtin (gcall *);
    2156              : 
    2157              :   /* Check a call to an ordinary function for invalid accesses.  */
    2158              :   bool check_call_access (gcall *);
    2159              : 
    2160              :   /* Check a non-call statement.  */
    2161              :   void check_stmt (gimple *);
    2162              : 
    2163              :   /* Check statements in a basic block.  */
    2164              :   void check_block (basic_block);
    2165              : 
    2166              :   /* Check a call to a function.  */
    2167              :   void check_call (gcall *);
    2168              : 
    2169              :   /* Check a call to the named built-in function.  */
    2170              :   void check_alloca (gcall *);
    2171              :   void check_alloc_size_call (gcall *);
    2172              :   void check_strcat (gcall *);
    2173              :   void check_strncat (gcall *);
    2174              :   void check_stxcpy (gcall *);
    2175              :   void check_stxncpy (gcall *);
    2176              :   void check_strncmp (gcall *);
    2177              :   void check_memop_access (gimple *, tree, tree, tree);
    2178              :   void check_read_access (gimple *, tree, tree = NULL_TREE, int = 1);
    2179              : 
    2180              :   void maybe_check_dealloc_call (gcall *);
    2181              :   void maybe_check_access_sizes (rdwr_map *, tree, tree, gimple *);
    2182              :   bool maybe_warn_memmodel (gimple *, tree, tree, const unsigned char *);
    2183              :   void check_atomic_memmodel (gimple *, tree, tree, const unsigned char *);
    2184              : 
    2185              :   /* Check for uses of indeterminate pointers.  */
    2186              :   void check_pointer_uses (gimple *, tree, tree = NULL_TREE, bool = false);
    2187              : 
    2188              :   /* Return the argument that a call returns.  */
    2189              :   tree gimple_call_return_arg (gcall *);
    2190              : 
    2191              :   /* Check a call for uses of a dangling pointer arguments.  */
    2192              :   void check_call_dangling (gcall *);
    2193              : 
    2194              :   /* Check uses of a dangling pointer or those derived from it.  */
    2195              :   void check_dangling_uses (tree, tree, bool = false, bool = false);
    2196              :   void check_dangling_uses ();
    2197              :   void check_dangling_stores ();
    2198              :   bool check_dangling_stores (basic_block, hash_set<tree> &);
    2199              : 
    2200              :   void warn_invalid_pointer (tree, gimple *, gimple *, tree, bool, bool = false);
    2201              : 
    2202              :   /* Return true if use follows an invalidating statement.  */
    2203              :   bool use_after_inval_p (gimple *, gimple *, bool = false);
    2204              : 
    2205              :   /* A pointer_query object to store information about pointers and
    2206              :      their targets in.  */
    2207              :   pointer_query m_ptr_qry;
    2208              :   /* Mapping from DECLs and their clobber statements in the function.  */
    2209              :   hash_map<tree, gimple *> m_clobbers;
    2210              :   /* A bit is set for each basic block whose statements have been assigned
    2211              :      valid UIDs.  */
    2212              :   bitmap m_bb_uids_set;
    2213              :   /* The current function.  */
    2214              :   function *m_func;
    2215              :   /* True to run checks for uses of dangling pointers.  */
    2216              :   bool m_check_dangling_p;
    2217              :   /* True to run checks early on in the optimization pipeline.  */
    2218              :   bool m_early_checks_p;
    2219              : };
    2220              : 
    2221              : /* Construct the pass.  */
    2222              : 
    2223       857166 : pass_waccess::pass_waccess (gcc::context *ctxt)
    2224              :   : gimple_opt_pass (pass_data_waccess, ctxt),
    2225       857166 :     m_ptr_qry (NULL),
    2226       857166 :     m_clobbers (),
    2227       857166 :     m_bb_uids_set (),
    2228       857166 :     m_func (),
    2229       857166 :     m_check_dangling_p (),
    2230       857166 :     m_early_checks_p ()
    2231              : {
    2232       857166 : }
    2233              : 
    2234              : /* Return a copy of the pass with RUN_NUMBER one greater than THIS.  */
    2235              : 
    2236              : opt_pass*
    2237       571444 : pass_waccess::clone ()
    2238              : {
    2239       571444 :   return new pass_waccess (m_ctxt);
    2240              : }
    2241              : 
    2242              : /* Release pointer_query cache.  */
    2243              : 
    2244      1539726 : pass_waccess::~pass_waccess ()
    2245              : {
    2246       769863 :   m_ptr_qry.flush_cache ();
    2247      1539726 : }
    2248              : 
    2249              : void
    2250      1714332 : pass_waccess::set_pass_param (unsigned int n, bool param)
    2251              : {
    2252              :   /* Check for dangling pointers in the earliest runs of the pass.
    2253              :      The latest point -Wdangling-pointer should run is just before
    2254              :      loop unrolling which introduces uses after clobbers.  Most cases
    2255              :      can be detected without optimization; cases where the address of
    2256              :      the local variable is passed to and then returned from a user-
    2257              :      defined function before its lifetime ends and the returned pointer
    2258              :      becomes dangling depend on inlining.  */
    2259      1714332 :   if (n == 0)
    2260       857166 :     m_early_checks_p = param;
    2261       857166 :   else if (n == 1)
    2262       857166 :     m_check_dangling_p = param;
    2263              :   else
    2264            0 :     __builtin_unreachable ();
    2265      1714332 : }
    2266              : 
    2267              : /* Return true when any checks performed by the pass are enabled.  */
    2268              : 
    2269              : bool
    2270      5362298 : pass_waccess::gate (function *)
    2271              : {
    2272      5362298 :   return (warn_free_nonheap_object
    2273          117 :           || warn_mismatched_alloc
    2274      5362415 :           || warn_mismatched_new_delete);
    2275              : }
    2276              : 
    2277              : /* Initialize ALLOC_OBJECT_SIZE_LIMIT based on the -Walloc-size-larger-than=
    2278              :    setting if the option is specified, or to the maximum object size if it
    2279              :    is not.  Return the initialized value.  */
    2280              : 
    2281              : static tree
    2282        74326 : alloc_max_size (void)
    2283              : {
    2284        74326 :   HOST_WIDE_INT limit = warn_alloc_size_limit;
    2285        74326 :   if (limit == HOST_WIDE_INT_MAX)
    2286        73930 :     limit = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node));
    2287              : 
    2288        74326 :   return build_int_cst (size_type_node, limit);
    2289              : }
    2290              : 
    2291              : /* Diagnose a call EXP to function FN decorated with attribute alloc_size
    2292              :    whose argument numbers given by IDX with values given by ARGS exceed
    2293              :    the maximum object size or cause an unsigned overflow (wrapping) when
    2294              :    multiplied.  FN is null when EXP is a call via a function pointer.
    2295              :    When ARGS[0] is null the function does nothing.  ARGS[1] may be null
    2296              :    for functions like malloc, and non-null for those like calloc that
    2297              :    are decorated with a two-argument attribute alloc_size.  */
    2298              : 
    2299              : void
    2300        74326 : maybe_warn_alloc_args_overflow (gimple *stmt, const tree args[2],
    2301              :                                 const int idx[2])
    2302              : {
    2303              :   /* The range each of the (up to) two arguments is known to be in.  */
    2304        74326 :   tree argrange[2][2] = { { NULL_TREE, NULL_TREE }, { NULL_TREE, NULL_TREE } };
    2305              : 
    2306              :   /* Maximum object size set by -Walloc-size-larger-than= or SIZE_MAX / 2.  */
    2307        74326 :   tree maxobjsize = alloc_max_size ();
    2308              : 
    2309        74326 :   location_t loc = get_location (stmt);
    2310              : 
    2311        74326 :   tree fn = gimple_call_fndecl (stmt);
    2312        74326 :   tree fntype = fn ? TREE_TYPE (fn) : gimple_call_fntype (stmt);
    2313        74326 :   bool warned = false;
    2314              : 
    2315              :   /* Validate each argument individually.  */
    2316       149935 :   for (unsigned i = 0; i != 2 && args[i]; ++i)
    2317              :     {
    2318        75609 :       if (TREE_CODE (args[i]) == INTEGER_CST)
    2319              :         {
    2320        38488 :           argrange[i][0] = args[i];
    2321        38488 :           argrange[i][1] = args[i];
    2322              : 
    2323        38488 :           if (tree_int_cst_lt (args[i], integer_zero_node))
    2324              :             {
    2325           24 :               warned = warning_at (loc, OPT_Walloc_size_larger_than_,
    2326              :                                    "argument %i value %qE is negative",
    2327           24 :                                    idx[i] + 1, args[i]);
    2328              :             }
    2329        38464 :           else if (integer_zerop (args[i]))
    2330              :             {
    2331              :               /* Avoid issuing -Walloc-zero for allocation functions other
    2332              :                  than __builtin_alloca that are declared with attribute
    2333              :                  returns_nonnull because there's no portability risk.  This
    2334              :                  avoids warning for such calls to libiberty's xmalloc and
    2335              :                  friends.
    2336              :                  Also avoid issuing the warning for calls to function named
    2337              :                  "alloca".  */
    2338          942 :               if (fn && fndecl_built_in_p (fn, BUILT_IN_ALLOCA)
    2339          964 :                   ? IDENTIFIER_LENGTH (DECL_NAME (fn)) != 6
    2340          482 :                   : !lookup_attribute ("returns_nonnull",
    2341          482 :                                        TYPE_ATTRIBUTES (fntype)))
    2342          475 :                 warned = warning_at (loc, OPT_Walloc_zero,
    2343              :                                      "argument %i value is zero",
    2344          475 :                                      idx[i] + 1);
    2345              :             }
    2346        37982 :           else if (tree_int_cst_lt (maxobjsize, args[i]))
    2347              :             {
    2348              :               /* G++ emits calls to ::operator new[](SIZE_MAX) in C++98 mode or
    2349              :                  with -fno-exceptions as a way to indicate array size overflow.
    2350              :                  Avoid diagnosing these calls.  Additionally, see e.g. PR99934,
    2351              :                  G++ also potentially generates such calls in C++11 and later as
    2352              :                  well, so suppress the diagnostic in all C++ modes.  */
    2353          130 :               if (i == 0
    2354          107 :                   && fn
    2355           89 :                   && !args[1]
    2356           81 :                   && DECL_IS_OPERATOR_NEW_P (fn)
    2357          130 :                   && integer_all_onesp (args[i]))
    2358           23 :                 continue;
    2359              : 
    2360           84 :               warned = warning_at (loc, OPT_Walloc_size_larger_than_,
    2361              :                                    "argument %i value %qE exceeds "
    2362              :                                    "maximum object size %E",
    2363           84 :                                    idx[i] + 1, args[i], maxobjsize);
    2364              :             }
    2365              :         }
    2366        37121 :       else if (TREE_CODE (args[i]) == SSA_NAME
    2367        37121 :                && get_size_range (args[i], argrange[i]))
    2368              :         {
    2369              :           /* Verify that the argument's range is not negative (including
    2370              :              upper bound of zero).  */
    2371        37108 :           if (tree_int_cst_lt (argrange[i][0], integer_zero_node)
    2372        37108 :               && tree_int_cst_le (argrange[i][1], integer_zero_node))
    2373              :             {
    2374           31 :               warned = warning_at (loc, OPT_Walloc_size_larger_than_,
    2375              :                                    "argument %i range [%E, %E] is negative",
    2376           31 :                                    idx[i] + 1,
    2377              :                                    argrange[i][0], argrange[i][1]);
    2378              :             }
    2379        37077 :           else if (tree_int_cst_lt (maxobjsize, argrange[i][0]))
    2380              :             {
    2381           33 :               warned = warning_at (loc, OPT_Walloc_size_larger_than_,
    2382              :                                    "argument %i range [%E, %E] exceeds "
    2383              :                                    "maximum object size %E",
    2384           33 :                                    idx[i] + 1,
    2385              :                                    argrange[i][0], argrange[i][1],
    2386              :                                    maxobjsize);
    2387              :             }
    2388              :         }
    2389              :     }
    2390              : 
    2391        74326 :   if (!argrange[0][0])
    2392           10 :     return;
    2393              : 
    2394              :   /* For a two-argument alloc_size, validate the product of the two
    2395              :      arguments if both of their values or ranges are known.  */
    2396        74093 :   if (!warned && tree_fits_uhwi_p (argrange[0][0])
    2397        74060 :       && argrange[1][0] && tree_fits_uhwi_p (argrange[1][0])
    2398         1183 :       && !integer_onep (argrange[0][0])
    2399        75162 :       && !integer_onep (argrange[1][0]))
    2400              :     {
    2401              :       /* Check for overflow in the product of a function decorated with
    2402              :          attribute alloc_size (X, Y).  */
    2403          445 :       unsigned szprec = TYPE_PRECISION (size_type_node);
    2404          445 :       wide_int x = wi::to_wide (argrange[0][0], szprec);
    2405          445 :       wide_int y = wi::to_wide (argrange[1][0], szprec);
    2406              : 
    2407          445 :       wi::overflow_type vflow;
    2408          445 :       wide_int prod = wi::umul (x, y, &vflow);
    2409              : 
    2410          445 :       if (vflow)
    2411            4 :         warned = warning_at (loc, OPT_Walloc_size_larger_than_,
    2412              :                              "product %<%E * %E%> of arguments %i and %i "
    2413              :                              "exceeds %<SIZE_MAX%>",
    2414              :                              argrange[0][0], argrange[1][0],
    2415            4 :                              idx[0] + 1, idx[1] + 1);
    2416          441 :       else if (wi::ltu_p (wi::to_wide (maxobjsize, szprec), prod))
    2417           14 :         warned = warning_at (loc, OPT_Walloc_size_larger_than_,
    2418              :                              "product %<%E * %E%> of arguments %i and %i "
    2419              :                              "exceeds maximum object size %E",
    2420              :                              argrange[0][0], argrange[1][0],
    2421           14 :                              idx[0] + 1, idx[1] + 1,
    2422              :                              maxobjsize);
    2423              : 
    2424          445 :       if (warned)
    2425              :         {
    2426              :           /* Print the full range of each of the two arguments to make
    2427              :              it clear when it is, in fact, in a range and not constant.  */
    2428           16 :           if (argrange[0][0] != argrange [0][1])
    2429            1 :             inform (loc, "argument %i in the range [%E, %E]",
    2430            1 :                     idx[0] + 1, argrange[0][0], argrange[0][1]);
    2431           16 :           if (argrange[1][0] != argrange [1][1])
    2432            1 :             inform (loc, "argument %i in the range [%E, %E]",
    2433            1 :                     idx[1] + 1, argrange[1][0], argrange[1][1]);
    2434              :         }
    2435          445 :     }
    2436              : 
    2437        74316 :   if (warned && fn)
    2438              :     {
    2439          214 :       location_t fnloc = DECL_SOURCE_LOCATION (fn);
    2440              : 
    2441          214 :       if (DECL_IS_UNDECLARED_BUILTIN (fn))
    2442           64 :         inform (loc,
    2443              :                 "in a call to built-in allocation function %qD", fn);
    2444              :       else
    2445          150 :         inform (fnloc,
    2446              :                 "in a call to allocation function %qD declared here", fn);
    2447              :     }
    2448              : }
    2449              : 
    2450              : /* Check a call to an alloca function for an excessive size.  */
    2451              : 
    2452              : void
    2453        31277 : pass_waccess::check_alloca (gcall *stmt)
    2454              : {
    2455        31277 :   if (m_early_checks_p)
    2456              :     return;
    2457              : 
    2458        14526 :   if ((warn_vla_limit >= HOST_WIDE_INT_MAX
    2459        14499 :        && warn_alloc_size_limit < warn_vla_limit)
    2460        14516 :       || (warn_alloca_limit >= HOST_WIDE_INT_MAX
    2461        14453 :           && warn_alloc_size_limit < warn_alloca_limit))
    2462              :     {
    2463              :       /* -Walloca-larger-than and -Wvla-larger-than settings of less
    2464              :          than  HWI_MAX override the more general -Walloc-size-larger-than
    2465              :          so unless either of the former options is smaller than the last
    2466              :          one (which would imply that the call was already checked), check
    2467              :          the alloca arguments for overflow.  */
    2468           10 :       const tree alloc_args[] = { call_arg (stmt, 0), NULL_TREE };
    2469           10 :       const int idx[] = { 0, -1 };
    2470           10 :       maybe_warn_alloc_args_overflow (stmt, alloc_args, idx);
    2471              :     }
    2472              : }
    2473              : 
    2474              : /* Check a call to an allocation function for an excessive size.  */
    2475              : 
    2476              : void
    2477      2967763 : pass_waccess::check_alloc_size_call (gcall *stmt)
    2478              : {
    2479      2967763 :   if (m_early_checks_p)
    2480      2893447 :     return;
    2481              : 
    2482      1418088 :   if (gimple_call_num_args (stmt) < 1)
    2483              :     /* Avoid invalid calls to functions without a prototype.  */
    2484              :     return;
    2485              : 
    2486      1181043 :   tree fndecl = gimple_call_fndecl (stmt);
    2487      1181043 :   if (fndecl && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
    2488              :     {
    2489              :       /* Alloca is handled separately.  */
    2490       566976 :       switch (DECL_FUNCTION_CODE (fndecl))
    2491              :         {
    2492              :         case BUILT_IN_ALLOCA:
    2493              :         case BUILT_IN_ALLOCA_WITH_ALIGN:
    2494              :         case BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX:
    2495              :           return;
    2496              :         default:
    2497              :           break;
    2498              :         }
    2499              :     }
    2500              : 
    2501      1171868 :   tree fntype = gimple_call_fntype (stmt);
    2502      1171868 :   tree fntypeattrs = TYPE_ATTRIBUTES (fntype);
    2503              : 
    2504      1171868 :   tree alloc_size = lookup_attribute ("alloc_size", fntypeattrs);
    2505      1171868 :   if (!alloc_size)
    2506              :     return;
    2507              : 
    2508              :   /* Extract attribute alloc_size from the type of the called expression
    2509              :      (which could be a function or a function pointer) and if set, store
    2510              :      the indices of the corresponding arguments in ALLOC_IDX, and then
    2511              :      the actual argument(s) at those indices in ALLOC_ARGS.  */
    2512        74321 :   int idx[2] = { -1, -1 };
    2513        74321 :   tree alloc_args[] = { NULL_TREE, NULL_TREE };
    2514        74321 :   unsigned nargs = gimple_call_num_args (stmt);
    2515              : 
    2516        74321 :   tree args = TREE_VALUE (alloc_size);
    2517        74321 :   idx[0] = TREE_INT_CST_LOW (TREE_VALUE (args)) - 1;
    2518              :   /* Avoid invalid calls to functions without a prototype.  */
    2519        74321 :   if ((unsigned) idx[0] >= nargs)
    2520              :     return;
    2521        74316 :   alloc_args[0] = call_arg (stmt, idx[0]);
    2522        74316 :   if (TREE_CHAIN (args))
    2523              :     {
    2524         1283 :       idx[1] = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (args))) - 1;
    2525         1283 :       if ((unsigned) idx[1] >= nargs)
    2526              :         return;
    2527         1283 :       alloc_args[1] = call_arg (stmt, idx[1]);
    2528              :     }
    2529              : 
    2530        74316 :   maybe_warn_alloc_args_overflow (stmt, alloc_args, idx);
    2531              : }
    2532              : 
    2533              : /* Check a call STMT to strcat() for overflow and warn if it does.  */
    2534              : 
    2535              : void
    2536         1657 : pass_waccess::check_strcat (gcall *stmt)
    2537              : {
    2538         1657 :   if (m_early_checks_p)
    2539          938 :     return;
    2540              : 
    2541          719 :   if (!warn_stringop_overflow && !warn_stringop_overread)
    2542              :     return;
    2543              : 
    2544          719 :   tree dest = call_arg (stmt, 0);
    2545          719 :   tree src = call_arg (stmt, 1);
    2546              : 
    2547              :   /* There is no way here to determine the length of the string in
    2548              :      the destination to which the SRC string is being appended so
    2549              :      just diagnose cases when the source string is longer than
    2550              :      the destination object.  */
    2551          719 :   access_data data (m_ptr_qry.rvals, stmt, access_read_write, NULL_TREE,
    2552          719 :                     true, NULL_TREE, true);
    2553          719 :   const int ost = warn_stringop_overflow ? warn_stringop_overflow - 1 : 1;
    2554          719 :   compute_objsize (src, stmt, ost, &data.src, &m_ptr_qry);
    2555          719 :   tree destsize = compute_objsize (dest, stmt, ost, &data.dst, &m_ptr_qry);
    2556              : 
    2557          719 :   check_access (stmt, /*dstwrite=*/NULL_TREE, /*maxread=*/NULL_TREE,
    2558              :                 src, destsize, data.mode, &data, m_ptr_qry.rvals);
    2559              : }
    2560              : 
    2561              : /* Check a call STMT to strcat() for overflow and warn if it does.  */
    2562              : 
    2563              : void
    2564         1667 : pass_waccess::check_strncat (gcall *stmt)
    2565              : {
    2566         1667 :   if (m_early_checks_p)
    2567          867 :     return;
    2568              : 
    2569          842 :   if (!warn_stringop_overflow && !warn_stringop_overread)
    2570              :     return;
    2571              : 
    2572          823 :   tree dest = call_arg (stmt, 0);
    2573          823 :   tree src = call_arg (stmt, 1);
    2574              :   /* The upper bound on the number of bytes to write.  */
    2575          823 :   tree maxread = call_arg (stmt, 2);
    2576              : 
    2577              :   /* Detect unterminated source (only).  */
    2578          823 :   if (!check_nul_terminated_array (stmt, src, maxread))
    2579              :     return;
    2580              : 
    2581              :   /* The length of the source sequence.  */
    2582          817 :   tree slen = c_strlen (src, 1);
    2583              : 
    2584              :   /* Try to determine the range of lengths that the source expression
    2585              :      refers to.  Since the lengths are only used for warning and not
    2586              :      for code generation disable strict mode below.  */
    2587          817 :   tree maxlen = slen;
    2588          817 :   if (!maxlen)
    2589              :     {
    2590          710 :       c_strlen_data lendata = { };
    2591          710 :       get_range_strlen (src, &lendata, /* eltsize = */ 1);
    2592          710 :       maxlen = lendata.maxbound;
    2593              :     }
    2594              : 
    2595          817 :   access_data data (m_ptr_qry.rvals, stmt, access_read_write);
    2596              :   /* Try to verify that the destination is big enough for the shortest
    2597              :      string.  First try to determine the size of the destination object
    2598              :      into which the source is being copied.  */
    2599          817 :   const int ost = warn_stringop_overflow - 1;
    2600          817 :   tree destsize = compute_objsize (dest, stmt, ost, &data.dst, &m_ptr_qry);
    2601              : 
    2602              :   /* Add one for the terminating nul.  */
    2603          817 :   tree srclen = (maxlen
    2604          817 :                  ? fold_build2 (PLUS_EXPR, size_type_node, maxlen,
    2605              :                                 size_one_node)
    2606              :                  : NULL_TREE);
    2607              : 
    2608              :   /* The strncat function copies at most MAXREAD bytes and always appends
    2609              :      the terminating nul so the specified upper bound should never be equal
    2610              :      to (or greater than) the size of the destination.  */
    2611          324 :   if (tree_fits_uhwi_p (maxread) && tree_fits_uhwi_p (destsize)
    2612         1141 :       && tree_int_cst_equal (destsize, maxread))
    2613              :     {
    2614           17 :       location_t loc = get_location (stmt);
    2615           17 :       rich_location_with_details richloc (loc, stmt);
    2616              : 
    2617           17 :       warning_at (&richloc, OPT_Wstringop_overflow_,
    2618              :                   "%qD specified bound %E equals destination size",
    2619              :                   get_callee_fndecl (stmt), maxread);
    2620              : 
    2621           17 :       return;
    2622           17 :     }
    2623              : 
    2624          800 :   if (!srclen
    2625          800 :       || (maxread && tree_fits_uhwi_p (maxread)
    2626          237 :           && tree_fits_uhwi_p (srclen)
    2627          237 :           && tree_int_cst_lt (maxread, srclen)))
    2628              :     srclen = maxread;
    2629              : 
    2630          800 :   check_access (stmt, /*dstwrite=*/NULL_TREE, maxread, srclen,
    2631              :                 destsize, data.mode, &data, m_ptr_qry.rvals);
    2632              : }
    2633              : 
    2634              : /* Check a call STMT to stpcpy() or strcpy() for overflow and warn
    2635              :    if it does.  */
    2636              : 
    2637              : void
    2638         7225 : pass_waccess::check_stxcpy (gcall *stmt)
    2639              : {
    2640         7225 :   if (m_early_checks_p)
    2641         4399 :     return;
    2642              : 
    2643         2968 :   tree dst = call_arg (stmt, 0);
    2644         2968 :   tree src = call_arg (stmt, 1);
    2645              : 
    2646         2968 :   tree size;
    2647         2968 :   bool exact;
    2648         2968 :   if (tree nonstr = unterminated_array (src, &size, &exact))
    2649              :     {
    2650              :       /* NONSTR refers to the non-nul terminated constant array.  */
    2651          142 :       warn_string_no_nul (get_location (stmt), stmt, NULL, src, nonstr,
    2652              :                           size, exact);
    2653          142 :       return;
    2654              :     }
    2655              : 
    2656         2826 :   if (warn_stringop_overflow)
    2657              :     {
    2658         2621 :       access_data data (m_ptr_qry.rvals, stmt, access_read_write, NULL_TREE,
    2659         2621 :                         true, NULL_TREE, true);
    2660         2621 :       const int ost = warn_stringop_overflow ? warn_stringop_overflow - 1 : 1;
    2661         2621 :       compute_objsize (src, stmt, ost, &data.src, &m_ptr_qry);
    2662         2621 :       tree dstsize = compute_objsize (dst, stmt, ost, &data.dst, &m_ptr_qry);
    2663         2621 :       check_access (stmt, /*dstwrite=*/ NULL_TREE,
    2664              :                     /*maxread=*/ NULL_TREE, /*srcstr=*/ src,
    2665              :                     dstsize, data.mode, &data, m_ptr_qry.rvals);
    2666              :     }
    2667              : 
    2668              :   /* Check to see if the argument was declared attribute nonstring
    2669              :      and if so, issue a warning since at this point it's not known
    2670              :      to be nul-terminated.  */
    2671         2826 :   tree fndecl = get_callee_fndecl (stmt);
    2672         2826 :   maybe_warn_nonstring_arg (fndecl, stmt);
    2673              : }
    2674              : 
    2675              : /* Check a call STMT to stpncpy() or strncpy() for overflow and warn
    2676              :    if it does.  */
    2677              : 
    2678              : void
    2679         5890 : pass_waccess::check_stxncpy (gcall *stmt)
    2680              : {
    2681         5890 :   if (m_early_checks_p || !warn_stringop_overflow)
    2682         3304 :     return;
    2683              : 
    2684         2586 :   tree dst = call_arg (stmt, 0);
    2685         2586 :   tree src = call_arg (stmt, 1);
    2686              :   /* The number of bytes to write (not the maximum).  */
    2687         2586 :   tree len = call_arg (stmt, 2);
    2688              : 
    2689         2586 :   access_data data (m_ptr_qry.rvals, stmt, access_read_write, len, true, len,
    2690         2586 :                     true);
    2691         2586 :   const int ost = warn_stringop_overflow ? warn_stringop_overflow - 1 : 1;
    2692         2586 :   compute_objsize (src, stmt, ost, &data.src, &m_ptr_qry);
    2693         2586 :   tree dstsize = compute_objsize (dst, stmt, ost, &data.dst, &m_ptr_qry);
    2694              : 
    2695         2586 :   check_access (stmt, /*dstwrite=*/len, /*maxread=*/len, src, dstsize,
    2696              :                 data.mode, &data, m_ptr_qry.rvals);
    2697              : }
    2698              : 
    2699              : /* Check a call STMT to stpncpy() or strncpy() for overflow and warn
    2700              :    if it does.  */
    2701              : 
    2702              : void
    2703         6070 : pass_waccess::check_strncmp (gcall *stmt)
    2704              : {
    2705         6070 :   if (m_early_checks_p || !warn_stringop_overread)
    2706         3974 :     return;
    2707              : 
    2708         2844 :   tree arg1 = call_arg (stmt, 0);
    2709         2844 :   tree arg2 = call_arg (stmt, 1);
    2710         2844 :   tree bound = call_arg (stmt, 2);
    2711              : 
    2712              :   /* First check each argument separately, considering the bound.  */
    2713         2844 :   if (!check_nul_terminated_array (stmt, arg1, bound)
    2714         2844 :       || !check_nul_terminated_array (stmt, arg2, bound))
    2715            6 :     return;
    2716              : 
    2717              :   /* A strncmp read from each argument is constrained not just by
    2718              :      the bound but also by the length of the shorter string.  Specifying
    2719              :      a bound that's larger than the size of either array makes no sense
    2720              :      and is likely a bug.  When the length of neither of the two strings
    2721              :      is known but the sizes of both of the arrays they are stored in is,
    2722              :      issue a warning if the bound is larger than the size of
    2723              :      the larger of the two arrays.  */
    2724              : 
    2725         2838 :   c_strlen_data lendata1{ }, lendata2{ };
    2726         2838 :   tree len1 = c_strlen (arg1, 1, &lendata1);
    2727         2838 :   tree len2 = c_strlen (arg2, 1, &lendata2);
    2728              : 
    2729         2838 :   if (len1 && TREE_CODE (len1) != INTEGER_CST)
    2730         2571 :     len1 = NULL_TREE;
    2731         2838 :   if (len2 && TREE_CODE (len2) != INTEGER_CST)
    2732         1563 :     len2 = NULL_TREE;
    2733              : 
    2734         2838 :   if (len1 && len2)
    2735              :     /* If the length of both arguments was computed they must both be
    2736              :        nul-terminated and no further checking is necessary regardless
    2737              :        of the bound.  */
    2738              :     return;
    2739              : 
    2740              :   /* Check to see if the argument was declared with attribute nonstring
    2741              :      and if so, issue a warning since at this point it's not known to be
    2742              :      nul-terminated.  */
    2743         2721 :   if (maybe_warn_nonstring_arg (get_callee_fndecl (stmt), stmt))
    2744              :     return;
    2745              : 
    2746         2548 :   access_data adata1 (m_ptr_qry.rvals, stmt, access_read_only, NULL_TREE, false,
    2747         2548 :                       bound, true);
    2748         2548 :   access_data adata2 (m_ptr_qry.rvals, stmt, access_read_only, NULL_TREE, false,
    2749         2548 :                       bound, true);
    2750              : 
    2751              :   /* Determine the range of the bound first and bail if it fails; it's
    2752              :      cheaper than computing the size of the objects.  */
    2753         2548 :   tree bndrng[2] = { NULL_TREE, NULL_TREE };
    2754         2548 :   get_size_range (m_ptr_qry.rvals, bound, stmt, bndrng, 0, adata1.src_bndrng);
    2755         2548 :   if (!bndrng[0] || integer_zerop (bndrng[0]))
    2756          452 :     return;
    2757              : 
    2758         2096 :   if (len1 && tree_int_cst_lt (len1, bndrng[0]))
    2759           20 :     bndrng[0] = len1;
    2760         2096 :   if (len2 && tree_int_cst_lt (len2, bndrng[0]))
    2761           54 :     bndrng[0] = len2;
    2762              : 
    2763              :   /* compute_objsize almost never fails (and ultimately should never
    2764              :      fail).  Don't bother to handle the rare case when it does.  */
    2765         2096 :   if (!compute_objsize (arg1, stmt, 1, &adata1.src, &m_ptr_qry)
    2766         2096 :       || !compute_objsize (arg2, stmt, 1, &adata2.src, &m_ptr_qry))
    2767            0 :     return;
    2768              : 
    2769              :   /* Compute the size of the remaining space in each array after
    2770              :      subtracting any offset into it.  */
    2771         2096 :   offset_int rem1 = adata1.src.size_remaining ();
    2772         2096 :   offset_int rem2 = adata2.src.size_remaining ();
    2773              : 
    2774              :   /* Cap REM1 and REM2 at the other if the other's argument is known
    2775              :      to be an unterminated array, either because there's no space
    2776              :      left in it after adding its offset or because it's constant and
    2777              :      has no nul.  */
    2778         4189 :   if (rem1 == 0 || (rem1 < rem2 && lendata1.decl))
    2779            5 :     rem2 = rem1;
    2780         4181 :   else if (rem2 == 0 || (rem2 < rem1 && lendata2.decl))
    2781            3 :     rem1 = rem2;
    2782              : 
    2783              :   /* Point PAD at the array to reference in the note if a warning
    2784              :      is issued.  */
    2785         2096 :   access_data *pad = len1 ? &adata2 : &adata1;
    2786         2096 :   offset_int maxrem = wi::max (rem1, rem2, UNSIGNED);
    2787         2094 :   if (lendata1.decl || lendata2.decl
    2788         4188 :       || maxrem < wi::to_offset (bndrng[0]))
    2789              :     {
    2790              :       /* Warn when either argument isn't nul-terminated or the maximum
    2791              :          remaining space in the two arrays is less than the bound.  */
    2792           21 :       tree func = get_callee_fndecl (stmt);
    2793           21 :       location_t loc = gimple_location (stmt);
    2794           42 :       maybe_warn_for_bound (OPT_Wstringop_overread, loc, stmt, func,
    2795           42 :                             bndrng, wide_int_to_tree (sizetype, maxrem),
    2796              :                             pad);
    2797              :     }
    2798              : }
    2799              : 
    2800              : /* Determine and check the sizes of the source and the destination
    2801              :    of calls to __builtin_{bzero,memcpy,mempcpy,memset} calls.  STMT is
    2802              :    the call statement, DEST is the destination argument, SRC is the source
    2803              :    argument or null, and SIZE is the number of bytes being accessed.  Use
    2804              :    Object Size type-0 regardless of the OPT_Wstringop_overflow_ setting.
    2805              :    Return true on success (no overflow or invalid sizes), false otherwise.  */
    2806              : 
    2807              : void
    2808       627977 : pass_waccess::check_memop_access (gimple *stmt, tree dest, tree src, tree size)
    2809              : {
    2810       627977 :   if (m_early_checks_p)
    2811       279374 :     return;
    2812              : 
    2813              :   /* For functions like memset and memcpy that operate on raw memory
    2814              :      try to determine the size of the largest source and destination
    2815              :      object using type-0 Object Size regardless of the object size
    2816              :      type specified by the option.  */
    2817       348603 :   access_data data (m_ptr_qry.rvals, stmt, access_read_write);
    2818       348603 :   tree srcsize
    2819       348603 :     = src ? compute_objsize (src, stmt, 0, &data.src, &m_ptr_qry) : NULL_TREE;
    2820       348603 :   tree dstsize = compute_objsize (dest, stmt, 0, &data.dst, &m_ptr_qry);
    2821              : 
    2822       348603 :   check_access (stmt, size, /*maxread=*/NULL_TREE, srcsize, dstsize,
    2823              :                 data.mode, &data, m_ptr_qry.rvals);
    2824              : }
    2825              : 
    2826              : /* A convenience wrapper for check_access to check access by a read-only
    2827              :    function like puts or strcmp.  */
    2828              : 
    2829              : void
    2830       843345 : pass_waccess::check_read_access (gimple *stmt, tree src,
    2831              :                                  tree bound /* = NULL_TREE */,
    2832              :                                  int ost /* = 1 */)
    2833              : {
    2834       843345 :   if (m_early_checks_p || !warn_stringop_overread)
    2835       521154 :     return;
    2836              : 
    2837       322191 :   if (bound && !useless_type_conversion_p (size_type_node, TREE_TYPE (bound)))
    2838            0 :     bound = fold_convert (size_type_node, bound);
    2839              : 
    2840       322191 :   tree fndecl = get_callee_fndecl (stmt);
    2841       322191 :   maybe_warn_nonstring_arg (fndecl, stmt);
    2842              : 
    2843       322191 :   access_data data (m_ptr_qry.rvals, stmt, access_read_only, NULL_TREE,
    2844       322191 :                    false, bound, true);
    2845       322191 :   compute_objsize (src, stmt, ost, &data.src, &m_ptr_qry);
    2846       322191 :   check_access (stmt, /*dstwrite=*/ NULL_TREE, /*maxread=*/ bound,
    2847              :                 /*srcstr=*/ src, /*dstsize=*/ NULL_TREE, data.mode,
    2848              :                 &data, m_ptr_qry.rvals);
    2849              : }
    2850              : 
    2851              : /* Return true if memory model ORD is constant in the context of STMT and
    2852              :    set *CSTVAL to the constant value.  Otherwise return false.  Warn for
    2853              :    invalid ORD.  */
    2854              : 
    2855              : bool
    2856       242239 : memmodel_to_uhwi (tree ord, gimple *stmt, unsigned HOST_WIDE_INT *cstval)
    2857              : {
    2858       242239 :   unsigned HOST_WIDE_INT val;
    2859              : 
    2860       242239 :   if (TREE_CODE (ord) == INTEGER_CST)
    2861              :     {
    2862       239485 :       if (!tree_fits_uhwi_p (ord))
    2863              :         return false;
    2864       239477 :       val = tree_to_uhwi (ord);
    2865              :     }
    2866              :   else
    2867              :     {
    2868              :       /* Use the range query to determine constant values in the absence
    2869              :          of constant propagation (such as at -O0).  */
    2870         2754 :       int_range_max rng (TREE_TYPE (ord));
    2871         5508 :       if (!get_range_query (cfun)->range_of_expr (rng, ord, stmt)
    2872         2754 :           || !rng.singleton_p (&ord))
    2873         2304 :         return false;
    2874              : 
    2875          450 :       wide_int lob = rng.lower_bound ();
    2876          450 :       if (!wi::fits_uhwi_p (lob))
    2877            0 :         return false;
    2878              : 
    2879          450 :       val = lob.to_shwi ();
    2880         2754 :     }
    2881              : 
    2882       239927 :   if (targetm.memmodel_check)
    2883              :     /* This might warn for an invalid VAL but return a conservatively
    2884              :        valid result.  */
    2885       239927 :     val = targetm.memmodel_check (val);
    2886            0 :   else if (val & ~MEMMODEL_MASK)
    2887              :     {
    2888            0 :       tree fndecl = gimple_call_fndecl (stmt);
    2889            0 :       location_t loc = gimple_location (stmt);
    2890            0 :       loc = expansion_point_location_if_in_system_header (loc);
    2891              : 
    2892            0 :       warning_at (loc, OPT_Winvalid_memory_model,
    2893              :                   "unknown architecture specifier in memory model "
    2894              :                   "%wi for %qD", val, fndecl);
    2895            0 :       return false;
    2896              :     }
    2897              : 
    2898       239927 :   *cstval = val;
    2899              : 
    2900       239927 :   return true;
    2901              : }
    2902              : 
    2903              : /* Valid memory model for each set of atomic built-in functions.  */
    2904              : 
    2905              : struct memmodel_pair
    2906              : {
    2907              :   memmodel modval;
    2908              :   const char* modname;
    2909              : 
    2910              : #define MEMMODEL_PAIR(val, str)                 \
    2911              :   { MEMMODEL_ ## val, "memory_order_" str }
    2912              : };
    2913              : 
    2914              : /* Valid memory models in the order of increasing strength.  */
    2915              : 
    2916              : static const memmodel_pair memory_models[] =
    2917              :   { MEMMODEL_PAIR (RELAXED, "relaxed"),
    2918              :     MEMMODEL_PAIR (SEQ_CST, "seq_cst"),
    2919              :     MEMMODEL_PAIR (ACQUIRE, "acquire"),
    2920              :     MEMMODEL_PAIR (CONSUME, "consume"),
    2921              :     MEMMODEL_PAIR (RELEASE, "release"),
    2922              :     MEMMODEL_PAIR (ACQ_REL, "acq_rel")
    2923              :   };
    2924              : 
    2925              : /* Return the name of the memory model VAL.  */
    2926              : 
    2927              : static const char*
    2928          230 : memmodel_name (unsigned HOST_WIDE_INT val)
    2929              : {
    2930          230 :   val = memmodel_base (val);
    2931              : 
    2932          988 :   for (unsigned i = 0; i != ARRAY_SIZE (memory_models); ++i)
    2933              :     {
    2934          971 :       if (val == memory_models[i].modval)
    2935          213 :         return memory_models[i].modname;
    2936              :     }
    2937              :   return NULL;
    2938              : }
    2939              : 
    2940              : /* Indices of valid MEMORY_MODELS above for corresponding atomic operations.  */
    2941              : static const unsigned char load_models[] = { 0, 1, 2, 3, UCHAR_MAX };
    2942              : static const unsigned char store_models[] = { 0, 1, 4, UCHAR_MAX };
    2943              : static const unsigned char xchg_models[] = { 0, 1, 3, 4, 5, UCHAR_MAX };
    2944              : static const unsigned char flag_clr_models[] = { 0, 1, 4, UCHAR_MAX };
    2945              : static const unsigned char all_models[] = { 0, 1, 2, 3, 4, 5, UCHAR_MAX };
    2946              : 
    2947              : /* Check the success memory model argument ORD_SUCS to the call STMT to
    2948              :    an atomic function and warn if it's invalid.  If nonnull, also check
    2949              :    the failure memory model ORD_FAIL and warn if it's invalid.  Return
    2950              :    true if a warning has been issued.  */
    2951              : 
    2952              : bool
    2953       219684 : pass_waccess::maybe_warn_memmodel (gimple *stmt, tree ord_sucs,
    2954              :                                    tree ord_fail, const unsigned char *valid)
    2955              : {
    2956       219684 :   unsigned HOST_WIDE_INT sucs, fail = 0;
    2957       219684 :   if (!memmodel_to_uhwi (ord_sucs, stmt, &sucs)
    2958       219684 :       || (ord_fail && !memmodel_to_uhwi (ord_fail, stmt, &fail)))
    2959         2312 :     return false;
    2960              : 
    2961       217372 :   bool is_valid = false;
    2962       217372 :   if (valid)
    2963       457734 :     for (unsigned i = 0; valid[i] != UCHAR_MAX; ++i)
    2964              :       {
    2965       457652 :         memmodel model = memory_models[valid[i]].modval;
    2966       457652 :         if (memmodel_base (sucs) == model)
    2967              :           {
    2968              :             is_valid = true;
    2969              :             break;
    2970              :           }
    2971              :       }
    2972              :   else
    2973              :     is_valid = true;
    2974              : 
    2975       217372 :   tree fndecl = gimple_call_fndecl (stmt);
    2976       217372 :   location_t loc = gimple_location (stmt);
    2977       217372 :   loc = expansion_point_location_if_in_system_header (loc);
    2978              : 
    2979       217372 :   if (!is_valid)
    2980              :     {
    2981           82 :       bool warned = false;
    2982           82 :       auto_diagnostic_group d;
    2983           82 :       if (const char *modname = memmodel_name (sucs))
    2984           65 :         warned = warning_at (loc, OPT_Winvalid_memory_model,
    2985              :                              "invalid memory model %qs for %qD",
    2986              :                              modname, fndecl);
    2987              :       else
    2988           17 :         warned = warning_at (loc, OPT_Winvalid_memory_model,
    2989              :                              "invalid memory model %wi for %qD",
    2990              :                              sucs, fndecl);
    2991              : 
    2992           82 :       if (!warned)
    2993              :         return false;
    2994              : 
    2995              :       /* Print a note with the valid memory models.  */
    2996           82 :       auto_vec<const char *> strings;
    2997          401 :       for (unsigned i = 0; valid[i] != UCHAR_MAX; ++i)
    2998              :         {
    2999          319 :           const char *modname = memory_models[valid[i]].modname;
    3000          319 :           strings.safe_push (modname);
    3001              :         }
    3002           82 :       pp_markup::comma_separated_quoted_strings e (strings);
    3003           82 :       inform (loc, "valid models are %e", &e);
    3004           82 :       return true;
    3005           82 :     }
    3006              : 
    3007       217290 :   if (!ord_fail)
    3008              :     return false;
    3009              : 
    3010        22543 :   if (fail == MEMMODEL_RELEASE || fail == MEMMODEL_ACQ_REL)
    3011           60 :     if (const char *failname = memmodel_name (fail))
    3012              :       {
    3013              :         /* If both memory model arguments are valid but their combination
    3014              :            is not, use their names in the warning.  */
    3015           60 :         auto_diagnostic_group d;
    3016           60 :         if (!warning_at (loc, OPT_Winvalid_memory_model,
    3017              :                          "invalid failure memory model %qs for %qD",
    3018              :                          failname, fndecl))
    3019              :           return false;
    3020              : 
    3021           60 :         inform (loc,
    3022              :                 "valid failure models are %qs, %qs, %qs, %qs",
    3023              :                 "memory_order_relaxed", "memory_order_seq_cst",
    3024              :                 "memory_order_acquire", "memory_order_consume");
    3025           60 :         return true;
    3026           60 :       }
    3027              : 
    3028        22483 :   if (memmodel_base (fail) <= memmodel_base (sucs))
    3029              :     return false;
    3030              : 
    3031           44 :   if (const char *sucsname = memmodel_name (sucs))
    3032           44 :     if (const char *failname = memmodel_name (fail))
    3033              :       {
    3034              :         /* If both memory model arguments are valid but their combination
    3035              :            is not, use their names in the warning.  */
    3036           44 :         auto_diagnostic_group d;
    3037           44 :         if (!warning_at (loc, OPT_Winvalid_memory_model,
    3038              :                          "failure memory model %qs cannot be stronger "
    3039              :                          "than success memory model %qs for %qD",
    3040              :                          failname, sucsname, fndecl))
    3041              :           return false;
    3042              : 
    3043              :         /* Print a note with the valid failure memory models which are
    3044              :            those with a value less than or equal to the success mode.  */
    3045           44 :         auto_vec<const char *> strings;
    3046           88 :         for (unsigned i = 0;
    3047           88 :              memory_models[i].modval <= memmodel_base (sucs); ++i)
    3048              :           {
    3049           44 :             const char *modname = memory_models[valid[i]].modname;
    3050           44 :             strings.safe_push (modname);
    3051              :           }
    3052           44 :         pp_markup::comma_separated_quoted_strings e (strings);
    3053              : 
    3054           44 :         inform (loc, "valid models are %e", &e);
    3055           44 :         return true;
    3056           44 :       }
    3057              : 
    3058              :   /* If either memory model argument value is invalid use the numerical
    3059              :      value of both in the message.  */
    3060            0 :   return warning_at (loc, OPT_Winvalid_memory_model,
    3061              :                      "failure memory model %wi cannot be stronger "
    3062              :                      "than success memory model %wi for %qD",
    3063              :                      fail, sucs, fndecl);
    3064              : }
    3065              : 
    3066              : /* Wrapper for the above.  */
    3067              : 
    3068              : void
    3069       219711 : pass_waccess::check_atomic_memmodel (gimple *stmt, tree ord_sucs,
    3070              :                                      tree ord_fail, const unsigned char *valid)
    3071              : {
    3072       219711 :   if (warning_suppressed_p (stmt, OPT_Winvalid_memory_model))
    3073              :     return;
    3074              : 
    3075       219684 :   if (!maybe_warn_memmodel (stmt, ord_sucs, ord_fail, valid))
    3076              :     return;
    3077              : 
    3078          186 :   suppress_warning (stmt, OPT_Winvalid_memory_model);
    3079              : }
    3080              : 
    3081              : /* Check a call STMT to an atomic or sync built-in.  */
    3082              : 
    3083              : bool
    3084      2539067 : pass_waccess::check_atomic_builtin (gcall *stmt)
    3085              : {
    3086      2539067 :   tree callee = gimple_call_fndecl (stmt);
    3087      2539067 :   if (!callee)
    3088              :     return false;
    3089              : 
    3090              :   /* The size in bytes of the access by the function, and the number
    3091              :      of the second argument to check (if any).  */
    3092      2539067 :   unsigned bytes = 0, arg2 = UINT_MAX;
    3093      2539067 :   unsigned sucs_arg = UINT_MAX, fail_arg = UINT_MAX;
    3094              :   /* Points to the array of indices of valid memory models.  */
    3095      2539067 :   const unsigned char *pvalid_models = NULL;
    3096              : 
    3097      2539067 :   switch (DECL_FUNCTION_CODE (callee))
    3098              :     {
    3099              : #define BUILTIN_ACCESS_SIZE_FNSPEC(N)                   \
    3100              :       BUILT_IN_SYNC_FETCH_AND_ADD_ ## N:                \
    3101              :     case BUILT_IN_SYNC_FETCH_AND_SUB_ ## N:             \
    3102              :     case BUILT_IN_SYNC_FETCH_AND_OR_ ## N:              \
    3103              :     case BUILT_IN_SYNC_FETCH_AND_AND_ ## N:             \
    3104              :     case BUILT_IN_SYNC_FETCH_AND_XOR_ ## N:             \
    3105              :     case BUILT_IN_SYNC_FETCH_AND_NAND_ ## N:            \
    3106              :     case BUILT_IN_SYNC_ADD_AND_FETCH_ ## N:             \
    3107              :     case BUILT_IN_SYNC_SUB_AND_FETCH_ ## N:             \
    3108              :     case BUILT_IN_SYNC_OR_AND_FETCH_ ## N:              \
    3109              :     case BUILT_IN_SYNC_AND_AND_FETCH_ ## N:             \
    3110              :     case BUILT_IN_SYNC_XOR_AND_FETCH_ ## N:             \
    3111              :     case BUILT_IN_SYNC_NAND_AND_FETCH_ ## N:            \
    3112              :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_ ## N:         \
    3113              :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_ ## N:     \
    3114              :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_ ## N:      \
    3115              :     case BUILT_IN_SYNC_LOCK_RELEASE_ ## N:              \
    3116              :       bytes = N;                                        \
    3117              :       break;                                            \
    3118              :     case BUILT_IN_ATOMIC_LOAD_ ## N:                    \
    3119              :       pvalid_models = load_models;                      \
    3120              :       sucs_arg = 1;                                     \
    3121              :       /* FALLTHROUGH */                                 \
    3122              :     case BUILT_IN_ATOMIC_STORE_ ## N:                   \
    3123              :       if (!pvalid_models)                               \
    3124              :         pvalid_models = store_models;                   \
    3125              :       /* FALLTHROUGH */                                 \
    3126              :     case BUILT_IN_ATOMIC_ADD_FETCH_ ## N:               \
    3127              :     case BUILT_IN_ATOMIC_SUB_FETCH_ ## N:               \
    3128              :     case BUILT_IN_ATOMIC_AND_FETCH_ ## N:               \
    3129              :     case BUILT_IN_ATOMIC_NAND_FETCH_ ## N:              \
    3130              :     case BUILT_IN_ATOMIC_XOR_FETCH_ ## N:               \
    3131              :     case BUILT_IN_ATOMIC_OR_FETCH_ ## N:                \
    3132              :     case BUILT_IN_ATOMIC_FETCH_ADD_ ## N:               \
    3133              :     case BUILT_IN_ATOMIC_FETCH_SUB_ ## N:               \
    3134              :     case BUILT_IN_ATOMIC_FETCH_AND_ ## N:               \
    3135              :     case BUILT_IN_ATOMIC_FETCH_NAND_ ## N:              \
    3136              :     case BUILT_IN_ATOMIC_FETCH_OR_ ## N:                \
    3137              :     case BUILT_IN_ATOMIC_FETCH_XOR_ ## N:               \
    3138              :         bytes = N;                                      \
    3139              :         if (sucs_arg == UINT_MAX)                       \
    3140              :           sucs_arg = 2;                                 \
    3141              :         if (!pvalid_models)                             \
    3142              :           pvalid_models = all_models;                   \
    3143              :         break;                                          \
    3144              :     case BUILT_IN_ATOMIC_EXCHANGE_ ## N:                \
    3145              :         bytes = N;                                      \
    3146              :         sucs_arg = 3;                                   \
    3147              :         pvalid_models = xchg_models;                    \
    3148              :         break;                                          \
    3149              :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_ ## N:        \
    3150              :         bytes = N;                                      \
    3151              :         sucs_arg = 4;                                   \
    3152              :         fail_arg = 5;                                   \
    3153              :         pvalid_models = all_models;                     \
    3154              :         arg2 = 1
    3155              : 
    3156        63300 :     case BUILTIN_ACCESS_SIZE_FNSPEC (1);
    3157         4820 :       break;
    3158        17051 :     case BUILTIN_ACCESS_SIZE_FNSPEC (2);
    3159         1813 :       break;
    3160        79515 :     case BUILTIN_ACCESS_SIZE_FNSPEC (4);
    3161         5656 :       break;
    3162        64784 :     case BUILTIN_ACCESS_SIZE_FNSPEC (8);
    3163         7212 :       break;
    3164        15087 :     case BUILTIN_ACCESS_SIZE_FNSPEC (16);
    3165         3438 :       break;
    3166              : 
    3167          104 :     case BUILT_IN_ATOMIC_CLEAR:
    3168          104 :       sucs_arg = 1;
    3169          104 :       pvalid_models = flag_clr_models;
    3170          104 :       break;
    3171              : 
    3172              :     default:
    3173              :       return false;
    3174              :     }
    3175              : 
    3176       233753 :   unsigned nargs = gimple_call_num_args (stmt);
    3177       233753 :   if (sucs_arg < nargs)
    3178              :     {
    3179       219711 :       tree ord_sucs = gimple_call_arg (stmt, sucs_arg);
    3180       219711 :       tree ord_fail = NULL_TREE;
    3181       219711 :       if (fail_arg < nargs)
    3182        22939 :         ord_fail = gimple_call_arg (stmt, fail_arg);
    3183       219711 :       check_atomic_memmodel (stmt, ord_sucs, ord_fail, pvalid_models);
    3184              :     }
    3185              : 
    3186       233753 :   if (!bytes)
    3187              :     return true;
    3188              : 
    3189       233649 :   tree size = build_int_cstu (sizetype, bytes);
    3190       233649 :   tree dst = gimple_call_arg (stmt, 0);
    3191       233649 :   check_memop_access (stmt, dst, NULL_TREE, size);
    3192              : 
    3193       233649 :   if (arg2 != UINT_MAX)
    3194              :     {
    3195        22939 :       tree dst = gimple_call_arg (stmt, arg2);
    3196        22939 :       check_memop_access (stmt, dst, NULL_TREE, size);
    3197              :     }
    3198              : 
    3199              :   return true;
    3200              : }
    3201              : 
    3202              : /* Check call STMT to a built-in function for invalid accesses.  Return
    3203              :    true if a call has been handled.  */
    3204              : 
    3205              : bool
    3206      3554216 : pass_waccess::check_builtin (gcall *stmt)
    3207              : {
    3208      3554216 :   tree callee = gimple_call_fndecl (stmt);
    3209      3554216 :   if (!callee)
    3210              :     return false;
    3211              : 
    3212      3554216 :   switch (DECL_FUNCTION_CODE (callee))
    3213              :     {
    3214        31277 :     case BUILT_IN_ALLOCA:
    3215        31277 :     case BUILT_IN_ALLOCA_WITH_ALIGN:
    3216        31277 :     case BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX:
    3217        31277 :       check_alloca (stmt);
    3218        31277 :       return true;
    3219              : 
    3220           62 :     case BUILT_IN_EXECL:
    3221           62 :     case BUILT_IN_EXECLE:
    3222           62 :     case BUILT_IN_EXECLP:
    3223           62 :     case BUILT_IN_EXECV:
    3224           62 :     case BUILT_IN_EXECVE:
    3225           62 :     case BUILT_IN_EXECVP:
    3226           62 :       check_read_access (stmt, call_arg (stmt, 0));
    3227           62 :       return true;
    3228              : 
    3229       140347 :     case BUILT_IN_FREE:
    3230       140347 :     case BUILT_IN_REALLOC:
    3231       140347 :       if (!m_early_checks_p)
    3232              :         {
    3233        66168 :           tree arg = call_arg (stmt, 0);
    3234        66168 :           if (TREE_CODE (arg) == SSA_NAME)
    3235        66084 :             check_pointer_uses (stmt, arg);
    3236              :         }
    3237              :       return true;
    3238              : 
    3239        10222 :     case BUILT_IN_GETTEXT:
    3240        10222 :     case BUILT_IN_PUTS:
    3241        10222 :     case BUILT_IN_PUTS_UNLOCKED:
    3242        10222 :     case BUILT_IN_STRDUP:
    3243        10222 :       check_read_access (stmt, call_arg (stmt, 0));
    3244        10222 :       return true;
    3245              : 
    3246        34357 :     case BUILT_IN_INDEX:
    3247        34357 :     case BUILT_IN_RINDEX:
    3248        34357 :     case BUILT_IN_STRCHR:
    3249        34357 :     case BUILT_IN_STRRCHR:
    3250        34357 :     case BUILT_IN_STRLEN:
    3251        34357 :       check_read_access (stmt, call_arg (stmt, 0));
    3252        34357 :       return true;
    3253              : 
    3254         2903 :     case BUILT_IN_FPUTS:
    3255         2903 :     case BUILT_IN_FPUTS_UNLOCKED:
    3256         2903 :       check_read_access (stmt, call_arg (stmt, 0));
    3257         2903 :       return true;
    3258              : 
    3259         2201 :     case BUILT_IN_STRNDUP:
    3260         2201 :     case BUILT_IN_STRNLEN:
    3261         2201 :       {
    3262         2201 :         tree str = call_arg (stmt, 0);
    3263         2201 :         tree len = call_arg (stmt, 1);
    3264         2201 :         check_read_access (stmt, str, len);
    3265         2201 :         return true;
    3266              :       }
    3267              : 
    3268         1657 :     case BUILT_IN_STRCAT:
    3269         1657 :       check_strcat (stmt);
    3270         1657 :       return true;
    3271              : 
    3272         1667 :     case BUILT_IN_STRNCAT:
    3273         1667 :       check_strncat (stmt);
    3274         1667 :       return true;
    3275              : 
    3276         7225 :     case BUILT_IN_STPCPY:
    3277         7225 :     case BUILT_IN_STRCPY:
    3278         7225 :       check_stxcpy (stmt);
    3279         7225 :       return true;
    3280              : 
    3281         5890 :     case BUILT_IN_STPNCPY:
    3282         5890 :     case BUILT_IN_STRNCPY:
    3283         5890 :       check_stxncpy (stmt);
    3284         5890 :       return true;
    3285              : 
    3286       259367 :     case BUILT_IN_STRCASECMP:
    3287       259367 :     case BUILT_IN_STRCMP:
    3288       259367 :     case BUILT_IN_STRPBRK:
    3289       259367 :     case BUILT_IN_STRSPN:
    3290       259367 :     case BUILT_IN_STRCSPN:
    3291       259367 :     case BUILT_IN_STRSTR:
    3292       259367 :       check_read_access (stmt, call_arg (stmt, 0));
    3293       259367 :       check_read_access (stmt, call_arg (stmt, 1));
    3294       259367 :       return true;
    3295              : 
    3296         6070 :     case BUILT_IN_STRNCASECMP:
    3297         6070 :     case BUILT_IN_STRNCMP:
    3298         6070 :       check_strncmp (stmt);
    3299         6070 :       return true;
    3300              : 
    3301       134351 :     case BUILT_IN_MEMCMP:
    3302       134351 :       {
    3303       134351 :         tree a1 = call_arg (stmt, 0);
    3304       134351 :         tree a2 = call_arg (stmt, 1);
    3305       134351 :         tree len = call_arg (stmt, 2);
    3306       134351 :         check_read_access (stmt, a1, len, 0);
    3307       134351 :         check_read_access (stmt, a2, len, 0);
    3308       134351 :         return true;
    3309              :       }
    3310              : 
    3311       191442 :     case BUILT_IN_MEMCPY:
    3312       191442 :     case BUILT_IN_MEMPCPY:
    3313       191442 :     case BUILT_IN_MEMMOVE:
    3314       191442 :       {
    3315       191442 :         tree dst = call_arg (stmt, 0);
    3316       191442 :         tree src = call_arg (stmt, 1);
    3317       191442 :         tree len = call_arg (stmt, 2);
    3318       191442 :         check_memop_access (stmt, dst, src, len);
    3319       191442 :         return true;
    3320              :       }
    3321              : 
    3322         6164 :     case BUILT_IN_MEMCHR:
    3323         6164 :       {
    3324         6164 :         tree src = call_arg (stmt, 0);
    3325         6164 :         tree len = call_arg (stmt, 2);
    3326         6164 :         check_read_access (stmt, src, len, 0);
    3327         6164 :         return true;
    3328              :       }
    3329              : 
    3330       179947 :     case BUILT_IN_MEMSET:
    3331       179947 :       {
    3332       179947 :         tree dst = call_arg (stmt, 0);
    3333       179947 :         tree len = call_arg (stmt, 2);
    3334       179947 :         check_memop_access (stmt, dst, NULL_TREE, len);
    3335       179947 :         return true;
    3336              :       }
    3337              : 
    3338      2539067 :     default:
    3339      2539067 :       if (check_atomic_builtin (stmt))
    3340              :         return true;
    3341              :       break;
    3342              :     }
    3343              : 
    3344              :   return false;
    3345              : }
    3346              : 
    3347              : /* Returns the type of the argument ARGNO to function with type FNTYPE
    3348              :    or null when the type cannot be determined or no such argument exists.  */
    3349              : 
    3350              : static tree
    3351        61677 : fntype_argno_type (tree fntype, unsigned argno)
    3352              : {
    3353        61677 :   if (!prototype_p (fntype))
    3354              :     return NULL_TREE;
    3355              : 
    3356        61673 :   tree argtype;
    3357        61673 :   function_args_iterator it;
    3358       124948 :   FOREACH_FUNCTION_ARGS (fntype, argtype, it)
    3359       124948 :     if (argno-- == 0)
    3360              :       return argtype;
    3361              : 
    3362              :   return NULL_TREE;
    3363              : }
    3364              : 
    3365              : /* Helper to append the "human readable" attribute access specification
    3366              :    described by ACCESS to the array ATTRSTR with size STRSIZE.  Used in
    3367              :    diagnostics.  */
    3368              : 
    3369              : static inline void
    3370          280 : append_attrname (const std::pair<int, attr_access> &access,
    3371              :                  char *attrstr, size_t strsize)
    3372              : {
    3373          280 :   if (access.second.internal_p)
    3374              :     return;
    3375              : 
    3376          262 :   tree str = access.second.to_external_string ();
    3377          262 :   gcc_assert (strsize >= (size_t) TREE_STRING_LENGTH (str));
    3378          262 :   strcpy (attrstr, TREE_STRING_POINTER (str));
    3379              : }
    3380              : 
    3381              : /* Iterate over attribute access read-only, read-write, and write-only
    3382              :    arguments and diagnose past-the-end accesses and related problems
    3383              :    in the function call EXP.  */
    3384              : 
    3385              : void
    3386      2967763 : pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
    3387              :                                         gimple *stmt)
    3388              : {
    3389      2967763 :   if (warning_suppressed_p (stmt, OPT_Wnonnull)
    3390      2967763 :       || warning_suppressed_p (stmt, OPT_Wstringop_overflow_))
    3391        19435 :     return;
    3392              : 
    3393      2948332 :   auto_diagnostic_group adg;
    3394              : 
    3395              :   /* Set if a warning has been issued for any argument (used to decide
    3396              :      whether to emit an informational note at the end).  */
    3397      2948332 :   opt_code opt_warned = no_warning;
    3398              : 
    3399              :   /* A string describing the attributes that the warnings issued by this
    3400              :      function apply to.  Used to print one informational note per function
    3401              :      call, rather than one per warning.  That reduces clutter.  */
    3402      2948332 :   char attrstr[80];
    3403      2948332 :   attrstr[0] = 0;
    3404              : 
    3405      3074988 :   for (rdwr_map::iterator it = rwm->begin (); it != rwm->end (); ++it)
    3406              :     {
    3407        63332 :       std::pair<int, attr_access> access = *it;
    3408              : 
    3409              :       /* Get the function call arguments corresponding to the attribute's
    3410              :          positional arguments.  When both arguments have been specified
    3411              :          there will be two entries in *RWM, one for each.  They are
    3412              :          cross-referenced by their respective argument numbers in
    3413              :          ACCESS.PTRARG and ACCESS.SIZARG.  */
    3414        63332 :       const int ptridx = access.second.ptrarg;
    3415        63332 :       const int sizidx = access.second.sizarg;
    3416              : 
    3417        63332 :       gcc_assert (ptridx != -1);
    3418        63332 :       gcc_assert (access.first == ptridx || access.first == sizidx);
    3419              : 
    3420              :       /* The pointer is set to null for the entry corresponding to
    3421              :          the size argument.  Skip it.  It's handled when the entry
    3422              :          corresponding to the pointer argument comes up.  */
    3423        63332 :       if (!access.second.ptr)
    3424         1686 :         continue;
    3425              : 
    3426        61677 :       tree ptrtype = fntype_argno_type (fntype, ptridx);
    3427        61677 :       if (!ptrtype)
    3428              :         /* A function with a prototype was redeclared without one and
    3429              :            the prototype has been lost.  See pr102759.  Avoid dealing
    3430              :            with this pathological case.  */
    3431            4 :         return;
    3432              : 
    3433        61673 :       tree argtype = TREE_TYPE (ptrtype);
    3434              : 
    3435              :       /* The size of the access by the call in elements.  */
    3436        61673 :       tree access_nelts;
    3437        61673 :       if (sizidx == -1)
    3438              :         {
    3439              :           /* If only the pointer attribute operand was specified and
    3440              :              not size, set SIZE to the greater of MINSIZE or size of
    3441              :              one element of the pointed to type to detect smaller
    3442              :              objects (null pointers are diagnosed in this case only
    3443              :              if the pointer is also declared with attribute nonnull.  */
    3444        60019 :           if (access.second.minsize
    3445        60019 :               && access.second.minsize != HOST_WIDE_INT_M1U)
    3446        50389 :             access_nelts = build_int_cstu (sizetype, access.second.minsize);
    3447         9630 :           else if (VOID_TYPE_P (argtype) && access.second.mode == access_none)
    3448              :             /* Treat access mode none on a void* argument as expecting
    3449              :                as little as zero bytes.  */
    3450          242 :             access_nelts = size_zero_node;
    3451              :           else
    3452         9388 :             access_nelts = size_one_node;
    3453              :         }
    3454              :       else
    3455         1654 :         access_nelts = rwm->get (sizidx)->size;
    3456              : 
    3457              :       /* If access_nelts is e.g. a PARM_DECL with larger precision than
    3458              :          sizetype, such as __int128 or _BitInt(34123) parameters,
    3459              :          cast it to sizetype.  */
    3460        61673 :       if (access_nelts
    3461        61673 :           && INTEGRAL_TYPE_P (TREE_TYPE (access_nelts))
    3462       123346 :           && (TYPE_PRECISION (TREE_TYPE (access_nelts))
    3463        61673 :               > TYPE_PRECISION (sizetype)))
    3464            2 :         access_nelts = fold_convert (sizetype, access_nelts);
    3465              : 
    3466              :       /* Format the value or range to avoid an explosion of messages.  */
    3467        61673 :       char sizstr[80];
    3468        61673 :       tree sizrng[2] = { size_zero_node, build_all_ones_cst (sizetype) };
    3469        61673 :       if (get_size_range (m_ptr_qry.rvals, access_nelts, stmt, sizrng, 1))
    3470              :         {
    3471        61673 :           char *s0 = print_generic_expr_to_str (sizrng[0]);
    3472        61673 :           if (tree_int_cst_equal (sizrng[0], sizrng[1]))
    3473              :             {
    3474        61222 :               gcc_checking_assert (strlen (s0) < sizeof sizstr);
    3475        61222 :               strcpy (sizstr, s0);
    3476              :             }
    3477              :           else
    3478              :             {
    3479          451 :               char *s1 = print_generic_expr_to_str (sizrng[1]);
    3480          451 :               gcc_checking_assert (strlen (s0) + strlen (s1)
    3481              :                                    < sizeof sizstr - 4);
    3482          451 :               sprintf (sizstr, "[%.37s, %.37s]", s0, s1);
    3483          451 :               free (s1);
    3484              :             }
    3485        61673 :           free (s0);
    3486              :         }
    3487              :       else
    3488            0 :         *sizstr = '\0';
    3489              : 
    3490              :       /* Set if a warning has been issued for the current argument.  */
    3491        61673 :       opt_code arg_warned = no_warning;
    3492        61673 :       location_t loc = get_location (stmt);
    3493        61673 :       tree ptr = access.second.ptr;
    3494        61673 :       if (*sizstr
    3495        61673 :           && tree_int_cst_sgn (sizrng[0]) < 0
    3496        61820 :           && tree_int_cst_sgn (sizrng[1]) < 0)
    3497              :         {
    3498           53 :           rich_location_with_details richloc (loc, stmt);
    3499              :           /* Warn about negative sizes.  */
    3500           53 :           if (access.second.internal_p)
    3501              :             {
    3502           18 :               const std::string argtypestr
    3503           18 :                 = access.second.array_as_string (ptrtype);
    3504              : 
    3505           18 :               if (warning_at (&richloc, OPT_Wstringop_overflow_,
    3506              :                               "bound argument %i value %s is "
    3507              :                               "negative for a variable length array "
    3508              :                               "argument %i of type %s",
    3509              :                               sizidx + 1, sizstr,
    3510              :                               ptridx + 1, argtypestr.c_str ()))
    3511           18 :                 arg_warned = OPT_Wstringop_overflow_;
    3512           18 :             }
    3513           35 :           else if (warning_at (&richloc, OPT_Wstringop_overflow_,
    3514              :                                "argument %i value %s is negative",
    3515              :                                sizidx + 1, sizstr))
    3516              :             arg_warned = OPT_Wstringop_overflow_;
    3517              : 
    3518           18 :           if (arg_warned != no_warning)
    3519              :             {
    3520           23 :               append_attrname (access, attrstr, sizeof attrstr);
    3521              :               /* Remember a warning has been issued and avoid warning
    3522              :                  again below for the same attribute.  */
    3523           23 :               opt_warned = arg_warned;
    3524           23 :               continue;
    3525              :             }
    3526           53 :         }
    3527              : 
    3528              :       /* The size of the access by the call in bytes.  */
    3529        61650 :       tree access_size = NULL_TREE;
    3530        61650 :       if (tree_int_cst_sgn (sizrng[0]) >= 0)
    3531              :         {
    3532        61526 :           if (COMPLETE_TYPE_P (argtype))
    3533              :             {
    3534              :               /* Multiply ACCESS_SIZE by the size of the type the pointer
    3535              :                  argument points to.  If it's incomplete the size is used
    3536              :                  as is.  */
    3537        58823 :               if (tree argsize = TYPE_SIZE_UNIT (argtype))
    3538        58823 :                 if (TREE_CODE (argsize) == INTEGER_CST)
    3539              :                   {
    3540        58595 :                     const int prec = TYPE_PRECISION (sizetype);
    3541        58595 :                     wide_int minsize = wi::to_wide (sizrng[0], prec);
    3542        58595 :                     minsize *= wi::to_wide (argsize, prec);
    3543        58595 :                     access_size = wide_int_to_tree (sizetype, minsize);
    3544        58595 :                   }
    3545              :             }
    3546              :           else
    3547              :             access_size = access_nelts;
    3548              :         }
    3549              : 
    3550        61650 :       if (integer_zerop (ptr))
    3551              :         {
    3552         1409 :           if (!access.second.internal_p
    3553         1409 :               && sizidx >= 0 && tree_int_cst_sgn (sizrng[0]) > 0)
    3554              :             {
    3555              :               /* Warn about null pointers with positive sizes.  This is
    3556              :                  different from also declaring the pointer argument with
    3557              :                  attribute nonnull when the function accepts null pointers
    3558              :                  only when the corresponding size is zero.  */
    3559           26 :               if (warning_at (loc, OPT_Wnonnull,
    3560              :                                    "argument %i is null but "
    3561              :                                    "the corresponding size argument "
    3562              :                                    "%i value is %s",
    3563              :                                    ptridx + 1, sizidx + 1, sizstr))
    3564            8 :                 arg_warned = OPT_Wnonnull;
    3565              :             }
    3566              : 
    3567           16 :           if (arg_warned != no_warning)
    3568              :             {
    3569            8 :               append_attrname (access, attrstr, sizeof attrstr);
    3570              :               /* Remember a warning has been issued and avoid warning
    3571              :                  again below for the same attribute.  */
    3572            8 :               opt_warned = OPT_Wnonnull;
    3573            8 :               continue;
    3574              :             }
    3575              :         }
    3576              : 
    3577        61642 :       access_data data (m_ptr_qry.rvals, stmt, access.second.mode,
    3578        61642 :                         NULL_TREE, false, NULL_TREE, false);
    3579        60759 :       access_ref* const pobj = (access.second.mode == access_write_only
    3580        61642 :                                 ? &data.dst : &data.src);
    3581        61642 :       tree objsize = compute_objsize (ptr, stmt, 1, pobj, &m_ptr_qry);
    3582              : 
    3583              :       /* The size of the destination or source object.  */
    3584        61642 :       tree dstsize = NULL_TREE, srcsize = NULL_TREE;
    3585        61642 :       if (access.second.mode == access_read_only
    3586              :           || access.second.mode == access_none)
    3587              :         {
    3588              :           /* For a read-only argument there is no destination.  For
    3589              :              no access, set the source as well and differentiate via
    3590              :              the access flag below.  */
    3591         1276 :           srcsize = objsize;
    3592         1276 :           if (access.second.mode == access_read_only
    3593              :               || access.second.mode == access_none)
    3594              :             {
    3595              :               /* For a read-only attribute there is no destination so
    3596              :                  clear OBJSIZE.  This emits "reading N bytes" kind of
    3597              :                  diagnostics instead of the "writing N bytes" kind,
    3598              :                  unless MODE is none.  */
    3599         1276 :               objsize = NULL_TREE;
    3600              :             }
    3601              :         }
    3602              :       else
    3603              :         dstsize = objsize;
    3604              : 
    3605              :       /* Clear the no-warning bit in case it was set by check_access
    3606              :          in a prior iteration so that accesses via different arguments
    3607              :          are diagnosed.  */
    3608        61642 :       suppress_warning (stmt, OPT_Wstringop_overflow_, false);
    3609        61642 :       access_mode mode = data.mode;
    3610        61642 :       if (mode == access_deferred)
    3611        58981 :         mode = TYPE_READONLY (argtype) ? access_read_only : access_read_write;
    3612        61642 :       check_access (stmt, access_size, /*maxread=*/ NULL_TREE, srcsize,
    3613              :                     dstsize, mode, &data, m_ptr_qry.rvals);
    3614              : 
    3615        61642 :       if (warning_suppressed_p (stmt, OPT_Wstringop_overflow_))
    3616              :         opt_warned = OPT_Wstringop_overflow_;
    3617        61435 :       if (opt_warned != no_warning)
    3618              :         {
    3619          322 :           if (access.second.internal_p)
    3620              :             {
    3621           73 :               unsigned HOST_WIDE_INT nelts =
    3622           73 :                 access_nelts ? access.second.minsize : HOST_WIDE_INT_M1U;
    3623           73 :               tree arrtype = build_printable_array_type (argtype, nelts);
    3624           73 :               inform (loc, "referencing argument %u of type %qT",
    3625              :                       ptridx + 1, arrtype);
    3626              :             }
    3627              :           else
    3628              :             /* If check_access issued a warning above, append the relevant
    3629              :                attribute to the string.  */
    3630          249 :             append_attrname (access, attrstr, sizeof attrstr);
    3631              :         }
    3632              :     }
    3633              : 
    3634      2948328 :   if (*attrstr)
    3635              :     {
    3636          145 :       if (fndecl)
    3637          129 :         inform (get_location (fndecl),
    3638              :                 "in a call to function %qD declared with attribute %qs",
    3639              :                 fndecl, attrstr);
    3640              :       else
    3641           16 :         inform (get_location (stmt),
    3642              :                 "in a call with type %qT and attribute %qs",
    3643              :                 fntype, attrstr);
    3644              :     }
    3645      2948183 :   else if (opt_warned != no_warning)
    3646              :     {
    3647           91 :       if (fndecl)
    3648           91 :         inform (get_location (fndecl),
    3649              :                 "in a call to function %qD", fndecl);
    3650              :       else
    3651            0 :         inform (get_location (stmt),
    3652              :                 "in a call with type %qT", fntype);
    3653              :     }
    3654              : 
    3655              :   /* Set the bit in case it was cleared and not set above.  */
    3656          236 :   if (opt_warned != no_warning)
    3657          236 :     suppress_warning (stmt, opt_warned);
    3658      2948332 : }
    3659              : 
    3660              : /* Check call STMT to an ordinary (non-built-in) function for invalid
    3661              :    accesses.  Return true if a call has been handled.  */
    3662              : 
    3663              : bool
    3664     17142495 : pass_waccess::check_call_access (gcall *stmt)
    3665              : {
    3666     17142495 :   tree fntype = gimple_call_fntype (stmt);
    3667     16435203 :   if (!fntype)
    3668              :     return false;
    3669              : 
    3670     16435203 :   tree fntypeattrs = TYPE_ATTRIBUTES (fntype);
    3671     16435203 :   if (!fntypeattrs)
    3672              :     return false;
    3673              : 
    3674              :   /* Map of attribute access specifications for function arguments.  */
    3675      2967763 :   rdwr_map rdwr_idx;
    3676      2967763 :   init_attr_rdwr_indices (&rdwr_idx, fntypeattrs);
    3677              : 
    3678      2967763 :   unsigned nargs = call_nargs (stmt);
    3679      9179082 :   for (unsigned i = 0; i != nargs; ++i)
    3680              :     {
    3681      6211319 :       tree arg = call_arg (stmt, i);
    3682              : 
    3683              :       /* Save the actual argument that corresponds to the access attribute
    3684              :          operand for later processing.  */
    3685      6211319 :       if (attr_access *access = rdwr_idx.get (i))
    3686              :         {
    3687        63979 :           if (POINTER_TYPE_P (TREE_TYPE (arg)))
    3688              :             {
    3689        62263 :               access->ptr = arg;
    3690              :               /* A nonnull ACCESS->SIZE contains VLA bounds.  */
    3691              :             }
    3692              :           else
    3693              :             {
    3694         1716 :               access->size = arg;
    3695         1716 :               gcc_assert (access->ptr == NULL_TREE);
    3696              :             }
    3697              :         }
    3698              :     }
    3699              : 
    3700              :   /* Check attribute access arguments.  */
    3701      2967763 :   tree fndecl = gimple_call_fndecl (stmt);
    3702      2967763 :   maybe_check_access_sizes (&rdwr_idx, fndecl, fntype, stmt);
    3703              : 
    3704      2967763 :   check_alloc_size_call (stmt);
    3705      2967763 :   return true;
    3706      2967763 : }
    3707              : 
    3708              : /* Check arguments in a call STMT for attribute nonstring.  */
    3709              : 
    3710              : static void
    3711      6844928 : check_nonstring_args (gcall *stmt)
    3712              : {
    3713      6844928 :   tree fndecl = gimple_call_fndecl (stmt);
    3714              : 
    3715              :   /* Detect passing non-string arguments to functions expecting
    3716              :      nul-terminated strings.  */
    3717      6844928 :   maybe_warn_nonstring_arg (fndecl, stmt);
    3718      6844928 : }
    3719              : 
    3720              : /* Issue a warning if a deallocation function such as free, realloc,
    3721              :    or C++ operator delete is called with an argument not returned by
    3722              :    a matching allocation function such as malloc or the corresponding
    3723              :    form of C++ operator new.  */
    3724              : 
    3725              : void
    3726      6844928 : pass_waccess::maybe_check_dealloc_call (gcall *call)
    3727              : {
    3728      6844928 :   tree fndecl = gimple_call_fndecl (call);
    3729      6844928 :   if (!fndecl)
    3730      6635483 :     return;
    3731              : 
    3732      6435822 :   unsigned argno = fndecl_dealloc_argno (fndecl);
    3733      6435822 :   if ((unsigned) call_nargs (call) <= argno)
    3734              :     return;
    3735              : 
    3736       210128 :   tree ptr = gimple_call_arg (call, argno);
    3737       210128 :   if (integer_zerop (ptr))
    3738              :     return;
    3739              : 
    3740       210034 :   access_ref aref;
    3741       210034 :   if (!compute_objsize (ptr, call, 0, &aref, &m_ptr_qry))
    3742              :     return;
    3743              : 
    3744       210034 :   tree ref = aref.ref;
    3745       210034 :   if (integer_zerop (ref))
    3746              :     return;
    3747              : 
    3748       209922 :   tree dealloc_decl = fndecl;
    3749       209922 :   location_t loc = gimple_location (call);
    3750              : 
    3751       209922 :   if (DECL_P (ref) || EXPR_P (ref))
    3752              :     {
    3753              :       /* Diagnose freeing a declared object.  */
    3754       118752 :       if (aref.ref_declared ())
    3755              :         {
    3756          152 :           auto_diagnostic_group d;
    3757          152 :           if (warning_at (loc, OPT_Wfree_nonheap_object,
    3758              :                           "%qD called on unallocated object %qD",
    3759              :                           dealloc_decl, ref))
    3760              :             {
    3761          140 :               inform (get_location (ref), "declared here");
    3762          140 :               return;
    3763              :             }
    3764          152 :         }
    3765              : 
    3766              :       /* Diagnose freeing a pointer that includes a positive offset.
    3767              :          Such a pointer cannot refer to the beginning of an allocated
    3768              :          object.  A negative offset may refer to it.  */
    3769       118612 :       if (aref.sizrng[0] != aref.sizrng[1]
    3770       118612 :           && warn_dealloc_offset (loc, call, aref))
    3771              :         return;
    3772              :     }
    3773        91170 :   else if (CONSTANT_CLASS_P (ref))
    3774              :     {
    3775           38 :       auto_diagnostic_group d;
    3776           38 :       if (warning_at (loc, OPT_Wfree_nonheap_object,
    3777              :                       "%qD called on a pointer to an unallocated "
    3778              :                       "object %qE", dealloc_decl, ref))
    3779              :         {
    3780           38 :           if (TREE_CODE (ptr) == SSA_NAME)
    3781              :             {
    3782           12 :               gimple *def_stmt = SSA_NAME_DEF_STMT (ptr);
    3783           12 :               if (is_gimple_assign (def_stmt))
    3784              :                 {
    3785           12 :                   location_t loc = gimple_location (def_stmt);
    3786           12 :                   inform (loc, "assigned here");
    3787              :                 }
    3788              :             }
    3789           38 :           return;
    3790              :         }
    3791           38 :     }
    3792        91132 :   else if (TREE_CODE (ref) == SSA_NAME)
    3793              :     {
    3794              :       /* Also warn if the pointer argument refers to the result
    3795              :          of an allocation call like alloca or VLA.  */
    3796        91132 :       gimple *def_stmt = SSA_NAME_DEF_STMT (ref);
    3797        91132 :       if (!def_stmt)
    3798              :         return;
    3799              : 
    3800        91132 :       if (is_gimple_call (def_stmt))
    3801              :         {
    3802        45959 :           auto_diagnostic_group d;
    3803        45959 :           bool warned = false;
    3804        45959 :           if (gimple_call_alloc_p (def_stmt))
    3805              :             {
    3806        42248 :               if (matching_alloc_calls_p (def_stmt, dealloc_decl))
    3807              :                 {
    3808        41828 :                   if (warn_dealloc_offset (loc, call, aref))
    3809              :                     return;
    3810              :                 }
    3811              :               else
    3812              :                 {
    3813          420 :                   tree alloc_decl = gimple_call_fndecl (def_stmt);
    3814          420 :                   const opt_code opt =
    3815          420 :                     (DECL_IS_OPERATOR_NEW_P (alloc_decl)
    3816          172 :                      || DECL_IS_OPERATOR_DELETE_P (dealloc_decl)
    3817          420 :                      ? OPT_Wmismatched_new_delete
    3818              :                      : OPT_Wmismatched_dealloc);
    3819          420 :                   warned = warning_at (loc, opt,
    3820              :                                        "%qD called on pointer returned "
    3821              :                                        "from a mismatched allocation "
    3822              :                                        "function", dealloc_decl);
    3823              :                 }
    3824              :             }
    3825         3711 :           else if (gimple_call_builtin_p (def_stmt, BUILT_IN_ALLOCA)
    3826         3711 :                    || gimple_call_builtin_p (def_stmt,
    3827              :                                              BUILT_IN_ALLOCA_WITH_ALIGN))
    3828           20 :             warned = warning_at (loc, OPT_Wfree_nonheap_object,
    3829              :                                  "%qD called on pointer to "
    3830              :                                  "an unallocated object",
    3831              :                                  dealloc_decl);
    3832         3691 :           else if (warn_dealloc_offset (loc, call, aref))
    3833              :             return;
    3834              : 
    3835          440 :           if (warned)
    3836              :             {
    3837          230 :               tree fndecl = gimple_call_fndecl (def_stmt);
    3838          230 :               inform (gimple_location (def_stmt),
    3839              :                       "returned from %qD", fndecl);
    3840          230 :               return;
    3841              :             }
    3842        45959 :         }
    3843        45173 :       else if (gimple_nop_p (def_stmt))
    3844              :         {
    3845        14543 :           ref = SSA_NAME_VAR (ref);
    3846              :           /* Diagnose freeing a pointer that includes a positive offset.  */
    3847        14543 :           if (TREE_CODE (ref) == PARM_DECL
    3848        14452 :               && !aref.deref
    3849        14452 :               && aref.sizrng[0] != aref.sizrng[1]
    3850        14543 :               && aref.offrng[0] > 0 && aref.offrng[1] > 0
    3851        14549 :               && warn_dealloc_offset (loc, call, aref))
    3852            6 :             return;
    3853              :         }
    3854              :     }
    3855              : }
    3856              : 
    3857              : /* Return true if either USE_STMT's basic block (that of a pointer's use)
    3858              :    is dominated by INVAL_STMT's (that of a pointer's invalidating statement,
    3859              :    which is either a clobber or a deallocation call), or if they're in
    3860              :    the same block, USE_STMT follows INVAL_STMT.  */
    3861              : 
    3862              : bool
    3863      5204412 : pass_waccess::use_after_inval_p (gimple *inval_stmt, gimple *use_stmt,
    3864              :                                  bool last_block /* = false */)
    3865              : {
    3866      5204412 :   tree clobvar =
    3867      5204412 :     gimple_clobber_p (inval_stmt) ? gimple_assign_lhs (inval_stmt) : NULL_TREE;
    3868              : 
    3869      5204412 :   basic_block inval_bb = gimple_bb (inval_stmt);
    3870      5204412 :   basic_block use_bb = gimple_bb (use_stmt);
    3871              : 
    3872      5204412 :   if (!inval_bb || !use_bb)
    3873              :     return false;
    3874              : 
    3875      5203410 :   if (inval_bb != use_bb)
    3876              :     {
    3877      4544603 :       if (dominated_by_p (CDI_DOMINATORS, use_bb, inval_bb))
    3878              :         return true;
    3879              : 
    3880      4543588 :       if (!clobvar || !last_block)
    3881              :         return false;
    3882              : 
    3883              :       /* Proceed only when looking for uses of dangling pointers.  */
    3884      3318270 :       auto gsi = gsi_for_stmt (use_stmt);
    3885              : 
    3886              :       /* A use statement in the last basic block in a function or one that
    3887              :          falls through to it is after any other prior clobber of the used
    3888              :          variable unless it's followed by a clobber of the same variable. */
    3889      3318270 :       basic_block bb = use_bb;
    3890      3318270 :       while (bb != inval_bb
    3891      4042274 :              && single_succ_p (bb)
    3892      5591449 :              && !(single_succ_edge (bb)->flags
    3893      1281639 :                   & (EDGE_EH | EDGE_ABNORMAL | EDGE_DFS_BACK)))
    3894              :         {
    3895     10949245 :           for (; !gsi_end_p (gsi); gsi_next_nondebug (&gsi))
    3896              :             {
    3897      9957705 :               gimple *stmt = gsi_stmt (gsi);
    3898      9957705 :               if (gimple_clobber_p (stmt))
    3899              :                 {
    3900       309111 :                   if (clobvar == gimple_assign_lhs (stmt))
    3901              :                     /* The use is followed by a clobber.  */
    3902              :                     return false;
    3903              :                 }
    3904              :             }
    3905              : 
    3906       991540 :           bb = single_succ (bb);
    3907      1983080 :           gsi = gsi_start_bb (bb);
    3908              :         }
    3909              : 
    3910              :       /* The use is one of a dangling pointer if a clobber of the variable
    3911              :          [the pointer points to] has not been found before the function exit
    3912              :          point.  */
    3913      3301581 :       return bb == EXIT_BLOCK_PTR_FOR_FN (cfun);
    3914              :     }
    3915              : 
    3916       658807 :   if (bitmap_set_bit (m_bb_uids_set, inval_bb->index))
    3917              :     /* The first time this basic block is visited assign increasing ids
    3918              :        to consecutive statements in it.  Use the ids to determine which
    3919              :        precedes which.  This avoids the linear traversal on subsequent
    3920              :        visits to the same block.  */
    3921       338910 :     renumber_gimple_stmt_uids_in_block (m_func, inval_bb);
    3922              : 
    3923       658807 :   return gimple_uid (inval_stmt) < gimple_uid (use_stmt);
    3924              : }
    3925              : 
    3926              : /* Issue a warning for the USE_STMT of pointer or reference REF rendered
    3927              :    invalid by INVAL_STMT.  REF may be null when it's been optimized away.
    3928              :    When nonnull, INVAL_STMT is the deallocation function that rendered
    3929              :    the pointer or reference dangling.  Otherwise, VAR is the auto variable
    3930              :    (including an unnamed temporary such as a compound literal) whose
    3931              :    lifetime's rended it dangling.  MAYBE is true to issue the "maybe"
    3932              :    kind of warning.  EQUALITY is true when the pointer is used in
    3933              :    an equality expression.  */
    3934              : 
    3935              : void
    3936        18150 : pass_waccess::warn_invalid_pointer (tree ref, gimple *use_stmt,
    3937              :                                     gimple *inval_stmt, tree var,
    3938              :                                     bool maybe, bool equality /* = false */)
    3939              : {
    3940              :   /* Avoid printing the unhelpful "<unknown>" in the diagnostics.  */
    3941        18150 :   if (ref && TREE_CODE (ref) == SSA_NAME)
    3942              :     {
    3943        18123 :       tree var = SSA_NAME_VAR (ref);
    3944        17431 :       if (!var)
    3945              :         ref = NULL_TREE;
    3946              :       /* Don't warn for cases like when a cdtor returns 'this' on ARM.  */
    3947        17431 :       else if (warning_suppressed_p (var, OPT_Wuse_after_free))
    3948              :         return;
    3949        17431 :       else if (DECL_ARTIFICIAL (var))
    3950          728 :         ref = NULL_TREE;
    3951              :     }
    3952              : 
    3953        18150 :   location_t use_loc = gimple_location (use_stmt);
    3954        18150 :   if (use_loc == UNKNOWN_LOCATION)
    3955              :     {
    3956            0 :       use_loc = m_func->function_end_locus;
    3957            0 :       if (!ref)
    3958              :         /* Avoid issuing a warning with no context other than
    3959              :            the function.  That would make it difficult to debug
    3960              :            in any but very simple cases.  */
    3961              :         return;
    3962              :     }
    3963              : 
    3964        18150 :   if (is_gimple_call (inval_stmt))
    3965              :     {
    3966        17863 :       if (!m_early_checks_p
    3967         5878 :           || (equality && warn_use_after_free < 3)
    3968         5617 :           || (maybe && warn_use_after_free < 2)
    3969        23439 :           || warning_suppressed_p (use_stmt, OPT_Wuse_after_free))
    3970        12287 :         return;
    3971              : 
    3972         5576 :       const tree inval_decl = gimple_call_fndecl (inval_stmt);
    3973              : 
    3974         5576 :       auto_diagnostic_group d;
    3975        11030 :       if ((ref && warning_at (use_loc, OPT_Wuse_after_free,
    3976              :                               (maybe
    3977              :                                ? G_("pointer %qE may be used after %qD")
    3978              :                                : G_("pointer %qE used after %qD")),
    3979              :                               ref, inval_decl))
    3980        10800 :           || (!ref && warning_at (use_loc, OPT_Wuse_after_free,
    3981              :                               (maybe
    3982              :                                ? G_("pointer may be used after %qD")
    3983              :                                : G_("pointer used after %qD")),
    3984              :                                   inval_decl)))
    3985              :         {
    3986          355 :           location_t loc = gimple_location (inval_stmt);
    3987          355 :           inform (loc, "call to %qD here", inval_decl);
    3988          355 :           suppress_warning (use_stmt, OPT_Wuse_after_free);
    3989              :         }
    3990         5576 :       return;
    3991         5576 :     }
    3992              : 
    3993          287 :   if (equality
    3994          281 :       || (maybe && warn_dangling_pointer < 2)
    3995          563 :       || warning_suppressed_p (use_stmt, OPT_Wdangling_pointer_))
    3996           66 :     return;
    3997              : 
    3998          221 :   if (DECL_NAME (var))
    3999              :     {
    4000          207 :       auto_diagnostic_group d;
    4001          207 :       if ((ref
    4002          174 :            && warning_at (use_loc, OPT_Wdangling_pointer_,
    4003              :                           (maybe
    4004              :                            ? G_("dangling pointer %qE to %qD may be used")
    4005              :                            : G_("using dangling pointer %qE to %qD")),
    4006              :                           ref, var))
    4007          207 :           || (!ref
    4008          214 :               && warning_at (use_loc, OPT_Wdangling_pointer_,
    4009              :                              (maybe
    4010              :                               ? G_("dangling pointer to %qD may be used")
    4011              :                               : G_("using a dangling pointer to %qD")),
    4012              :                              var)))
    4013           98 :         inform (DECL_SOURCE_LOCATION (var),
    4014              :                 "%qD declared here", var);
    4015          207 :       suppress_warning (use_stmt, OPT_Wdangling_pointer_);
    4016          207 :       return;
    4017          207 :     }
    4018              : 
    4019           14 :   if ((ref
    4020           14 :        && warning_at (use_loc, OPT_Wdangling_pointer_,
    4021              :                       (maybe
    4022              :                        ? G_("dangling pointer %qE to an unnamed temporary "
    4023              :                             "may be used")
    4024              :                        : G_("using dangling pointer %qE to an unnamed "
    4025              :                             "temporary")),
    4026              :                       ref))
    4027           14 :       || (!ref
    4028           12 :           && warning_at (use_loc, OPT_Wdangling_pointer_,
    4029              :                          (maybe
    4030              :                           ? G_("dangling pointer to an unnamed temporary "
    4031              :                                "may be used")
    4032              :                           : G_("using a dangling pointer to an unnamed "
    4033              :                                "temporary")))))
    4034              :     {
    4035           14 :       inform (DECL_SOURCE_LOCATION (var),
    4036              :               "unnamed temporary defined here");
    4037           14 :       suppress_warning (use_stmt, OPT_Wdangling_pointer_);
    4038              :     }
    4039              : }
    4040              : 
    4041              : /* If STMT is a call to either the standard realloc or to a user-defined
    4042              :    reallocation function returns its LHS and set *PTR to the reallocated
    4043              :    pointer.  Otherwise return null.  */
    4044              : 
    4045              : static tree
    4046       568609 : get_realloc_lhs (gimple *stmt, tree *ptr)
    4047              : {
    4048       568609 :   if (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC))
    4049              :     {
    4050        20653 :       *ptr = gimple_call_arg (stmt, 0);
    4051        20653 :       return gimple_call_lhs (stmt);
    4052              :     }
    4053              : 
    4054       920803 :   gcall *call = dyn_cast<gcall *>(stmt);
    4055       372987 :   if (!call)
    4056              :     return NULL_TREE;
    4057              : 
    4058       372987 :   tree fnattr = NULL_TREE;
    4059       372987 :   tree fndecl = gimple_call_fndecl (call);
    4060       372987 :   if (fndecl)
    4061       372987 :     fnattr = DECL_ATTRIBUTES (fndecl);
    4062              :   else
    4063              :     {
    4064            0 :       tree fntype = gimple_call_fntype (stmt);
    4065            0 :       if (!fntype)
    4066              :         return NULL_TREE;
    4067            0 :       fnattr = TYPE_ATTRIBUTES (fntype);
    4068              :     }
    4069              : 
    4070       372987 :   if (!fnattr)
    4071              :     return NULL_TREE;
    4072              : 
    4073       365816 :   for (tree ats = fnattr;  (ats = lookup_attribute ("*dealloc", ats));
    4074        12453 :        ats = TREE_CHAIN (ats))
    4075              :     {
    4076        12593 :       tree args = TREE_VALUE (ats);
    4077        12593 :       if (!args)
    4078            0 :         continue;
    4079              : 
    4080        12593 :       tree alloc = TREE_VALUE (args);
    4081        12593 :       if (!alloc)
    4082            0 :         continue;
    4083              : 
    4084        12593 :       if (alloc == DECL_NAME (fndecl))
    4085              :         {
    4086          140 :           unsigned argno = 0;
    4087          140 :           if (tree index = TREE_CHAIN (args))
    4088           82 :             argno = TREE_INT_CST_LOW (TREE_VALUE (index)) - 1;
    4089          140 :           *ptr = gimple_call_arg (stmt, argno);
    4090          140 :           return gimple_call_lhs (stmt);
    4091              :         }
    4092              :     }
    4093              : 
    4094              :   return NULL_TREE;
    4095              : }
    4096              : 
    4097              : /* Warn if STMT is a call to a deallocation function that's not a match
    4098              :    for the REALLOC_STMT call.  Return true if warned.  */
    4099              : 
    4100              : static bool
    4101        83077 : maybe_warn_mismatched_realloc (tree ptr, gimple *realloc_stmt, gimple *stmt)
    4102              : {
    4103        83077 :   if (!is_gimple_call (stmt))
    4104              :     return false;
    4105              : 
    4106        39503 :   tree fndecl = gimple_call_fndecl (stmt);
    4107        39503 :   if (!fndecl)
    4108              :     return false;
    4109              : 
    4110        39503 :   unsigned argno = fndecl_dealloc_argno (fndecl);
    4111        39503 :   if (call_nargs (stmt) <= argno)
    4112              :     return false;
    4113              : 
    4114         2342 :   if (matching_alloc_calls_p (realloc_stmt, fndecl))
    4115              :     return false;
    4116              : 
    4117              :   /* Avoid printing the unhelpful "<unknown>" in the diagnostics.  */
    4118           42 :   if (ptr && TREE_CODE (ptr) == SSA_NAME
    4119           84 :       && (!SSA_NAME_VAR (ptr) || DECL_ARTIFICIAL (SSA_NAME_VAR (ptr))))
    4120              :     ptr = NULL_TREE;
    4121              : 
    4122           42 :   location_t loc = gimple_location (stmt);
    4123           42 :   tree realloc_decl = gimple_call_fndecl (realloc_stmt);
    4124           42 :   tree dealloc_decl = gimple_call_fndecl (stmt);
    4125           42 :   if (ptr && !warning_at (loc, OPT_Wmismatched_dealloc,
    4126              :                           "%qD called on pointer %qE passed to mismatched "
    4127              :                           "allocation function %qD",
    4128              :                           dealloc_decl, ptr, realloc_decl))
    4129            3 :     return false;
    4130           39 :   if (!ptr && !warning_at (loc, OPT_Wmismatched_dealloc,
    4131              :                            "%qD called on a pointer passed to mismatched "
    4132              :                            "reallocation function %qD",
    4133              :                            dealloc_decl, realloc_decl))
    4134            0 :     return false;
    4135              : 
    4136           39 :   inform (gimple_location (realloc_stmt),
    4137              :           "call to %qD", realloc_decl);
    4138           39 :   return true;
    4139              : }
    4140              : 
    4141              : /* Return true if P and Q point to the same object, and false if they
    4142              :    either don't or their relationship cannot be determined.  */
    4143              : 
    4144              : static bool
    4145        83048 : pointers_related_p (gimple *stmt, tree p, tree q, pointer_query &qry,
    4146              :                     auto_bitmap &visited)
    4147              : {
    4148        83048 :   if (!ptr_derefs_may_alias_p (p, q))
    4149              :     return false;
    4150              : 
    4151              :   /* TODO: Work harder to rule out relatedness.  */
    4152        83048 :   access_ref pref, qref;
    4153        83048 :   if (!qry.get_ref (p, stmt, &pref, 0)
    4154        83048 :       || !qry.get_ref (q, stmt, &qref, 0))
    4155              :     /* GET_REF() only rarely fails.  When it does, it's likely because
    4156              :        it involves a self-referential PHI.  Return a conservative result.  */
    4157            0 :     return false;
    4158              : 
    4159        83048 :   if (pref.ref == qref.ref)
    4160              :     return true;
    4161              : 
    4162              :   /* If either pointer is a PHI, iterate over all its operands and
    4163              :      return true if they're all related to the other pointer.  */
    4164          108 :   tree ptr = q;
    4165          108 :   unsigned version;
    4166          108 :   gphi *phi = pref.phi ();
    4167          108 :   if (phi)
    4168          108 :     version = SSA_NAME_VERSION (pref.ref);
    4169              :   else
    4170              :     {
    4171            0 :       phi = qref.phi ();
    4172            0 :       if (!phi)
    4173              :         return false;
    4174              : 
    4175            0 :       ptr = p;
    4176            0 :       version = SSA_NAME_VERSION (qref.ref);
    4177              :     }
    4178              : 
    4179          108 :   if (!bitmap_set_bit (visited, version))
    4180              :     return true;
    4181              : 
    4182           60 :   unsigned nargs = gimple_phi_num_args (phi);
    4183          180 :   for (unsigned i = 0; i != nargs; ++i)
    4184              :     {
    4185          120 :       tree arg = gimple_phi_arg_def (phi, i);
    4186          120 :       if (!pointers_related_p (stmt, arg, ptr, qry, visited))
    4187              :         return false;
    4188              :     }
    4189              : 
    4190              :   return true;
    4191              : }
    4192              : 
    4193              : /* Convenience wrapper for the above.  */
    4194              : 
    4195              : static bool
    4196        82928 : pointers_related_p (gimple *stmt, tree p, tree q, pointer_query &qry)
    4197              : {
    4198        82928 :   auto_bitmap visited;
    4199        82928 :   return pointers_related_p (stmt, p, q, qry, visited);
    4200        82928 : }
    4201              : 
    4202              : /* For a STMT either a call to a deallocation function or a clobber, warn
    4203              :    for uses of the pointer PTR it was called with (including its copies
    4204              :    or others derived from it by pointer arithmetic).  If STMT is a clobber,
    4205              :    VAR is the decl of the clobbered variable.  When MAYBE is true use
    4206              :    a "maybe" form of diagnostic.  */
    4207              : 
    4208              : void
    4209       568609 : pass_waccess::check_pointer_uses (gimple *stmt, tree ptr,
    4210              :                                   tree var /* = NULL_TREE */,
    4211              :                                   bool maybe /* = false */)
    4212              : {
    4213       568609 :   gcc_assert (TREE_CODE (ptr) == SSA_NAME);
    4214              : 
    4215       568609 :   const bool check_dangling = !is_gimple_call (stmt);
    4216       568609 :   basic_block stmt_bb = gimple_bb (stmt);
    4217              : 
    4218              :   /* If STMT is a reallocation function set to the reallocated pointer
    4219              :      and the LHS of the call, respectively.  */
    4220       568609 :   tree realloc_ptr = NULL_TREE;
    4221       568609 :   tree realloc_lhs = get_realloc_lhs (stmt, &realloc_ptr);
    4222              : 
    4223       568609 :   auto_bitmap visited;
    4224              : 
    4225       568609 :   auto_vec<tree, 8> pointers;
    4226       568609 :   pointers.quick_push (ptr);
    4227       568609 :   hash_map<tree, int> *phi_map = nullptr;
    4228              : 
    4229              :   /* Starting with PTR, iterate over POINTERS added by the loop, and
    4230              :      either warn for their uses in basic blocks dominated by the STMT
    4231              :      or in statements that follow it in the same basic block, or add
    4232              :      them to POINTERS if they point into the same object as PTR (i.e.,
    4233              :      are obtained by pointer arithmetic on PTR).  */
    4234      2605634 :   for (unsigned i = 0; i != pointers.length (); ++i)
    4235              :     {
    4236       734208 :       tree ptr = pointers[i];
    4237       734208 :       if (!bitmap_set_bit (visited, SSA_NAME_VERSION (ptr)))
    4238              :         /* Avoid revisiting the same pointer.  */
    4239           43 :         continue;
    4240              : 
    4241       734165 :       use_operand_p use_p;
    4242       734165 :       imm_use_iterator iter;
    4243      4626338 :       FOR_EACH_IMM_USE_FAST (use_p, iter, ptr)
    4244              :         {
    4245      3158008 :           gimple *use_stmt = USE_STMT (use_p);
    4246      3158008 :           if (use_stmt == stmt || is_gimple_debug (use_stmt))
    4247      1391458 :             continue;
    4248              : 
    4249              :           /* A clobber isn't a use.  */
    4250      1766550 :           if (gimple_clobber_p (use_stmt))
    4251        62820 :             continue;
    4252              : 
    4253      1703730 :           if (realloc_lhs)
    4254              :             {
    4255              :               /* Check to see if USE_STMT is a mismatched deallocation
    4256              :                  call for the pointer passed to realloc.  That's a bug
    4257              :                  regardless of the pointer's value and so warn.  */
    4258        83077 :               if (maybe_warn_mismatched_realloc (*use_p->use, stmt, use_stmt))
    4259          149 :                 continue;
    4260              : 
    4261              :               /* Pointers passed to realloc that are used in basic blocks
    4262              :                  where the realloc call is known to have failed are valid.
    4263              :                  Ignore pointers that nothing is known about.  Those could
    4264              :                  have escaped along with their nullness.  */
    4265        83038 :               prange vr;
    4266        83038 :               if (m_ptr_qry.rvals->range_of_expr (vr, realloc_lhs, use_stmt))
    4267              :                 {
    4268        83038 :                   if (vr.zero_p ())
    4269          110 :                     continue;
    4270              : 
    4271        82928 :                   if (!pointers_related_p (stmt, ptr, realloc_ptr, m_ptr_qry))
    4272            0 :                     continue;
    4273              :                 }
    4274        83038 :             }
    4275              : 
    4276      1703790 :           if (check_dangling
    4277      1703581 :               && gimple_code (use_stmt) == GIMPLE_RETURN)
    4278              :             /* Avoid interfering with -Wreturn-local-addr (which runs only
    4279              :                with optimization enabled so it won't diagnose cases that
    4280              :                would be caught here when optimization is disabled).  */
    4281          209 :             continue;
    4282              : 
    4283      1703372 :           bool equality = false;
    4284      1703372 :           if (is_gimple_assign (use_stmt))
    4285              :             {
    4286       984276 :               tree_code code = gimple_assign_rhs_code (use_stmt);
    4287       984276 :               equality = code == EQ_EXPR || code == NE_EXPR;
    4288              :             }
    4289       719096 :           else if (gcond *cond = dyn_cast<gcond *>(use_stmt))
    4290              :             {
    4291       209716 :               tree_code code = gimple_cond_code (cond);
    4292       209716 :               equality = code == EQ_EXPR || code == NE_EXPR;
    4293              :             }
    4294       509380 :           else if (gphi *phi = dyn_cast <gphi *> (use_stmt))
    4295              :             {
    4296              :               /* Only add a PHI result to POINTERS if all its
    4297              :                  operands are related to PTR, otherwise continue.  The
    4298              :                  PHI result is related once we've reached all arguments
    4299              :                  through this iteration.  That also means any invariant
    4300              :                  argument will make the PHI not related.  For arguments
    4301              :                  flowing over natural loop backedges we are optimistic
    4302              :                  (and diagnose the first iteration).  */
    4303       132507 :               tree lhs = gimple_phi_result (phi);
    4304       132507 :               if (!phi_map)
    4305        47358 :                 phi_map = new hash_map<tree, int>;
    4306       132507 :               bool existed_p;
    4307       132507 :               int &related = phi_map->get_or_insert (lhs, &existed_p);
    4308       132507 :               if (!existed_p)
    4309              :                 {
    4310        70478 :                   related = gimple_phi_num_args (phi) - 1;
    4311       348253 :                   for (unsigned j = 0; j < gimple_phi_num_args (phi); ++j)
    4312              :                     {
    4313       277775 :                       if ((unsigned) phi_arg_index_from_use (use_p) == j)
    4314        70478 :                         continue;
    4315       207297 :                       tree arg = gimple_phi_arg_def (phi, j);
    4316       207297 :                       edge e = gimple_phi_arg_edge (phi, j);
    4317       207297 :                       basic_block arg_bb;
    4318       207297 :                       if (dominated_by_p (CDI_DOMINATORS, e->src, e->dest)
    4319              :                           /* Make sure we are not forward visiting a
    4320              :                              backedge argument.  */
    4321       207297 :                           && (TREE_CODE (arg) != SSA_NAME
    4322        25665 :                               || (!SSA_NAME_IS_DEFAULT_DEF (arg)
    4323        25665 :                                   && ((arg_bb
    4324        25665 :                                          = gimple_bb (SSA_NAME_DEF_STMT (arg)))
    4325        25665 :                                       != e->dest)
    4326        13567 :                                   && !dominated_by_p (CDI_DOMINATORS,
    4327              :                                                       e->dest, arg_bb))))
    4328        13567 :                         related--;
    4329              :                     }
    4330              :                 }
    4331              :               else
    4332        62029 :                 related--;
    4333              : 
    4334       132507 :               if (related == 0)
    4335        20794 :                 pointers.safe_push (lhs);
    4336       132507 :               continue;
    4337       132507 :             }
    4338              : 
    4339              :           /* Warn if USE_STMT is dominated by the deallocation STMT.
    4340              :              Otherwise, add the pointer to POINTERS so that the uses
    4341              :              of any other pointers derived from it can be checked.  */
    4342      1570865 :           if (use_after_inval_p (stmt, use_stmt, check_dangling))
    4343              :             {
    4344        18027 :               basic_block use_bb = gimple_bb (use_stmt);
    4345        18027 :               bool this_maybe
    4346              :                 = (maybe
    4347        18027 :                    || !dominated_by_p (CDI_POST_DOMINATORS, stmt_bb, use_bb));
    4348        18027 :               warn_invalid_pointer (*use_p->use, use_stmt, stmt, var,
    4349              :                                     this_maybe, equality);
    4350        18027 :               continue;
    4351        18027 :             }
    4352              : 
    4353      1552838 :           if (is_gimple_assign (use_stmt))
    4354              :             {
    4355       982430 :               tree lhs = gimple_assign_lhs (use_stmt);
    4356       982430 :               if (TREE_CODE (lhs) == SSA_NAME)
    4357              :                 {
    4358       650447 :                   tree_code rhs_code = gimple_assign_rhs_code (use_stmt);
    4359       650447 :                   if (rhs_code == POINTER_PLUS_EXPR || rhs_code == SSA_NAME)
    4360       143475 :                     pointers.safe_push (lhs);
    4361              :                 }
    4362       982430 :               continue;
    4363       982430 :             }
    4364              : 
    4365      3728416 :           if (gcall *call = dyn_cast <gcall *>(use_stmt))
    4366              :             {
    4367       359893 :               if (gimple_call_return_arg (call) == ptr)
    4368        36272 :                 if (tree lhs = gimple_call_lhs (call))
    4369         1330 :                   if (TREE_CODE (lhs) == SSA_NAME)
    4370         1330 :                     pointers.safe_push (lhs);
    4371       359893 :               continue;
    4372       359893 :             }
    4373       734165 :         }
    4374              :     }
    4375              : 
    4376       568609 :   if (phi_map)
    4377        47358 :     delete phi_map;
    4378       568609 : }
    4379              : 
    4380              : /* Check call STMT for invalid accesses.  */
    4381              : 
    4382              : void
    4383     22978828 : pass_waccess::check_call (gcall *stmt)
    4384              : {
    4385              :   /* Skip special calls generated by the compiler.  */
    4386     22978828 :   if (gimple_call_from_thunk_p (stmt))
    4387              :     return;
    4388              : 
    4389              :   /* .ASAN_MARK doesn't access any vars, only modifies shadow memory.  */
    4390     22975836 :   if (gimple_call_internal_p (stmt)
    4391     22975836 :       && gimple_call_internal_fn (stmt) == IFN_ASAN_MARK)
    4392              :     return;
    4393              : 
    4394     22963286 :   if (m_check_dangling_p)
    4395              :     {
    4396     16118358 :       check_call_dangling (stmt);
    4397              : 
    4398              :       /* Don't do any other checks when doing dangling pointer checks the
    4399              :          second time.  */
    4400     16118358 :       if (!m_early_checks_p)
    4401              :         return;
    4402              :     }
    4403              : 
    4404     17142495 :   if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
    4405      3554216 :     check_builtin (stmt);
    4406              : 
    4407     17142495 :   if (tree callee = gimple_call_fndecl (stmt))
    4408              :     {
    4409              :       /* Check for uses of the pointer passed to either a standard
    4410              :          or a user-defined deallocation function.  */
    4411     16085375 :       unsigned argno = fndecl_dealloc_argno (callee);
    4412     16085375 :       if (argno < (unsigned) call_nargs (stmt))
    4413              :         {
    4414       327866 :           tree arg = call_arg (stmt, argno);
    4415       327866 :           if (TREE_CODE (arg) == SSA_NAME)
    4416       327556 :             check_pointer_uses (stmt, arg);
    4417              :         }
    4418              :     }
    4419              : 
    4420     17142495 :   check_call_access (stmt);
    4421              : 
    4422     17142495 :   if (m_early_checks_p)
    4423              :     return;
    4424              : 
    4425      6844928 :   maybe_check_dealloc_call (stmt);
    4426      6844928 :   check_nonstring_args (stmt);
    4427              : }
    4428              : 
    4429              : /* Check non-call STMT for invalid accesses.  */
    4430              : 
    4431              : void
    4432    132345833 : pass_waccess::check_stmt (gimple *stmt)
    4433              : {
    4434    132345833 :   if (m_check_dangling_p
    4435    132345833 :       && gimple_clobber_p (stmt, CLOBBER_STORAGE_END))
    4436              :     {
    4437              :       /* Ignore clobber statements in blocks with exceptional edges.  */
    4438      3352878 :       basic_block bb = gimple_bb (stmt);
    4439      3352878 :       edge e = EDGE_PRED (bb, 0);
    4440      3352878 :       if (e->flags & EDGE_EH)
    4441              :         return;
    4442              : 
    4443      2591897 :       tree var = gimple_assign_lhs (stmt);
    4444      2591897 :       m_clobbers.put (var, stmt);
    4445      2591897 :       return;
    4446              :     }
    4447              : 
    4448    128992955 :   if (is_gimple_assign (stmt))
    4449              :     {
    4450              :       /* Clobbered unnamed temporaries such as compound literals can be
    4451              :          revived.  Check for an assignment to one and remove it from
    4452              :          M_CLOBBERS.  */
    4453     95987696 :       tree lhs = gimple_assign_lhs (stmt);
    4454    119782484 :       while (handled_component_p (lhs))
    4455     23794788 :         lhs = TREE_OPERAND (lhs, 0);
    4456              : 
    4457     95987696 :       if (auto_var_p (lhs))
    4458     15497510 :         m_clobbers.remove (lhs);
    4459     95987696 :       return;
    4460              :     }
    4461              : 
    4462     33005259 :   if (greturn *ret = dyn_cast <greturn *> (stmt))
    4463              :     {
    4464      5272919 :       if (optimize && flag_isolate_erroneous_paths_dereference)
    4465              :         /* Avoid interfering with -Wreturn-local-addr (which runs only
    4466              :            with optimization enabled).  */
    4467      5272918 :         return;
    4468              : 
    4469      1105375 :       tree arg = gimple_return_retval (ret);
    4470      1105375 :       if (!arg || TREE_CODE (arg) != ADDR_EXPR)
    4471              :         return;
    4472              : 
    4473          313 :       arg = TREE_OPERAND (arg, 0);
    4474          421 :       while (handled_component_p (arg))
    4475          108 :         arg = TREE_OPERAND (arg, 0);
    4476              : 
    4477          313 :       if (!auto_var_p (arg))
    4478              :         return;
    4479              : 
    4480            3 :       gimple **pclobber = m_clobbers.get (arg);
    4481            3 :       if (!pclobber)
    4482              :         return;
    4483              : 
    4484            1 :       if (!use_after_inval_p (*pclobber, stmt))
    4485              :         return;
    4486              : 
    4487            1 :       warn_invalid_pointer (NULL_TREE, stmt, *pclobber, arg, false);
    4488              :     }
    4489              : }
    4490              : 
    4491              : /* Check basic block BB for invalid accesses.  */
    4492              : 
    4493              : void
    4494     44245572 : pass_waccess::check_block (basic_block bb)
    4495              : {
    4496              :   /* Iterate over statements, looking for function calls.  */
    4497    243815805 :   for (auto si = gsi_start_bb (bb); !gsi_end_p (si);
    4498    155324661 :        gsi_next_nondebug (&si))
    4499              :     {
    4500    155324661 :       gimple *stmt = gsi_stmt (si);
    4501    155324661 :       if (gcall *call = dyn_cast <gcall *> (stmt))
    4502     22978828 :         check_call (call);
    4503              :       else
    4504    132345833 :         check_stmt (stmt);
    4505              :     }
    4506     44245572 : }
    4507              : 
    4508              : /* Return the argument that the call STMT to a built-in function returns
    4509              :    (including with an offset) or null if it doesn't.  */
    4510              : 
    4511              : tree
    4512      2344676 : pass_waccess::gimple_call_return_arg (gcall *call)
    4513              : {
    4514              :   /* Check for attribute fn spec to see if the function returns one
    4515              :      of its arguments.  */
    4516      2344676 :   attr_fnspec fnspec = gimple_call_fnspec (call);
    4517      2344676 :   unsigned int argno;
    4518      2344676 :   if (!fnspec.returns_arg (&argno))
    4519              :     {
    4520      2270645 :       if (gimple_call_num_args (call) < 1)
    4521              :         return NULL_TREE;
    4522              : 
    4523      2201888 :       if (!gimple_call_builtin_p (call, BUILT_IN_NORMAL))
    4524              :         return NULL_TREE;
    4525              : 
    4526       295639 :       tree fndecl = gimple_call_fndecl (call);
    4527       295639 :       switch (DECL_FUNCTION_CODE (fndecl))
    4528              :         {
    4529              :         case BUILT_IN_MEMPCPY:
    4530              :         case BUILT_IN_MEMPCPY_CHK:
    4531              :         case BUILT_IN_MEMCHR:
    4532              :         case BUILT_IN_STRCHR:
    4533              :         case BUILT_IN_STRRCHR:
    4534              :         case BUILT_IN_STRSTR:
    4535              :         case BUILT_IN_STPCPY:
    4536              :         case BUILT_IN_STPCPY_CHK:
    4537              :         case BUILT_IN_STPNCPY:
    4538              :         case BUILT_IN_STPNCPY_CHK:
    4539              :           argno = 0;
    4540              :           break;
    4541              : 
    4542              :         default:
    4543              :           return NULL_TREE;
    4544              :         }
    4545              :     }
    4546              : 
    4547        89733 :   if (gimple_call_num_args (call) <= argno)
    4548              :     return NULL_TREE;
    4549              : 
    4550        89733 :   return gimple_call_arg (call, argno);
    4551              : }
    4552              : 
    4553              : /* Check for and diagnose all uses of the dangling pointer VAR to the auto
    4554              :    object DECL whose lifetime has ended.  OBJREF is true when VAR denotes
    4555              :    an access to a DECL that may have been clobbered.  */
    4556              : 
    4557              : void
    4558     14641991 : pass_waccess::check_dangling_uses (tree var, tree decl, bool maybe /* = false */,
    4559              :                                    bool objref /* = false */)
    4560              : {
    4561     14641991 :   if (!decl || !auto_var_p (decl))
    4562      6504068 :     return;
    4563              : 
    4564      8137923 :   gimple **pclob = m_clobbers.get (decl);
    4565      8137923 :   if (!pclob)
    4566              :     return;
    4567              : 
    4568      3632210 :   if (!objref)
    4569              :     {
    4570       174969 :       check_pointer_uses (*pclob, var, decl, maybe);
    4571       174969 :       return;
    4572              :     }
    4573              : 
    4574      3457241 :   gimple *use_stmt = SSA_NAME_DEF_STMT (var);
    4575      3457241 :   if (!use_after_inval_p (*pclob, use_stmt, true))
    4576              :     return;
    4577              : 
    4578           96 :   basic_block use_bb = gimple_bb (use_stmt);
    4579           96 :   basic_block clob_bb = gimple_bb (*pclob);
    4580           96 :   maybe = maybe || !dominated_by_p (CDI_POST_DOMINATORS, clob_bb, use_bb);
    4581           96 :   warn_invalid_pointer (var, use_stmt, *pclob, decl, maybe, false);
    4582              : }
    4583              : 
    4584              : /* Diagnose stores in BB and (recursively) its predecessors of the addresses
    4585              :    of local variables into nonlocal pointers that are left dangling after
    4586              :    the function returns.  Returns true when we can continue walking
    4587              :    the CFG to predecessors.  */
    4588              : 
    4589              : bool
    4590     15730471 : pass_waccess::check_dangling_stores (basic_block bb,
    4591              :                                      hash_set<tree> &stores)
    4592              : {
    4593              :   /* Iterate backwards over the statements looking for a store of
    4594              :      the address of a local variable into a nonlocal pointer.  */
    4595     52949139 :   for (auto gsi = gsi_last_nondebug_bb (bb); ; gsi_prev_nondebug (&gsi))
    4596              :     {
    4597     52949139 :       gimple *stmt = gsi_stmt (gsi);
    4598     52949139 :       if (!stmt)
    4599              :         break;
    4600              : 
    4601     41069759 :       if (warning_suppressed_p (stmt, OPT_Wdangling_pointer_))
    4602     37218049 :         continue;
    4603              : 
    4604     41013862 :       if (is_gimple_call (stmt)
    4605     41013862 :           && !(gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE)))
    4606              :         /* Avoid looking before nonconst, nonpure calls since those might
    4607              :            use the escaped locals.  */
    4608      3851091 :         return false;
    4609              : 
    4610     37322245 :       if (!is_gimple_assign (stmt) || gimple_clobber_p (stmt)
    4611     61819587 :           || !gimple_store_p (stmt))
    4612     32086293 :         continue;
    4613              : 
    4614      5235952 :       access_ref lhs_ref;
    4615      5235952 :       tree lhs = gimple_assign_lhs (stmt);
    4616      5235952 :       if (!m_ptr_qry.get_ref (lhs, stmt, &lhs_ref, 0))
    4617         9350 :         continue;
    4618              : 
    4619      5226602 :       if (TREE_CODE (lhs_ref.ref) == MEM_REF)
    4620              :         {
    4621        23369 :           lhs_ref.ref = TREE_OPERAND (lhs_ref.ref, 0);
    4622        23369 :           ++lhs_ref.deref;
    4623              :         }
    4624      5226602 :       if (TREE_CODE (lhs_ref.ref) == ADDR_EXPR)
    4625              :         {
    4626        10646 :           lhs_ref.ref = TREE_OPERAND (lhs_ref.ref, 0);
    4627        10646 :           --lhs_ref.deref;
    4628              :         }
    4629      5226602 :       if (TREE_CODE (lhs_ref.ref) == SSA_NAME)
    4630              :         {
    4631      1072420 :           gimple *def_stmt = SSA_NAME_DEF_STMT (lhs_ref.ref);
    4632      1072420 :           if (!gimple_nop_p (def_stmt))
    4633              :             /* Avoid looking at or before stores into unknown objects.  */
    4634              :             return false;
    4635              : 
    4636       912946 :           lhs_ref.ref = SSA_NAME_VAR (lhs_ref.ref);
    4637              :         }
    4638              : 
    4639      5067128 :       if (TREE_CODE (lhs_ref.ref) == PARM_DECL
    4640      5067128 :           && (lhs_ref.deref - DECL_BY_REFERENCE (lhs_ref.ref)) > 0)
    4641              :         /* Assignment through a (real) pointer/reference parameter.  */;
    4642      7397600 :       else if (VAR_P (lhs_ref.ref)
    4643      4219689 :                && !auto_var_p (lhs_ref.ref))
    4644              :         /* Assignment to/through a non-local variable.  */;
    4645              :       else
    4646              :         /* Something else, don't warn.  */
    4647      3177911 :         continue;
    4648              : 
    4649      1889217 :       if (stores.add (lhs_ref.ref))
    4650      1291132 :         continue;
    4651              : 
    4652              :       /* FIXME: Handle stores of alloca() and VLA.  */
    4653       598085 :       access_ref rhs_ref;
    4654       598085 :       tree rhs = gimple_assign_rhs1 (stmt);
    4655       598085 :       if (!m_ptr_qry.get_ref (rhs, stmt, &rhs_ref, 0)
    4656       598085 :           || rhs_ref.deref != -1)
    4657       570562 :         continue;
    4658              : 
    4659        27523 :       if (!auto_var_p (rhs_ref.ref))
    4660        26904 :         continue;
    4661              : 
    4662          619 :       auto_diagnostic_group d;
    4663          619 :       location_t loc = gimple_location (stmt);
    4664          619 :       if (warning_at (loc, OPT_Wdangling_pointer_,
    4665              :                       "storing the address of local variable %qD in %qE",
    4666              :                       rhs_ref.ref, lhs))
    4667              :         {
    4668           45 :           suppress_warning (stmt, OPT_Wdangling_pointer_);
    4669              : 
    4670           45 :           location_t loc = DECL_SOURCE_LOCATION (rhs_ref.ref);
    4671           45 :           inform (loc, "%qD declared here", rhs_ref.ref);
    4672              : 
    4673           45 :           loc = DECL_SOURCE_LOCATION (lhs_ref.ref);
    4674           45 :           inform (loc, "%qD declared here", lhs_ref.ref);
    4675              :         }
    4676     37219287 :     }
    4677              : 
    4678     11879380 :   return true;
    4679              : }
    4680              : 
    4681              : /* Diagnose stores of the addresses of local variables into nonlocal
    4682              :    pointers that are left dangling after the function returns.  */
    4683              : 
    4684              : void
    4685      3889864 : pass_waccess::check_dangling_stores ()
    4686              : {
    4687      3889864 :   if (EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (m_func)->preds) == 0)
    4688        58241 :     return;
    4689              : 
    4690      3831623 :   auto_bitmap bbs;
    4691      3831623 :   hash_set<tree> stores;
    4692      3831623 :   auto_vec<edge_iterator, 8> worklist (n_basic_blocks_for_fn (cfun) + 1);
    4693      3831623 :   worklist.quick_push (ei_start (EXIT_BLOCK_PTR_FOR_FN (m_func)->preds));
    4694     34256897 :   do
    4695              :     {
    4696     34256897 :       edge_iterator ei = worklist.last ();
    4697     34256897 :       basic_block src = ei_edge (ei)->src;
    4698     34256897 :       if (bitmap_set_bit (bbs, src->index))
    4699              :         {
    4700     15730471 :           if (check_dangling_stores (src, stores)
    4701     15730471 :               && EDGE_COUNT (src->preds) > 0)
    4702     10323226 :             worklist.quick_push (ei_start (src->preds));
    4703              :         }
    4704              :       else
    4705              :         {
    4706     18526426 :           if (ei_one_before_end_p (ei))
    4707     14154849 :             worklist.pop ();
    4708              :           else
    4709      4371577 :             ei_next (&worklist.last ());
    4710              :         }
    4711              :     }
    4712     68513794 :   while (!worklist.is_empty ());
    4713      3831623 : }
    4714              : 
    4715              : /* Check for and diagnose uses of dangling pointers to auto objects
    4716              :    whose lifetime has ended.  */
    4717              : 
    4718              : void
    4719      3889864 : pass_waccess::check_dangling_uses ()
    4720              : {
    4721      3889864 :   tree var;
    4722      3889864 :   unsigned i;
    4723    114936872 :   FOR_EACH_SSA_NAME (i, var, m_func)
    4724              :     {
    4725              :       /* For each SSA_NAME pointer VAR find the object it points to.
    4726              :          If the object is a clobbered local variable, check to see
    4727              :          if any of VAR's uses (or those of other pointers derived
    4728              :          from VAR) happens after the clobber.  If so, warn.  */
    4729              : 
    4730    106106986 :       gimple *def_stmt = SSA_NAME_DEF_STMT (var);
    4731    106106986 :       if (is_gimple_assign (def_stmt))
    4732              :         {
    4733     67824567 :           tree rhs = gimple_assign_rhs1 (def_stmt);
    4734     67824567 :           if (TREE_CODE (rhs) == ADDR_EXPR)
    4735              :             {
    4736      4551542 :               if (!POINTER_TYPE_P (TREE_TYPE (var)))
    4737      2030438 :                 continue;
    4738      2521104 :               check_dangling_uses (var, TREE_OPERAND (rhs, 0));
    4739              :             }
    4740              :           else
    4741              :             {
    4742              :               /* For other expressions, check the base DECL to see
    4743              :                  if it's been clobbered, most likely as a result of
    4744              :                  inlining a reference to it.  */
    4745     63273025 :               tree decl = get_base_address (rhs);
    4746     63273025 :               if (DECL_P (decl))
    4747     11891589 :                 check_dangling_uses (var, decl, false, true);
    4748              :             }
    4749              :         }
    4750     38282419 :       else if (POINTER_TYPE_P (TREE_TYPE (var)))
    4751              :         {
    4752      6317315 :           if (gcall *call = dyn_cast<gcall *>(def_stmt))
    4753              :             {
    4754      1984783 :               if (tree arg = gimple_call_return_arg (call))
    4755              :                 {
    4756        31959 :                   access_ref aref;
    4757        31959 :                   if (m_ptr_qry.get_ref (arg, call, &aref, 0)
    4758        31959 :                       && aref.deref < 0)
    4759         9551 :                     check_dangling_uses (var, aref.ref);
    4760              :                 }
    4761              :             }
    4762    111656453 :           else if (gphi *phi = dyn_cast <gphi *>(def_stmt))
    4763              :             {
    4764       609445 :               unsigned nargs = gimple_phi_num_args (phi);
    4765      2094356 :               for (unsigned i = 0; i != nargs; ++i)
    4766              :                 {
    4767      1484911 :                   access_ref aref;
    4768      1484911 :                   tree arg = gimple_phi_arg_def (phi, i);
    4769      1484911 :                   if (m_ptr_qry.get_ref (arg, phi, &aref, 0)
    4770      1484911 :                       && aref.deref < 0)
    4771       219747 :                     check_dangling_uses (var, aref.ref, true);
    4772              :                 }
    4773              :             }
    4774              :         }
    4775              :     }
    4776      3889864 : }
    4777              : 
    4778              : /* Check CALL arguments for dangling pointers (those that have been
    4779              :    clobbered) and warn if found.  */
    4780              : 
    4781              : void
    4782     16118358 : pass_waccess::check_call_dangling (gcall *call)
    4783              : {
    4784     16118358 :   unsigned nargs = gimple_call_num_args (call);
    4785     47050956 :   for (unsigned i = 0; i != nargs; ++i)
    4786              :     {
    4787     30932598 :       tree arg = gimple_call_arg (call, i);
    4788     30932598 :       if (TREE_CODE (arg) != ADDR_EXPR)
    4789     30932572 :         continue;
    4790              : 
    4791      8586030 :       arg = TREE_OPERAND (arg, 0);
    4792      8586030 :       if (!DECL_P (arg))
    4793      2835801 :         continue;
    4794              : 
    4795      5750229 :       gimple **pclobber = m_clobbers.get (arg);
    4796      5750229 :       if (!pclobber)
    4797      5573924 :         continue;
    4798              : 
    4799       176305 :       if (!use_after_inval_p (*pclobber, call))
    4800       176279 :         continue;
    4801              : 
    4802           26 :       warn_invalid_pointer (NULL_TREE, call, *pclobber, arg, false);
    4803              :     }
    4804     16118358 : }
    4805              : 
    4806              : /* Check function FUN for invalid accesses.  */
    4807              : 
    4808              : unsigned
    4809      5361948 : pass_waccess::execute (function *fun)
    4810              : {
    4811      5361948 :   auto_urlify_attributes sentinel;
    4812              : 
    4813      5361948 :   calculate_dominance_info (CDI_DOMINATORS);
    4814      5361948 :   calculate_dominance_info (CDI_POST_DOMINATORS);
    4815              : 
    4816              :   /* Set or clear EDGE_DFS_BACK bits on back edges.  */
    4817      5361948 :   mark_dfs_back_edges (fun);
    4818              : 
    4819              :   /* Create a new ranger instance and associate it with FUN.  */
    4820      5361948 :   m_ptr_qry.rvals = enable_ranger (fun);
    4821      5361948 :   m_func = fun;
    4822              : 
    4823      5361948 :   auto_bitmap bb_uids_set (&bitmap_default_obstack);
    4824      5361948 :   m_bb_uids_set = bb_uids_set;
    4825              : 
    4826      5361948 :   set_gimple_stmt_max_uid (m_func, 0);
    4827              : 
    4828      5361948 :   basic_block bb;
    4829     49607520 :   FOR_EACH_BB_FN (bb, fun)
    4830     44245572 :     check_block (bb);
    4831              : 
    4832      5361948 :   if (m_check_dangling_p)
    4833              :     {
    4834      3889864 :       check_dangling_uses ();
    4835      3889864 :       check_dangling_stores ();
    4836              :     }
    4837              : 
    4838      5361948 :   if (dump_file)
    4839          167 :     m_ptr_qry.dump (dump_file, (dump_flags & TDF_DETAILS) != 0);
    4840              : 
    4841      5361948 :   m_ptr_qry.flush_cache ();
    4842              : 
    4843              :   /* Release the ranger instance and replace it with a global ranger.
    4844              :      Also reset the pointer since calling disable_ranger() deletes it.  */
    4845      5361948 :   disable_ranger (fun);
    4846      5361948 :   m_ptr_qry.rvals = NULL;
    4847              : 
    4848      5361948 :   m_clobbers.empty ();
    4849      5361948 :   m_bb_uids_set = NULL;
    4850              : 
    4851      5361948 :   free_dominance_info (CDI_POST_DOMINATORS);
    4852      5361948 :   free_dominance_info (CDI_DOMINATORS);
    4853      5361948 :   return 0;
    4854      5361948 : }
    4855              : 
    4856              : }   // namespace
    4857              : 
    4858              : /* Return a new instance of the pass.  */
    4859              : 
    4860              : gimple_opt_pass *
    4861       285722 : make_pass_warn_access (gcc::context *ctxt)
    4862              : {
    4863       285722 :   return new pass_waccess (ctxt);
    4864              : }
        

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.