LCOV - code coverage report
Current view: top level - gcc - gimple-ssa-warn-access.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.9 % 1962 1842
Test Date: 2026-04-20 14:57:17 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      2059234 : get_location (const gimple *stmt)
      80              : {
      81      1875642 :   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      1070596 : get_callee_fndecl (const gimple *stmt)
     102              : {
     103          623 :   return gimple_call_fndecl (stmt);
     104              : }
     105              : 
     106              : static inline unsigned
     107     27874349 : call_nargs (const gimple *stmt)
     108              : {
     109      2190611 :   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     10062392 : call_arg (const gimple *stmt, unsigned argno)
     121              : {
     122      1367404 :   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       623839 : 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       623839 :   c_strlen_data lendata = { };
     278       623839 :   tree len = c_strlen (exp, 1, &lendata);
     279       623839 :   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       617588 : 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       617588 :   tree nonstr = unterminated_array (src, &size, &exact);
     328       617588 :   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       322524 : check_nul_terminated_array (gimple *stmt, tree src, tree bound /* = NULL_TREE */)
     366              : {
     367       322524 :   return check_nul_terminated_array<gimple *>(stmt, src, bound);
     368              : }
     369              : 
     370              : bool
     371       282608 : check_nul_terminated_array (tree expr, tree src, tree bound /* = NULL_TREE */)
     372              : {
     373       282608 :   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      7261037 : maybe_warn_nonstring_arg (tree fndecl, GimpleOrTree exp)
     383              : {
     384      7261037 :   if (!fndecl || !fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
     385              :     return false;
     386              : 
     387      2202748 :   if (!warn_stringop_overread
     388      2202748 :       || warning_suppressed_p (exp, OPT_Wstringop_overread))
     389        11781 :     return false;
     390              : 
     391              :   /* Avoid clearly invalid calls (more checking done below).  */
     392      2190967 :   unsigned nargs = call_nargs (exp);
     393      2190967 :   if (!nargs)
     394              :     return false;
     395              : 
     396              :   /* The bound argument to a bounded string function like strncpy.  */
     397      1875019 :   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      1875019 :   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      1875019 :   int fncode = DECL_FUNCTION_CODE (fndecl);
     410      1875019 :   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       392450 :         for (unsigned argno = 0;
     422       783978 :              argno < MIN (nargs, 2)
     423       783978 :                && !(maxlen && TREE_CODE (maxlen) == INTEGER_CST); argno++)
     424              :           {
     425       392450 :             tree arg = call_arg (exp, argno);
     426       392450 :             if (!get_attr_nonstring_decl (arg))
     427              :               {
     428       391510 :                 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       391510 :                 lendata.maxbound = arg;
     433       391510 :                 get_range_strlen (arg, &lendata, /* eltsize = */ 1);
     434       391510 :                 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       397519 :       if (nargs > 2)
     444        11368 :         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      1875019 :   tree bndrng[2] = { NULL_TREE, NULL_TREE };
     477      1875019 :   if (bound)
     478              :     {
     479        13560 :       STRIP_NOPS (bound);
     480        13560 :       get_size_range (bound, bndrng);
     481              :     }
     482              : 
     483      1875019 :   location_t loc = get_location (exp);
     484              : 
     485      1875019 :   if (bndrng[0])
     486              :     {
     487              :       /* Diagnose excessive bound prior to the adjustment below and
     488              :          regardless of attribute nonstring.  */
     489        13540 :       tree maxobjsize = max_object_size ();
     490        13540 :       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      1874888 :   if (maxlen && !integer_all_onesp (maxlen))
     514              :     {
     515              :       /* Add one for the nul.  */
     516         6956 :       maxlen = const_binop (PLUS_EXPR, TREE_TYPE (maxlen), maxlen,
     517              :                             size_one_node);
     518              : 
     519         6956 :       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         2364 :       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         2355 :           if (tree_int_cst_lt (maxlen, bndrng[0]))
     532          200 :             bndrng[0] = maxlen;
     533         2155 :           else if (tree_int_cst_lt (maxlen, bndrng[1]))
     534          527 :             bndrng[1] = maxlen;
     535              :         }
     536              :     }
     537              : 
     538      1874888 :   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      1874888 :   function_args_iter_init (&it, TREE_TYPE (fndecl));
     545              : 
     546      5936710 :   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      5933756 :       if (argno >= nargs)
     551              :         break;
     552              : 
     553      4218536 :       tree argtype = function_args_iter_cond (&it);
     554      4218536 :       if (!argtype)
     555              :         break;
     556              : 
     557      4058868 :       if (!POINTER_TYPE_P (argtype))
     558      4055914 :         continue;
     559              : 
     560      2491682 :       argtype = TREE_TYPE (argtype);
     561              : 
     562      3997186 :       if (TREE_CODE (argtype) != INTEGER_TYPE
     563      2491682 :           || !TYPE_READONLY (argtype))
     564      1505504 :         continue;
     565              : 
     566       986178 :       argtype = TYPE_MAIN_VARIANT (argtype);
     567       986178 :       if (argtype != char_type_node)
     568        11410 :         continue;
     569              : 
     570       974768 :       tree callarg = call_arg (exp, argno);
     571       974768 :       if (TREE_CODE (callarg) == ADDR_EXPR)
     572       538727 :         callarg = TREE_OPERAND (callarg, 0);
     573              : 
     574              :       /* See if the destination is declared with attribute "nonstring".  */
     575       974768 :       tree decl = get_attr_nonstring_decl (callarg);
     576       974768 :       if (!decl)
     577       971814 :         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      1874888 :   if (any_arg_warned)
     690          897 :     suppress_warning (exp, OPT_Wstringop_overread);
     691              : 
     692              :   return any_arg_warned;
     693              : }
     694              : 
     695              : bool
     696       360552 : maybe_warn_nonstring_arg (tree fndecl, gimple *stmt)
     697              : {
     698       360552 :   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         2170 : 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         2170 :   bool warned = false;
     949              : 
     950         2170 :   rich_location_with_details richloc (loc, exp);
     951              : 
     952         2170 :   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         2032 :   if (write)
    1019              :     {
    1020         1180 :       if (tree_int_cst_equal (range[0], range[1]))
    1021         1069 :         warned = (func
    1022         2136 :                   ? 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         1071 :                   : 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         1180 :       return warned;
    1086              :     }
    1087              : 
    1088          852 :   if (read)
    1089              :     {
    1090          849 :       if (tree_int_cst_equal (range[0], range[1]))
    1091          517 :         warned = (func
    1092         1032 :                   ? 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          519 :                   : 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          849 :       if (warned)
    1155          401 :         suppress_warning (exp, OPT_Wstringop_overread);
    1156              : 
    1157          849 :       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         2170 : }
    1202              : 
    1203              : static bool
    1204         1715 : 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      1283938 : get_size_range (range_query *query, tree bound, gimple *stmt, tree range[2],
    1224              :                 int flags, const offset_int bndrng[2])
    1225              : {
    1226      1283938 :   if (bound)
    1227       498362 :     get_size_range (query, bound, stmt, range, flags);
    1228              : 
    1229      1283938 :   if (!bndrng || (bndrng[0] == 0 && bndrng[1] == HOST_WIDE_INT_M1U))
    1230       918354 :     return;
    1231              : 
    1232       365584 :   if (range[0] && TREE_CODE (range[0]) == INTEGER_CST)
    1233              :     {
    1234       365548 :       offset_int r[] =
    1235       365548 :         { wi::to_offset (range[0]), wi::to_offset (range[1]) };
    1236       365548 :       if (r[0] < bndrng[0])
    1237            0 :         range[0] = wide_int_to_tree (sizetype, bndrng[0]);
    1238       365548 :       if (bndrng[1] < r[1])
    1239            3 :         range[1] = wide_int_to_tree (sizetype, bndrng[1]);
    1240       365548 :     }
    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       744701 : 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       744701 :   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       744701 :   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       744701 :   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       744701 :   bool at_least_one = false;
    1305       744701 :   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       450106 :       if (POINTER_TYPE_P (TREE_TYPE (srcstr)))
    1310              :         {
    1311       329187 :           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       328637 :           c_strlen_data lendata = { };
    1322       328637 :           get_range_strlen (srcstr, &lendata, /* eltsize = */ 1);
    1323       328637 :           range[0] = lendata.minlen;
    1324       328637 :           range[1] = lendata.maxbound ? lendata.maxbound : lendata.maxlen;
    1325       328637 :           if (range[0]
    1326       328637 :               && TREE_CODE (range[0]) == INTEGER_CST
    1327       328632 :               && TREE_CODE (range[1]) == INTEGER_CST
    1328       328632 :               && (!maxread || TREE_CODE (maxread) == INTEGER_CST))
    1329              :             {
    1330        29425 :               if (maxread && tree_int_cst_le (maxread, range[0]))
    1331          401 :                 range[0] = range[1] = maxread;
    1332              :               else
    1333       316880 :                 range[0] = fold_build2 (PLUS_EXPR, size_type_node,
    1334              :                                         range[0], size_one_node);
    1335              : 
    1336       317281 :               if (maxread && tree_int_cst_le (maxread, range[1]))
    1337        12395 :                 range[1] = maxread;
    1338       304886 :               else if (!integer_all_onesp (range[1]))
    1339       158160 :                 range[1] = fold_build2 (PLUS_EXPR, size_type_node,
    1340              :                                         range[1], size_one_node);
    1341              : 
    1342       317281 :               slen = range[0];
    1343              :             }
    1344              :           else
    1345              :             {
    1346        11356 :               at_least_one = true;
    1347        11356 :               slen = size_one_node;
    1348              :             }
    1349              :         }
    1350              :       else
    1351              :         slen = srcstr;
    1352              :     }
    1353              : 
    1354       744151 :   if (!dstwrite && !maxread)
    1355              :     {
    1356              :       /* When the only available piece of data is the object size
    1357              :          there is nothing to do.  */
    1358       288000 :       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       287681 :       if (!range[0])
    1364           67 :         dstwrite = slen;
    1365              :     }
    1366              : 
    1367       743832 :   if (!dstsize)
    1368       323272 :     dstsize = maxobjsize;
    1369              : 
    1370              :   /* Set RANGE to that of DSTWRITE if non-null, bounded by PAD->DST_BNDRNG
    1371              :      if valid.  */
    1372       743832 :   gimple *stmt = pad ? pad->stmt : nullptr;
    1373      2229029 :   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       743832 :                   integer_zerop (dstsize) ? SR_ALLOW_ZERO : 0,
    1378              :                   pad ? pad->dst_bndrng : NULL);
    1379              : 
    1380       743832 :   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       743832 :   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       743832 :   if (range[0]
    1390       742672 :       && TREE_CODE (range[0]) == INTEGER_CST
    1391      1486500 :       && 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       743694 :   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       743694 :   if (range[0] || !exactwrite || integer_all_onesp (dstwrite))
    1406              :     {
    1407       743694 :       if (range[0]
    1408       742534 :           && TREE_CODE (range[0]) == INTEGER_CST
    1409      1486224 :           && ((tree_fits_uhwi_p (dstsize)
    1410       742213 :                && tree_int_cst_lt (dstsize, range[0]))
    1411       740920 :               || (dstwrite
    1412       415129 :                   && tree_fits_uhwi_p (dstwrite)
    1413       328918 :                   && tree_int_cst_lt (dstwrite, range[0]))))
    1414              :         {
    1415         1610 :           const opt_code opt = OPT_Wstringop_overflow_;
    1416         1610 :           if (warning_suppressed_p (exp, opt)
    1417         1610 :               || (pad && pad->dst.ref
    1418          905 :                   && warning_suppressed_p (pad->dst.ref, opt)))
    1419          281 :             return false;
    1420              : 
    1421         1329 :           auto_diagnostic_group d;
    1422         1329 :           location_t loc = get_location (exp);
    1423         1329 :           rich_location_with_details richloc (loc, exp);
    1424              : 
    1425         1329 :           bool warned = false;
    1426         1329 :           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         1329 :               const bool read
    1446         1329 :                 = mode == access_read_only || mode == access_read_write;
    1447         1329 :               const bool write
    1448         1329 :                 = mode == access_write_only || mode == access_read_write;
    1449         1329 :               const bool maybe = pad && pad->dst.parmarray;
    1450         1329 :               warned = warn_for_access (loc, func, exp,
    1451              :                                         OPT_Wstringop_overflow_,
    1452              :                                         range, dstsize,
    1453         1329 :                                         write, read && !builtin, maybe);
    1454              :             }
    1455              : 
    1456         1329 :           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         1329 :         }
    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       742084 :   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        41825 :       get_size_range (rvals, maxread, stmt, range, 0,
    1476              :                       pad ? pad->src_bndrng : NULL);
    1477              : 
    1478        41825 :       location_t loc = get_location (exp);
    1479        41825 :       tree size = dstsize;
    1480        41825 :       if (pad && pad->mode == access_read_only)
    1481        38208 :         size = wide_int_to_tree (sizetype, pad->src.size_remaining ());
    1482              : 
    1483        41825 :       if (range[0] && maxread && tree_fits_uhwi_p (size))
    1484              :         {
    1485        41781 :           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        41694 :           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        41520 :       maybe_warn_nonstring_arg (func, exp);
    1503              :     }
    1504              : 
    1505              :   /* Check for reading past the end of SRC.  */
    1506      1483558 :   bool overread = (slen
    1507       741779 :                    && slen == srcstr
    1508       120302 :                    && dstwrite
    1509       119483 :                    && range[0]
    1510       119483 :                    && TREE_CODE (slen) == INTEGER_CST
    1511       861262 :                    && 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       741779 :   if (!overread
    1515       741779 :       && pad
    1516       739660 :       && pad->src.sizrng[1] >= 0
    1517       505589 :       && pad->src.offrng[0] >= 0
    1518      1481439 :       && (pad->src.offrng[1] < 0
    1519       495732 :           || 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       495732 :       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       495732 :       overread = pad->src.sizrng[1] - pad->src.offrng[0] < pad->src_bndrng[0];
    1527       495732 :       range[0] = wide_int_to_tree (sizetype, pad->src_bndrng[0]);
    1528       495732 :       slen = size_zero_node;
    1529              :     }
    1530              : 
    1531       741779 :   if (overread)
    1532              :     {
    1533          936 :       const opt_code opt = OPT_Wstringop_overread;
    1534          936 :       if (warning_suppressed_p (exp, opt)
    1535          869 :           || (srcstr && warning_suppressed_p (srcstr, opt))
    1536         1777 :           || (pad && pad->src.ref
    1537          841 :               && warning_suppressed_p (pad->src.ref, opt)))
    1538           95 :         return false;
    1539              : 
    1540          841 :       location_t loc = get_location (exp);
    1541          841 :       const bool read
    1542          841 :         = mode == access_read_only || mode == access_read_write;
    1543          841 :       const bool maybe = pad && pad->dst.parmarray;
    1544          841 :       auto_diagnostic_group d;
    1545          841 :       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          841 :     }
    1554              : 
    1555              :   return true;
    1556              : }
    1557              : 
    1558              : static bool
    1559       735972 : 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        46259 : fndecl_alloc_p (tree fndecl, bool all_alloc)
    1584              : {
    1585        46259 :   if (!fndecl)
    1586              :     return false;
    1587              : 
    1588              :   /* A call to operator new isn't recognized as one to a built-in.  */
    1589        46014 :   if (DECL_IS_OPERATOR_NEW_P (fndecl))
    1590              :     return true;
    1591              : 
    1592        34126 :   if (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
    1593              :     {
    1594        29618 :       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         4519 :   tree attrs = DECL_ATTRIBUTES (fndecl);
    1617         4519 :   if (!attrs)
    1618              :     return false;
    1619              : 
    1620          103 :   for (tree allocs = attrs;
    1621         1818 :        (allocs = lookup_attribute ("malloc", allocs));
    1622          103 :        allocs = TREE_CHAIN (allocs))
    1623              :     {
    1624         1008 :       tree args = TREE_VALUE (allocs);
    1625         1008 :       if (!args)
    1626          103 :         continue;
    1627              : 
    1628          905 :       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        46259 : gimple_call_alloc_p (gimple *stmt, bool all_alloc = false)
    1640              : {
    1641        46259 :   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        11859 : new_delete_mismatch_p (tree new_decl, tree delete_decl)
    1767              : {
    1768        11859 :   tree new_name = DECL_ASSEMBLER_NAME (new_decl);
    1769        11859 :   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        11859 :   bool certain;
    1776        11859 :   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        44724 : 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        44724 :   enum class alloc_kind_t { none, builtin, user }
    1823        44724 :   alloc_dealloc_kind = alloc_kind_t::none;
    1824              : 
    1825        44724 :   if (DECL_IS_OPERATOR_NEW_P (alloc_decl))
    1826              :     {
    1827        11888 :       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        11859 :         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        32836 :   else if (fndecl_built_in_p (alloc_decl, BUILT_IN_NORMAL))
    1841              :     {
    1842        31919 :       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        30696 :         case BUILT_IN_ALIGNED_ALLOC:
    1861        30696 :         case BUILT_IN_CALLOC:
    1862        30696 :         case BUILT_IN_MALLOC:
    1863        30696 :         case BUILT_IN_REALLOC:
    1864        30696 :         case BUILT_IN_STRDUP:
    1865        30696 :         case BUILT_IN_STRNDUP:
    1866        30696 :           if (DECL_IS_OPERATOR_DELETE_P (dealloc_decl))
    1867              :             return false;
    1868              : 
    1869        30621 :           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          956 :   alloc_kind_t realloc_kind = alloc_kind_t::none;
    1883              : 
    1884          956 :   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          888 :   const bool alloc_builtin = fndecl_built_in_p (alloc_decl, BUILT_IN_NORMAL);
    1910          888 :   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          888 :   for (tree ddats = DECL_ATTRIBUTES (dealloc_decl);
    1918         3146 :        (ddats = lookup_attribute ("*dealloc", ddats));
    1919         2258 :        ddats = TREE_CHAIN (ddats))
    1920              :     {
    1921         2979 :       tree args = TREE_VALUE (ddats);
    1922         2979 :       if (!args)
    1923            0 :         continue;
    1924              : 
    1925         2979 :       tree alloc = TREE_VALUE (args);
    1926         2979 :       if (!alloc)
    1927            0 :         continue;
    1928              : 
    1929         2979 :       if (alloc == DECL_NAME (dealloc_decl))
    1930           44 :         realloc_kind = alloc_kind_t::user;
    1931              : 
    1932         2979 :       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         2979 :       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        44724 : matching_alloc_calls_p (gimple *alloc, tree dealloc_decl)
    2032              : {
    2033        44724 :   tree alloc_decl = gimple_call_fndecl (alloc);
    2034        44724 :   if (!alloc_decl)
    2035              :     return true;
    2036              : 
    2037        44724 :   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       165356 : warn_dealloc_offset (location_t loc, gimple *call, const access_ref &aref)
    2047              : {
    2048       165356 :   if (aref.deref || aref.offrng[0] <= 0 || aref.offrng[1] <= 0)
    2049       165281 :     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       866325 : pass_waccess::pass_waccess (gcc::context *ctxt)
    2224              :   : gimple_opt_pass (pass_data_waccess, ctxt),
    2225       866325 :     m_ptr_qry (NULL),
    2226       866325 :     m_clobbers (),
    2227       866325 :     m_bb_uids_set (),
    2228       866325 :     m_func (),
    2229       866325 :     m_check_dangling_p (),
    2230       866325 :     m_early_checks_p ()
    2231              : {
    2232       866325 : }
    2233              : 
    2234              : /* Return a copy of the pass with RUN_NUMBER one greater than THIS.  */
    2235              : 
    2236              : opt_pass*
    2237       577550 : pass_waccess::clone ()
    2238              : {
    2239       577550 :   return new pass_waccess (m_ctxt);
    2240              : }
    2241              : 
    2242              : /* Release pointer_query cache.  */
    2243              : 
    2244      1556976 : pass_waccess::~pass_waccess ()
    2245              : {
    2246       778488 :   m_ptr_qry.flush_cache ();
    2247      1556976 : }
    2248              : 
    2249              : void
    2250      1732650 : 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      1732650 :   if (n == 0)
    2260       866325 :     m_early_checks_p = param;
    2261       866325 :   else if (n == 1)
    2262       866325 :     m_check_dangling_p = param;
    2263              :   else
    2264            0 :     __builtin_unreachable ();
    2265      1732650 : }
    2266              : 
    2267              : /* Return true when any checks performed by the pass are enabled.  */
    2268              : 
    2269              : bool
    2270      5403177 : pass_waccess::gate (function *)
    2271              : {
    2272      5403177 :   return (warn_free_nonheap_object
    2273          117 :           || warn_mismatched_alloc
    2274      5403294 :           || 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        78555 : alloc_max_size (void)
    2283              : {
    2284        78555 :   HOST_WIDE_INT limit = warn_alloc_size_limit;
    2285        78555 :   if (limit == HOST_WIDE_INT_MAX)
    2286        78159 :     limit = tree_to_shwi (TYPE_MAX_VALUE (ptrdiff_type_node));
    2287              : 
    2288        78555 :   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        78555 : 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        78555 :   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        78555 :   tree maxobjsize = alloc_max_size ();
    2308              : 
    2309        78555 :   location_t loc = get_location (stmt);
    2310              : 
    2311        78555 :   tree fn = gimple_call_fndecl (stmt);
    2312        78555 :   tree fntype = fn ? TREE_TYPE (fn) : gimple_call_fntype (stmt);
    2313        78555 :   bool warned = false;
    2314              : 
    2315              :   /* Validate each argument individually.  */
    2316       158393 :   for (unsigned i = 0; i != 2 && args[i]; ++i)
    2317              :     {
    2318        79838 :       if (TREE_CODE (args[i]) == INTEGER_CST)
    2319              :         {
    2320        39928 :           argrange[i][0] = args[i];
    2321        39928 :           argrange[i][1] = args[i];
    2322              : 
    2323        39928 :           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        39904 :           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        39422 :           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        39910 :       else if (TREE_CODE (args[i]) == SSA_NAME
    2367        39910 :                && 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        39897 :           if (tree_int_cst_lt (argrange[i][0], integer_zero_node)
    2372        39897 :               && 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        39866 :           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        78555 :   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        78322 :   if (!warned && tree_fits_uhwi_p (argrange[0][0])
    2397        78289 :       && argrange[1][0] && tree_fits_uhwi_p (argrange[1][0])
    2398         1183 :       && !integer_onep (argrange[0][0])
    2399        79391 :       && !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        78545 :   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        30966 : pass_waccess::check_alloca (gcall *stmt)
    2454              : {
    2455        30966 :   if (m_early_checks_p)
    2456              :     return;
    2457              : 
    2458        14345 :   if ((warn_vla_limit >= HOST_WIDE_INT_MAX
    2459        14318 :        && warn_alloc_size_limit < warn_vla_limit)
    2460        14335 :       || (warn_alloca_limit >= HOST_WIDE_INT_MAX
    2461        14272 :           && 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      2983430 : pass_waccess::check_alloc_size_call (gcall *stmt)
    2478              : {
    2479      2983430 :   if (m_early_checks_p)
    2480      2904885 :     return;
    2481              : 
    2482      1428372 :   if (gimple_call_num_args (stmt) < 1)
    2483              :     /* Avoid invalid calls to functions without a prototype.  */
    2484              :     return;
    2485              : 
    2486      1190968 :   tree fndecl = gimple_call_fndecl (stmt);
    2487      1190968 :   if (fndecl && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
    2488              :     {
    2489              :       /* Alloca is handled separately.  */
    2490       571300 :       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      1181988 :   tree fntype = gimple_call_fntype (stmt);
    2502      1181988 :   tree fntypeattrs = TYPE_ATTRIBUTES (fntype);
    2503              : 
    2504      1181988 :   tree alloc_size = lookup_attribute ("alloc_size", fntypeattrs);
    2505      1181988 :   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        78550 :   int idx[2] = { -1, -1 };
    2513        78550 :   tree alloc_args[] = { NULL_TREE, NULL_TREE };
    2514        78550 :   unsigned nargs = gimple_call_num_args (stmt);
    2515              : 
    2516        78550 :   tree args = TREE_VALUE (alloc_size);
    2517        78550 :   idx[0] = TREE_INT_CST_LOW (TREE_VALUE (args)) - 1;
    2518              :   /* Avoid invalid calls to functions without a prototype.  */
    2519        78550 :   if ((unsigned) idx[0] >= nargs)
    2520              :     return;
    2521        78545 :   alloc_args[0] = call_arg (stmt, idx[0]);
    2522        78545 :   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        78545 :   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         1669 : pass_waccess::check_strcat (gcall *stmt)
    2537              : {
    2538         1669 :   if (m_early_checks_p)
    2539          944 :     return;
    2540              : 
    2541          725 :   if (!warn_stringop_overflow && !warn_stringop_overread)
    2542              :     return;
    2543              : 
    2544          725 :   tree dest = call_arg (stmt, 0);
    2545          725 :   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          725 :   access_data data (m_ptr_qry.rvals, stmt, access_read_write, NULL_TREE,
    2552          725 :                     true, NULL_TREE, true);
    2553          725 :   const int ost = warn_stringop_overflow ? warn_stringop_overflow - 1 : 1;
    2554          725 :   compute_objsize (src, stmt, ost, &data.src, &m_ptr_qry);
    2555          725 :   tree destsize = compute_objsize (dest, stmt, ost, &data.dst, &m_ptr_qry);
    2556              : 
    2557          725 :   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         7246 : pass_waccess::check_stxcpy (gcall *stmt)
    2639              : {
    2640         7246 :   if (m_early_checks_p)
    2641         4406 :     return;
    2642              : 
    2643         2982 :   tree dst = call_arg (stmt, 0);
    2644         2982 :   tree src = call_arg (stmt, 1);
    2645              : 
    2646         2982 :   tree size;
    2647         2982 :   bool exact;
    2648         2982 :   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         2840 :   if (warn_stringop_overflow)
    2657              :     {
    2658         2635 :       access_data data (m_ptr_qry.rvals, stmt, access_read_write, NULL_TREE,
    2659         2635 :                         true, NULL_TREE, true);
    2660         2635 :       const int ost = warn_stringop_overflow ? warn_stringop_overflow - 1 : 1;
    2661         2635 :       compute_objsize (src, stmt, ost, &data.src, &m_ptr_qry);
    2662         2635 :       tree dstsize = compute_objsize (dst, stmt, ost, &data.dst, &m_ptr_qry);
    2663         2635 :       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         2840 :   tree fndecl = get_callee_fndecl (stmt);
    2672         2840 :   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         6072 : pass_waccess::check_strncmp (gcall *stmt)
    2704              : {
    2705         6072 :   if (m_early_checks_p || !warn_stringop_overread)
    2706         3975 :     return;
    2707              : 
    2708         2845 :   tree arg1 = call_arg (stmt, 0);
    2709         2845 :   tree arg2 = call_arg (stmt, 1);
    2710         2845 :   tree bound = call_arg (stmt, 2);
    2711              : 
    2712              :   /* First check each argument separately, considering the bound.  */
    2713         2845 :   if (!check_nul_terminated_array (stmt, arg1, bound)
    2714         2845 :       || !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         2839 :   c_strlen_data lendata1{ }, lendata2{ };
    2726         2839 :   tree len1 = c_strlen (arg1, 1, &lendata1);
    2727         2839 :   tree len2 = c_strlen (arg2, 1, &lendata2);
    2728              : 
    2729         2839 :   if (len1 && TREE_CODE (len1) != INTEGER_CST)
    2730         2572 :     len1 = NULL_TREE;
    2731         2839 :   if (len2 && TREE_CODE (len2) != INTEGER_CST)
    2732         1564 :     len2 = NULL_TREE;
    2733              : 
    2734         2839 :   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         2722 :   if (maybe_warn_nonstring_arg (get_callee_fndecl (stmt), stmt))
    2744              :     return;
    2745              : 
    2746         2549 :   access_data adata1 (m_ptr_qry.rvals, stmt, access_read_only, NULL_TREE, false,
    2747         2549 :                       bound, true);
    2748         2549 :   access_data adata2 (m_ptr_qry.rvals, stmt, access_read_only, NULL_TREE, false,
    2749         2549 :                       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         2549 :   tree bndrng[2] = { NULL_TREE, NULL_TREE };
    2754         2549 :   get_size_range (m_ptr_qry.rvals, bound, stmt, bndrng, 0, adata1.src_bndrng);
    2755         2549 :   if (!bndrng[0] || integer_zerop (bndrng[0]))
    2756          452 :     return;
    2757              : 
    2758         2097 :   if (len1 && tree_int_cst_lt (len1, bndrng[0]))
    2759           20 :     bndrng[0] = len1;
    2760         2097 :   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         2097 :   if (!compute_objsize (arg1, stmt, 1, &adata1.src, &m_ptr_qry)
    2766         2097 :       || !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         2097 :   offset_int rem1 = adata1.src.size_remaining ();
    2772         2097 :   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         4191 :   if (rem1 == 0 || (rem1 < rem2 && lendata1.decl))
    2779            5 :     rem2 = rem1;
    2780         4183 :   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         2097 :   access_data *pad = len1 ? &adata2 : &adata1;
    2786         2097 :   offset_int maxrem = wi::max (rem1, rem2, UNSIGNED);
    2787         2095 :   if (lendata1.decl || lendata2.decl
    2788         4190 :       || 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       631205 : pass_waccess::check_memop_access (gimple *stmt, tree dest, tree src, tree size)
    2809              : {
    2810       631205 :   if (m_early_checks_p)
    2811       279489 :     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       351716 :   access_data data (m_ptr_qry.rvals, stmt, access_read_write);
    2818       351716 :   tree srcsize
    2819       351716 :     = src ? compute_objsize (src, stmt, 0, &data.src, &m_ptr_qry) : NULL_TREE;
    2820       351716 :   tree dstsize = compute_objsize (dest, stmt, 0, &data.dst, &m_ptr_qry);
    2821              : 
    2822       351716 :   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       844070 : pass_waccess::check_read_access (gimple *stmt, tree src,
    2831              :                                  tree bound /* = NULL_TREE */,
    2832              :                                  int ost /* = 1 */)
    2833              : {
    2834       844070 :   if (m_early_checks_p || !warn_stringop_overread)
    2835       521546 :     return;
    2836              : 
    2837       322524 :   if (bound && !useless_type_conversion_p (size_type_node, TREE_TYPE (bound)))
    2838            0 :     bound = fold_convert (size_type_node, bound);
    2839              : 
    2840       322524 :   tree fndecl = get_callee_fndecl (stmt);
    2841       322524 :   maybe_warn_nonstring_arg (fndecl, stmt);
    2842              : 
    2843       322524 :   access_data data (m_ptr_qry.rvals, stmt, access_read_only, NULL_TREE,
    2844       322524 :                    false, bound, true);
    2845       322524 :   compute_objsize (src, stmt, ost, &data.src, &m_ptr_qry);
    2846       322524 :   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       246192 : memmodel_to_uhwi (tree ord, gimple *stmt, unsigned HOST_WIDE_INT *cstval)
    2857              : {
    2858       246192 :   unsigned HOST_WIDE_INT val;
    2859              : 
    2860       246192 :   if (TREE_CODE (ord) == INTEGER_CST)
    2861              :     {
    2862       243055 :       if (!tree_fits_uhwi_p (ord))
    2863              :         return false;
    2864       243047 :       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         3137 :       int_range_max rng (TREE_TYPE (ord));
    2871         6274 :       if (!get_range_query (cfun)->range_of_expr (rng, ord, stmt)
    2872         3137 :           || !rng.singleton_p (&ord))
    2873         2631 :         return false;
    2874              : 
    2875          506 :       wide_int lob = rng.lower_bound ();
    2876          506 :       if (!wi::fits_uhwi_p (lob))
    2877            0 :         return false;
    2878              : 
    2879          506 :       val = lob.to_shwi ();
    2880         3137 :     }
    2881              : 
    2882       243553 :   if (targetm.memmodel_check)
    2883              :     /* This might warn for an invalid VAL but return a conservatively
    2884              :        valid result.  */
    2885       243553 :     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       243553 :   *cstval = val;
    2899              : 
    2900       243553 :   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          256 : memmodel_name (unsigned HOST_WIDE_INT val)
    2929              : {
    2930          256 :   val = memmodel_base (val);
    2931              : 
    2932         1104 :   for (unsigned i = 0; i != ARRAY_SIZE (memory_models); ++i)
    2933              :     {
    2934         1085 :       if (val == memory_models[i].modval)
    2935          237 :         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 flag_clr_models[] = { 0, 1, 4, UCHAR_MAX };
    2944              : static const unsigned char all_models[] = { 0, 1, 2, 3, 4, 5, UCHAR_MAX };
    2945              : 
    2946              : /* Check the success memory model argument ORD_SUCS to the call STMT to
    2947              :    an atomic function and warn if it's invalid.  If nonnull, also check
    2948              :    the failure memory model ORD_FAIL and warn if it's invalid.  Return
    2949              :    true if a warning has been issued.  */
    2950              : 
    2951              : bool
    2952       223627 : pass_waccess::maybe_warn_memmodel (gimple *stmt, tree ord_sucs,
    2953              :                                    tree ord_fail, const unsigned char *valid)
    2954              : {
    2955       223627 :   unsigned HOST_WIDE_INT sucs, fail = 0;
    2956       223627 :   if (!memmodel_to_uhwi (ord_sucs, stmt, &sucs)
    2957       223627 :       || (ord_fail && !memmodel_to_uhwi (ord_fail, stmt, &fail)))
    2958         2639 :     return false;
    2959              : 
    2960       220988 :   bool is_valid = false;
    2961       220988 :   if (valid)
    2962       469369 :     for (unsigned i = 0; valid[i] != UCHAR_MAX; ++i)
    2963              :       {
    2964       469269 :         memmodel model = memory_models[valid[i]].modval;
    2965       469269 :         if (memmodel_base (sucs) == model)
    2966              :           {
    2967              :             is_valid = true;
    2968              :             break;
    2969              :           }
    2970              :       }
    2971              :   else
    2972              :     is_valid = true;
    2973              : 
    2974       220988 :   tree fndecl = gimple_call_fndecl (stmt);
    2975       220988 :   location_t loc = gimple_location (stmt);
    2976       220988 :   loc = expansion_point_location_if_in_system_header (loc);
    2977              : 
    2978       220988 :   if (!is_valid)
    2979              :     {
    2980          100 :       bool warned = false;
    2981          100 :       auto_diagnostic_group d;
    2982          100 :       if (const char *modname = memmodel_name (sucs))
    2983           81 :         warned = warning_at (loc, OPT_Winvalid_memory_model,
    2984              :                              "invalid memory model %qs for %qD",
    2985              :                              modname, fndecl);
    2986              :       else
    2987           19 :         warned = warning_at (loc, OPT_Winvalid_memory_model,
    2988              :                              "invalid memory model %wi for %qD",
    2989              :                              sucs, fndecl);
    2990              : 
    2991          100 :       if (!warned)
    2992              :         return false;
    2993              : 
    2994              :       /* Print a note with the valid memory models.  */
    2995          100 :       auto_vec<const char *> strings;
    2996          479 :       for (unsigned i = 0; valid[i] != UCHAR_MAX; ++i)
    2997              :         {
    2998          379 :           const char *modname = memory_models[valid[i]].modname;
    2999          379 :           strings.safe_push (modname);
    3000              :         }
    3001          100 :       pp_markup::comma_separated_quoted_strings e (strings);
    3002          100 :       inform (loc, "valid models are %e", &e);
    3003          100 :       return true;
    3004          100 :     }
    3005              : 
    3006       220888 :   if (!ord_fail)
    3007              :     return false;
    3008              : 
    3009        22553 :   if (fail == MEMMODEL_RELEASE || fail == MEMMODEL_ACQ_REL)
    3010           64 :     if (const char *failname = memmodel_name (fail))
    3011              :       {
    3012              :         /* If both memory model arguments are valid but their combination
    3013              :            is not, use their names in the warning.  */
    3014           64 :         auto_diagnostic_group d;
    3015           64 :         if (!warning_at (loc, OPT_Winvalid_memory_model,
    3016              :                          "invalid failure memory model %qs for %qD",
    3017              :                          failname, fndecl))
    3018              :           return false;
    3019              : 
    3020           64 :         inform (loc,
    3021              :                 "valid failure models are %qs, %qs, %qs, %qs",
    3022              :                 "memory_order_relaxed", "memory_order_seq_cst",
    3023              :                 "memory_order_acquire", "memory_order_consume");
    3024           64 :         return true;
    3025           64 :       }
    3026              : 
    3027        22489 :   if (memmodel_base (fail) <= memmodel_base (sucs))
    3028              :     return false;
    3029              : 
    3030           46 :   if (const char *sucsname = memmodel_name (sucs))
    3031           46 :     if (const char *failname = memmodel_name (fail))
    3032              :       {
    3033              :         /* If both memory model arguments are valid but their combination
    3034              :            is not, use their names in the warning.  */
    3035           46 :         auto_diagnostic_group d;
    3036           46 :         if (!warning_at (loc, OPT_Winvalid_memory_model,
    3037              :                          "failure memory model %qs cannot be stronger "
    3038              :                          "than success memory model %qs for %qD",
    3039              :                          failname, sucsname, fndecl))
    3040              :           return false;
    3041              : 
    3042              :         /* Print a note with the valid failure memory models which are
    3043              :            those with a value less than or equal to the success mode.  */
    3044           46 :         auto_vec<const char *> strings;
    3045           92 :         for (unsigned i = 0;
    3046           92 :              memory_models[i].modval <= memmodel_base (sucs); ++i)
    3047              :           {
    3048           46 :             const char *modname = memory_models[valid[i]].modname;
    3049           46 :             strings.safe_push (modname);
    3050              :           }
    3051           46 :         pp_markup::comma_separated_quoted_strings e (strings);
    3052              : 
    3053           46 :         inform (loc, "valid models are %e", &e);
    3054           46 :         return true;
    3055           46 :       }
    3056              : 
    3057              :   /* If either memory model argument value is invalid use the numerical
    3058              :      value of both in the message.  */
    3059            0 :   return warning_at (loc, OPT_Winvalid_memory_model,
    3060              :                      "failure memory model %wi cannot be stronger "
    3061              :                      "than success memory model %wi for %qD",
    3062              :                      fail, sucs, fndecl);
    3063              : }
    3064              : 
    3065              : /* Wrapper for the above.  */
    3066              : 
    3067              : void
    3068       223656 : pass_waccess::check_atomic_memmodel (gimple *stmt, tree ord_sucs,
    3069              :                                      tree ord_fail, const unsigned char *valid)
    3070              : {
    3071       223656 :   if (warning_suppressed_p (stmt, OPT_Winvalid_memory_model))
    3072              :     return;
    3073              : 
    3074       223627 :   if (!maybe_warn_memmodel (stmt, ord_sucs, ord_fail, valid))
    3075              :     return;
    3076              : 
    3077          210 :   suppress_warning (stmt, OPT_Winvalid_memory_model);
    3078              : }
    3079              : 
    3080              : /* Check a call STMT to an atomic or sync built-in.  */
    3081              : 
    3082              : bool
    3083      2546045 : pass_waccess::check_atomic_builtin (gcall *stmt)
    3084              : {
    3085      2546045 :   tree callee = gimple_call_fndecl (stmt);
    3086      2546045 :   if (!callee)
    3087              :     return false;
    3088              : 
    3089              :   /* The size in bytes of the access by the function, and the number
    3090              :      of the second argument to check (if any).  */
    3091      2546045 :   unsigned bytes = 0, arg2 = UINT_MAX;
    3092      2546045 :   unsigned sucs_arg = UINT_MAX, fail_arg = UINT_MAX;
    3093              :   /* Points to the array of indices of valid memory models.  */
    3094      2546045 :   const unsigned char *pvalid_models = NULL;
    3095              : 
    3096      2546045 :   switch (DECL_FUNCTION_CODE (callee))
    3097              :     {
    3098              : #define BUILTIN_ACCESS_SIZE_FNSPEC(N)                   \
    3099              :          BUILT_IN_SYNC_FETCH_AND_ADD_ ## N:             \
    3100              :     case BUILT_IN_SYNC_FETCH_AND_SUB_ ## N:             \
    3101              :     case BUILT_IN_SYNC_FETCH_AND_OR_ ## N:              \
    3102              :     case BUILT_IN_SYNC_FETCH_AND_AND_ ## N:             \
    3103              :     case BUILT_IN_SYNC_FETCH_AND_XOR_ ## N:             \
    3104              :     case BUILT_IN_SYNC_FETCH_AND_NAND_ ## N:            \
    3105              :     case BUILT_IN_SYNC_ADD_AND_FETCH_ ## N:             \
    3106              :     case BUILT_IN_SYNC_SUB_AND_FETCH_ ## N:             \
    3107              :     case BUILT_IN_SYNC_OR_AND_FETCH_ ## N:              \
    3108              :     case BUILT_IN_SYNC_AND_AND_FETCH_ ## N:             \
    3109              :     case BUILT_IN_SYNC_XOR_AND_FETCH_ ## N:             \
    3110              :     case BUILT_IN_SYNC_NAND_AND_FETCH_ ## N:            \
    3111              :     case BUILT_IN_SYNC_LOCK_TEST_AND_SET_ ## N:         \
    3112              :     case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_ ## N:     \
    3113              :     case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_ ## N:      \
    3114              :     case BUILT_IN_SYNC_LOCK_RELEASE_ ## N:              \
    3115              :       bytes = N;                                        \
    3116              :       break;                                            \
    3117              :     case BUILT_IN_ATOMIC_LOAD_ ## N:                    \
    3118              :       pvalid_models = load_models;                      \
    3119              :       sucs_arg = 1;                                     \
    3120              :       /* FALLTHROUGH */                                 \
    3121              :     case BUILT_IN_ATOMIC_STORE_ ## N:                   \
    3122              :       if (!pvalid_models)                               \
    3123              :         pvalid_models = store_models;                   \
    3124              :       /* FALLTHROUGH */                                 \
    3125              :     case BUILT_IN_ATOMIC_ADD_FETCH_ ## N:               \
    3126              :     case BUILT_IN_ATOMIC_SUB_FETCH_ ## N:               \
    3127              :     case BUILT_IN_ATOMIC_AND_FETCH_ ## N:               \
    3128              :     case BUILT_IN_ATOMIC_NAND_FETCH_ ## N:              \
    3129              :     case BUILT_IN_ATOMIC_XOR_FETCH_ ## N:               \
    3130              :     case BUILT_IN_ATOMIC_OR_FETCH_ ## N:                \
    3131              :     case BUILT_IN_ATOMIC_FETCH_ADD_ ## N:               \
    3132              :     case BUILT_IN_ATOMIC_FETCH_SUB_ ## N:               \
    3133              :     case BUILT_IN_ATOMIC_FETCH_AND_ ## N:               \
    3134              :     case BUILT_IN_ATOMIC_FETCH_NAND_ ## N:              \
    3135              :     case BUILT_IN_ATOMIC_FETCH_OR_ ## N:                \
    3136              :     case BUILT_IN_ATOMIC_FETCH_XOR_ ## N:               \
    3137              :       bytes = N;                                        \
    3138              :       if (sucs_arg == UINT_MAX)                         \
    3139              :         sucs_arg = 2;                                   \
    3140              :       if (!pvalid_models)                               \
    3141              :         pvalid_models = all_models;                     \
    3142              :       break;                                            \
    3143              :     case BUILT_IN_ATOMIC_EXCHANGE_ ## N:                \
    3144              :       bytes = N;                                        \
    3145              :       sucs_arg = 2;                                     \
    3146              :       pvalid_models = all_models;                       \
    3147              :       break;                                            \
    3148              :     case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_ ## N:        \
    3149              :       bytes = N;                                        \
    3150              :       sucs_arg = 4;                                     \
    3151              :       fail_arg = 5;                                     \
    3152              :       pvalid_models = all_models;                       \
    3153              :       arg2 = 1
    3154              : 
    3155        63375 :     case BUILTIN_ACCESS_SIZE_FNSPEC (1);
    3156         4820 :       break;
    3157        17051 :     case BUILTIN_ACCESS_SIZE_FNSPEC (2);
    3158         1813 :       break;
    3159        79422 :     case BUILTIN_ACCESS_SIZE_FNSPEC (4);
    3160         5681 :       break;
    3161        64676 :     case BUILTIN_ACCESS_SIZE_FNSPEC (8);
    3162         7195 :       break;
    3163        15087 :     case BUILTIN_ACCESS_SIZE_FNSPEC (16);
    3164         3438 :       break;
    3165              : 
    3166          110 :     case BUILT_IN_ATOMIC_CLEAR:
    3167          110 :       sucs_arg = 1;
    3168          110 :       pvalid_models = flag_clr_models;
    3169          110 :       break;
    3170              : 
    3171              : #define BUILTIN_TSAN_ACCESS_SIZE_FNSPEC(N)              \
    3172              :          BUILT_IN_TSAN_ATOMIC ## N ##_LOAD:             \
    3173              :       pvalid_models = load_models;                      \
    3174              :       sucs_arg = 1;                                     \
    3175              :       /* FALLTHROUGH */                                 \
    3176              :     case BUILT_IN_TSAN_ATOMIC ## N ##_STORE:            \
    3177              :       if (!pvalid_models)                               \
    3178              :         pvalid_models = store_models;                   \
    3179              :       /* FALLTHROUGH */                                 \
    3180              :     case BUILT_IN_TSAN_ATOMIC ## N ##_FETCH_ADD:        \
    3181              :     case BUILT_IN_TSAN_ATOMIC ## N ##_FETCH_SUB:        \
    3182              :     case BUILT_IN_TSAN_ATOMIC ## N ##_FETCH_AND:        \
    3183              :     case BUILT_IN_TSAN_ATOMIC ## N ##_FETCH_NAND:       \
    3184              :     case BUILT_IN_TSAN_ATOMIC ## N ##_FETCH_OR:         \
    3185              :     case BUILT_IN_TSAN_ATOMIC ## N ##_FETCH_XOR:        \
    3186              :       bytes = N / 8;                                    \
    3187              :       if (sucs_arg == UINT_MAX)                         \
    3188              :         sucs_arg = 2;                                   \
    3189              :       if (!pvalid_models)                               \
    3190              :         pvalid_models = all_models;                     \
    3191              :       break;                                            \
    3192              :     case BUILT_IN_TSAN_ATOMIC ## N ##_EXCHANGE:         \
    3193              :       bytes = N / 8;                                    \
    3194              :       sucs_arg = 2;                                     \
    3195              :       pvalid_models = all_models;                       \
    3196              :       break;                                            \
    3197              :     case BUILT_IN_TSAN_ATOMIC ## N ##_COMPARE_EXCHANGE_STRONG:  \
    3198              :     case BUILT_IN_TSAN_ATOMIC ## N ##_COMPARE_EXCHANGE_WEAK:    \
    3199              :       bytes = N / 8;                                    \
    3200              :       sucs_arg = 3;                                     \
    3201              :       fail_arg = 4;                                     \
    3202              :       pvalid_models = all_models;                       \
    3203              :       arg2 = 1
    3204              : 
    3205           32 :     case BUILTIN_TSAN_ACCESS_SIZE_FNSPEC (8);
    3206            0 :       break;
    3207              : 
    3208            0 :     case BUILTIN_TSAN_ACCESS_SIZE_FNSPEC (16);
    3209            0 :       break;
    3210              : 
    3211           24 :     case BUILTIN_TSAN_ACCESS_SIZE_FNSPEC (32);
    3212            8 :       break;
    3213              : 
    3214            0 :     case BUILTIN_TSAN_ACCESS_SIZE_FNSPEC (64);
    3215            0 :       break;
    3216              : 
    3217            0 :     case BUILTIN_TSAN_ACCESS_SIZE_FNSPEC (128);
    3218            0 :       break;
    3219              : 
    3220              :     default:
    3221              :       return false;
    3222              :     }
    3223              : 
    3224       233679 :   unsigned nargs = gimple_call_num_args (stmt);
    3225       233679 :   if (sucs_arg < nargs)
    3226              :     {
    3227       223656 :       tree ord_sucs = gimple_call_arg (stmt, sucs_arg);
    3228       223656 :       tree ord_fail = NULL_TREE;
    3229       223656 :       if (fail_arg < nargs)
    3230        22955 :         ord_fail = gimple_call_arg (stmt, fail_arg);
    3231       223656 :       check_atomic_memmodel (stmt, ord_sucs, ord_fail, pvalid_models);
    3232              :     }
    3233              : 
    3234       233679 :   if (!bytes)
    3235              :     return true;
    3236              : 
    3237       233569 :   tree size = build_int_cstu (sizetype, bytes);
    3238       233569 :   tree dst = gimple_call_arg (stmt, 0);
    3239       233569 :   check_memop_access (stmt, dst, NULL_TREE, size);
    3240              : 
    3241       233569 :   if (arg2 != UINT_MAX)
    3242              :     {
    3243        22955 :       tree dst = gimple_call_arg (stmt, arg2);
    3244        22955 :       check_memop_access (stmt, dst, NULL_TREE, size);
    3245              :     }
    3246              : 
    3247              :   return true;
    3248              : }
    3249              : 
    3250              : /* Check call STMT to a built-in function for invalid accesses.  Return
    3251              :    true if a call has been handled.  */
    3252              : 
    3253              : bool
    3254      3566885 : pass_waccess::check_builtin (gcall *stmt)
    3255              : {
    3256      3566885 :   tree callee = gimple_call_fndecl (stmt);
    3257      3566885 :   if (!callee)
    3258              :     return false;
    3259              : 
    3260      3566885 :   switch (DECL_FUNCTION_CODE (callee))
    3261              :     {
    3262        30966 :     case BUILT_IN_ALLOCA:
    3263        30966 :     case BUILT_IN_ALLOCA_WITH_ALIGN:
    3264        30966 :     case BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX:
    3265        30966 :       check_alloca (stmt);
    3266        30966 :       return true;
    3267              : 
    3268           62 :     case BUILT_IN_EXECL:
    3269           62 :     case BUILT_IN_EXECLE:
    3270           62 :     case BUILT_IN_EXECLP:
    3271           62 :     case BUILT_IN_EXECV:
    3272           62 :     case BUILT_IN_EXECVE:
    3273           62 :     case BUILT_IN_EXECVP:
    3274           62 :       check_read_access (stmt, call_arg (stmt, 0));
    3275           62 :       return true;
    3276              : 
    3277       142505 :     case BUILT_IN_FREE:
    3278       142505 :     case BUILT_IN_REALLOC:
    3279       142505 :       if (!m_early_checks_p)
    3280              :         {
    3281        67186 :           tree arg = call_arg (stmt, 0);
    3282        67186 :           if (TREE_CODE (arg) == SSA_NAME)
    3283        67102 :             check_pointer_uses (stmt, arg);
    3284              :         }
    3285              :       return true;
    3286              : 
    3287        10242 :     case BUILT_IN_GETTEXT:
    3288        10242 :     case BUILT_IN_PUTS:
    3289        10242 :     case BUILT_IN_PUTS_UNLOCKED:
    3290        10242 :     case BUILT_IN_STRDUP:
    3291        10242 :       check_read_access (stmt, call_arg (stmt, 0));
    3292        10242 :       return true;
    3293              : 
    3294        34958 :     case BUILT_IN_INDEX:
    3295        34958 :     case BUILT_IN_RINDEX:
    3296        34958 :     case BUILT_IN_STRCHR:
    3297        34958 :     case BUILT_IN_STRRCHR:
    3298        34958 :     case BUILT_IN_STRLEN:
    3299        34958 :       check_read_access (stmt, call_arg (stmt, 0));
    3300        34958 :       return true;
    3301              : 
    3302         2903 :     case BUILT_IN_FPUTS:
    3303         2903 :     case BUILT_IN_FPUTS_UNLOCKED:
    3304         2903 :       check_read_access (stmt, call_arg (stmt, 0));
    3305         2903 :       return true;
    3306              : 
    3307         2201 :     case BUILT_IN_STRNDUP:
    3308         2201 :     case BUILT_IN_STRNLEN:
    3309         2201 :       {
    3310         2201 :         tree str = call_arg (stmt, 0);
    3311         2201 :         tree len = call_arg (stmt, 1);
    3312         2201 :         check_read_access (stmt, str, len);
    3313         2201 :         return true;
    3314              :       }
    3315              : 
    3316         1669 :     case BUILT_IN_STRCAT:
    3317         1669 :       check_strcat (stmt);
    3318         1669 :       return true;
    3319              : 
    3320         1667 :     case BUILT_IN_STRNCAT:
    3321         1667 :       check_strncat (stmt);
    3322         1667 :       return true;
    3323              : 
    3324         7246 :     case BUILT_IN_STPCPY:
    3325         7246 :     case BUILT_IN_STRCPY:
    3326         7246 :       check_stxcpy (stmt);
    3327         7246 :       return true;
    3328              : 
    3329         5890 :     case BUILT_IN_STPNCPY:
    3330         5890 :     case BUILT_IN_STRNCPY:
    3331         5890 :       check_stxncpy (stmt);
    3332         5890 :       return true;
    3333              : 
    3334       259384 :     case BUILT_IN_STRCASECMP:
    3335       259384 :     case BUILT_IN_STRCMP:
    3336       259384 :     case BUILT_IN_STRPBRK:
    3337       259384 :     case BUILT_IN_STRSPN:
    3338       259384 :     case BUILT_IN_STRCSPN:
    3339       259384 :     case BUILT_IN_STRSTR:
    3340       259384 :       check_read_access (stmt, call_arg (stmt, 0));
    3341       259384 :       check_read_access (stmt, call_arg (stmt, 1));
    3342       259384 :       return true;
    3343              : 
    3344         6072 :     case BUILT_IN_STRNCASECMP:
    3345         6072 :     case BUILT_IN_STRNCMP:
    3346         6072 :       check_strncmp (stmt);
    3347         6072 :       return true;
    3348              : 
    3349       134542 :     case BUILT_IN_MEMCMP:
    3350       134542 :       {
    3351       134542 :         tree a1 = call_arg (stmt, 0);
    3352       134542 :         tree a2 = call_arg (stmt, 1);
    3353       134542 :         tree len = call_arg (stmt, 2);
    3354       134542 :         check_read_access (stmt, a1, len, 0);
    3355       134542 :         check_read_access (stmt, a2, len, 0);
    3356       134542 :         return true;
    3357              :       }
    3358              : 
    3359       195110 :     case BUILT_IN_MEMCPY:
    3360       195110 :     case BUILT_IN_MEMPCPY:
    3361       195110 :     case BUILT_IN_MEMMOVE:
    3362       195110 :       {
    3363       195110 :         tree dst = call_arg (stmt, 0);
    3364       195110 :         tree src = call_arg (stmt, 1);
    3365       195110 :         tree len = call_arg (stmt, 2);
    3366       195110 :         check_memop_access (stmt, dst, src, len);
    3367       195110 :         return true;
    3368              :       }
    3369              : 
    3370         5852 :     case BUILT_IN_MEMCHR:
    3371         5852 :       {
    3372         5852 :         tree src = call_arg (stmt, 0);
    3373         5852 :         tree len = call_arg (stmt, 2);
    3374         5852 :         check_read_access (stmt, src, len, 0);
    3375         5852 :         return true;
    3376              :       }
    3377              : 
    3378       179571 :     case BUILT_IN_MEMSET:
    3379       179571 :       {
    3380       179571 :         tree dst = call_arg (stmt, 0);
    3381       179571 :         tree len = call_arg (stmt, 2);
    3382       179571 :         check_memop_access (stmt, dst, NULL_TREE, len);
    3383       179571 :         return true;
    3384              :       }
    3385              : 
    3386      2546045 :     default:
    3387      2546045 :       if (check_atomic_builtin (stmt))
    3388              :         return true;
    3389              :       break;
    3390              :     }
    3391              : 
    3392              :   return false;
    3393              : }
    3394              : 
    3395              : /* Returns the type of the argument ARGNO to function with type FNTYPE
    3396              :    or null when the type cannot be determined or no such argument exists.  */
    3397              : 
    3398              : static tree
    3399        61767 : fntype_argno_type (tree fntype, unsigned argno)
    3400              : {
    3401        61767 :   if (!prototype_p (fntype))
    3402              :     return NULL_TREE;
    3403              : 
    3404        61763 :   tree argtype;
    3405        61763 :   function_args_iterator it;
    3406       125118 :   FOREACH_FUNCTION_ARGS (fntype, argtype, it)
    3407       125118 :     if (argno-- == 0)
    3408              :       return argtype;
    3409              : 
    3410              :   return NULL_TREE;
    3411              : }
    3412              : 
    3413              : /* Helper to append the "human readable" attribute access specification
    3414              :    described by ACCESS to the array ATTRSTR with size STRSIZE.  Used in
    3415              :    diagnostics.  */
    3416              : 
    3417              : static inline void
    3418          280 : append_attrname (const std::pair<int, attr_access> &access,
    3419              :                  char *attrstr, size_t strsize)
    3420              : {
    3421          280 :   if (access.second.internal_p)
    3422              :     return;
    3423              : 
    3424          262 :   tree str = access.second.to_external_string ();
    3425          262 :   gcc_assert (strsize >= (size_t) TREE_STRING_LENGTH (str));
    3426          262 :   strcpy (attrstr, TREE_STRING_POINTER (str));
    3427              : }
    3428              : 
    3429              : /* Iterate over attribute access read-only, read-write, and write-only
    3430              :    arguments and diagnose past-the-end accesses and related problems
    3431              :    in the function call EXP.  */
    3432              : 
    3433              : void
    3434      2983430 : pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
    3435              :                                         gimple *stmt)
    3436              : {
    3437      2983430 :   if (warning_suppressed_p (stmt, OPT_Wnonnull)
    3438      2983430 :       || warning_suppressed_p (stmt, OPT_Wstringop_overflow_))
    3439        19513 :     return;
    3440              : 
    3441      2963921 :   auto_diagnostic_group adg;
    3442              : 
    3443              :   /* Set if a warning has been issued for any argument (used to decide
    3444              :      whether to emit an informational note at the end).  */
    3445      2963921 :   opt_code opt_warned = no_warning;
    3446              : 
    3447              :   /* A string describing the attributes that the warnings issued by this
    3448              :      function apply to.  Used to print one informational note per function
    3449              :      call, rather than one per warning.  That reduces clutter.  */
    3450      2963921 :   char attrstr[80];
    3451      2963921 :   attrstr[0] = 0;
    3452              : 
    3453      3090849 :   for (rdwr_map::iterator it = rwm->begin (); it != rwm->end (); ++it)
    3454              :     {
    3455        63468 :       std::pair<int, attr_access> access = *it;
    3456              : 
    3457              :       /* Get the function call arguments corresponding to the attribute's
    3458              :          positional arguments.  When both arguments have been specified
    3459              :          there will be two entries in *RWM, one for each.  They are
    3460              :          cross-referenced by their respective argument numbers in
    3461              :          ACCESS.PTRARG and ACCESS.SIZARG.  */
    3462        63468 :       const int ptridx = access.second.ptrarg;
    3463        63468 :       const int sizidx = access.second.sizarg;
    3464              : 
    3465        63468 :       gcc_assert (ptridx != -1);
    3466        63468 :       gcc_assert (access.first == ptridx || access.first == sizidx);
    3467              : 
    3468              :       /* The pointer is set to null for the entry corresponding to
    3469              :          the size argument.  Skip it.  It's handled when the entry
    3470              :          corresponding to the pointer argument comes up.  */
    3471        63468 :       if (!access.second.ptr)
    3472         1732 :         continue;
    3473              : 
    3474        61767 :       tree ptrtype = fntype_argno_type (fntype, ptridx);
    3475        61767 :       if (!ptrtype)
    3476              :         /* A function with a prototype was redeclared without one and
    3477              :            the prototype has been lost.  See pr102759.  Avoid dealing
    3478              :            with this pathological case.  */
    3479            4 :         return;
    3480              : 
    3481        61763 :       tree argtype = TREE_TYPE (ptrtype);
    3482              : 
    3483              :       /* The size of the access by the call in elements.  */
    3484        61763 :       tree access_nelts;
    3485        61763 :       if (sizidx == -1)
    3486              :         {
    3487              :           /* If only the pointer attribute operand was specified and
    3488              :              not size, set SIZE to the greater of MINSIZE or size of
    3489              :              one element of the pointed to type to detect smaller
    3490              :              objects (null pointers are diagnosed in this case only
    3491              :              if the pointer is also declared with attribute nonnull.  */
    3492        60063 :           if (access.second.minsize
    3493        60063 :               && access.second.minsize != HOST_WIDE_INT_M1U)
    3494        50391 :             access_nelts = build_int_cstu (sizetype, access.second.minsize);
    3495         9672 :           else if (VOID_TYPE_P (argtype) && access.second.mode == access_none)
    3496              :             /* Treat access mode none on a void* argument as expecting
    3497              :                as little as zero bytes.  */
    3498          242 :             access_nelts = size_zero_node;
    3499              :           else
    3500         9430 :             access_nelts = size_one_node;
    3501              :         }
    3502              :       else
    3503         1700 :         access_nelts = rwm->get (sizidx)->size;
    3504              : 
    3505              :       /* If access_nelts is e.g. a PARM_DECL with larger precision than
    3506              :          sizetype, such as __int128 or _BitInt(34123) parameters,
    3507              :          cast it to sizetype.  */
    3508        61763 :       if (access_nelts
    3509        61763 :           && INTEGRAL_TYPE_P (TREE_TYPE (access_nelts))
    3510       123526 :           && (TYPE_PRECISION (TREE_TYPE (access_nelts))
    3511        61763 :               > TYPE_PRECISION (sizetype)))
    3512            2 :         access_nelts = fold_convert (sizetype, access_nelts);
    3513              : 
    3514              :       /* Format the value or range to avoid an explosion of messages.  */
    3515        61763 :       char sizstr[80];
    3516        61763 :       tree sizrng[2] = { size_zero_node, build_all_ones_cst (sizetype) };
    3517        61763 :       if (get_size_range (m_ptr_qry.rvals, access_nelts, stmt, sizrng, 1))
    3518              :         {
    3519        61763 :           char *s0 = print_generic_expr_to_str (sizrng[0]);
    3520        61763 :           if (tree_int_cst_equal (sizrng[0], sizrng[1]))
    3521              :             {
    3522        61308 :               gcc_checking_assert (strlen (s0) < sizeof sizstr);
    3523        61308 :               strcpy (sizstr, s0);
    3524              :             }
    3525              :           else
    3526              :             {
    3527          455 :               char *s1 = print_generic_expr_to_str (sizrng[1]);
    3528          455 :               gcc_checking_assert (strlen (s0) + strlen (s1)
    3529              :                                    < sizeof sizstr - 4);
    3530          455 :               sprintf (sizstr, "[%.37s, %.37s]", s0, s1);
    3531          455 :               free (s1);
    3532              :             }
    3533        61763 :           free (s0);
    3534              :         }
    3535              :       else
    3536            0 :         *sizstr = '\0';
    3537              : 
    3538              :       /* Set if a warning has been issued for the current argument.  */
    3539        61763 :       opt_code arg_warned = no_warning;
    3540        61763 :       location_t loc = get_location (stmt);
    3541        61763 :       tree ptr = access.second.ptr;
    3542        61763 :       if (*sizstr
    3543        61763 :           && tree_int_cst_sgn (sizrng[0]) < 0
    3544        61910 :           && tree_int_cst_sgn (sizrng[1]) < 0)
    3545              :         {
    3546           53 :           rich_location_with_details richloc (loc, stmt);
    3547              :           /* Warn about negative sizes.  */
    3548           53 :           if (access.second.internal_p)
    3549              :             {
    3550           18 :               const std::string argtypestr
    3551           18 :                 = access.second.array_as_string (ptrtype);
    3552              : 
    3553           18 :               if (warning_at (&richloc, OPT_Wstringop_overflow_,
    3554              :                               "bound argument %i value %s is "
    3555              :                               "negative for a variable length array "
    3556              :                               "argument %i of type %s",
    3557              :                               sizidx + 1, sizstr,
    3558              :                               ptridx + 1, argtypestr.c_str ()))
    3559           18 :                 arg_warned = OPT_Wstringop_overflow_;
    3560           18 :             }
    3561           35 :           else if (warning_at (&richloc, OPT_Wstringop_overflow_,
    3562              :                                "argument %i value %s is negative",
    3563              :                                sizidx + 1, sizstr))
    3564              :             arg_warned = OPT_Wstringop_overflow_;
    3565              : 
    3566           18 :           if (arg_warned != no_warning)
    3567              :             {
    3568           23 :               append_attrname (access, attrstr, sizeof attrstr);
    3569              :               /* Remember a warning has been issued and avoid warning
    3570              :                  again below for the same attribute.  */
    3571           23 :               opt_warned = arg_warned;
    3572           23 :               continue;
    3573              :             }
    3574           53 :         }
    3575              : 
    3576              :       /* The size of the access by the call in bytes.  */
    3577        61740 :       tree access_size = NULL_TREE;
    3578        61740 :       if (tree_int_cst_sgn (sizrng[0]) >= 0)
    3579              :         {
    3580        61616 :           if (COMPLETE_TYPE_P (argtype))
    3581              :             {
    3582              :               /* Multiply ACCESS_SIZE by the size of the type the pointer
    3583              :                  argument points to.  If it's incomplete the size is used
    3584              :                  as is.  */
    3585        58875 :               if (tree argsize = TYPE_SIZE_UNIT (argtype))
    3586        58875 :                 if (TREE_CODE (argsize) == INTEGER_CST)
    3587              :                   {
    3588        58647 :                     const int prec = TYPE_PRECISION (sizetype);
    3589        58647 :                     wide_int minsize = wi::to_wide (sizrng[0], prec);
    3590        58647 :                     minsize *= wi::to_wide (argsize, prec);
    3591        58647 :                     access_size = wide_int_to_tree (sizetype, minsize);
    3592        58647 :                   }
    3593              :             }
    3594              :           else
    3595              :             access_size = access_nelts;
    3596              :         }
    3597              : 
    3598        61740 :       if (integer_zerop (ptr))
    3599              :         {
    3600         1411 :           if (!access.second.internal_p
    3601         1411 :               && sizidx >= 0 && tree_int_cst_sgn (sizrng[0]) > 0)
    3602              :             {
    3603              :               /* Warn about null pointers with positive sizes.  This is
    3604              :                  different from also declaring the pointer argument with
    3605              :                  attribute nonnull when the function accepts null pointers
    3606              :                  only when the corresponding size is zero.  */
    3607           26 :               if (warning_at (loc, OPT_Wnonnull,
    3608              :                                    "argument %i is null but "
    3609              :                                    "the corresponding size argument "
    3610              :                                    "%i value is %s",
    3611              :                                    ptridx + 1, sizidx + 1, sizstr))
    3612            8 :                 arg_warned = OPT_Wnonnull;
    3613              :             }
    3614              : 
    3615           16 :           if (arg_warned != no_warning)
    3616              :             {
    3617            8 :               append_attrname (access, attrstr, sizeof attrstr);
    3618              :               /* Remember a warning has been issued and avoid warning
    3619              :                  again below for the same attribute.  */
    3620            8 :               opt_warned = OPT_Wnonnull;
    3621            8 :               continue;
    3622              :             }
    3623              :         }
    3624              : 
    3625        61732 :       access_data data (m_ptr_qry.rvals, stmt, access.second.mode,
    3626        61732 :                         NULL_TREE, false, NULL_TREE, false);
    3627        60805 :       access_ref* const pobj = (access.second.mode == access_write_only
    3628        61732 :                                 ? &data.dst : &data.src);
    3629        61732 :       tree objsize = compute_objsize (ptr, stmt, 1, pobj, &m_ptr_qry);
    3630              : 
    3631              :       /* The size of the destination or source object.  */
    3632        61732 :       tree dstsize = NULL_TREE, srcsize = NULL_TREE;
    3633        61732 :       if (access.second.mode == access_read_only
    3634              :           || access.second.mode == access_none)
    3635              :         {
    3636              :           /* For a read-only argument there is no destination.  For
    3637              :              no access, set the source as well and differentiate via
    3638              :              the access flag below.  */
    3639         1278 :           srcsize = objsize;
    3640         1278 :           if (access.second.mode == access_read_only
    3641              :               || access.second.mode == access_none)
    3642              :             {
    3643              :               /* For a read-only attribute there is no destination so
    3644              :                  clear OBJSIZE.  This emits "reading N bytes" kind of
    3645              :                  diagnostics instead of the "writing N bytes" kind,
    3646              :                  unless MODE is none.  */
    3647         1278 :               objsize = NULL_TREE;
    3648              :             }
    3649              :         }
    3650              :       else
    3651              :         dstsize = objsize;
    3652              : 
    3653              :       /* Clear the no-warning bit in case it was set by check_access
    3654              :          in a prior iteration so that accesses via different arguments
    3655              :          are diagnosed.  */
    3656        61732 :       suppress_warning (stmt, OPT_Wstringop_overflow_, false);
    3657        61732 :       access_mode mode = data.mode;
    3658        61732 :       if (mode == access_deferred)
    3659        59025 :         mode = TYPE_READONLY (argtype) ? access_read_only : access_read_write;
    3660        61732 :       check_access (stmt, access_size, /*maxread=*/ NULL_TREE, srcsize,
    3661              :                     dstsize, mode, &data, m_ptr_qry.rvals);
    3662              : 
    3663        61732 :       if (warning_suppressed_p (stmt, OPT_Wstringop_overflow_))
    3664              :         opt_warned = OPT_Wstringop_overflow_;
    3665        61525 :       if (opt_warned != no_warning)
    3666              :         {
    3667          322 :           if (access.second.internal_p)
    3668              :             {
    3669           73 :               unsigned HOST_WIDE_INT nelts =
    3670           73 :                 access_nelts ? access.second.minsize : HOST_WIDE_INT_M1U;
    3671           73 :               tree arrtype = build_printable_array_type (argtype, nelts);
    3672           73 :               inform (loc, "referencing argument %u of type %qT",
    3673              :                       ptridx + 1, arrtype);
    3674              :             }
    3675              :           else
    3676              :             /* If check_access issued a warning above, append the relevant
    3677              :                attribute to the string.  */
    3678          249 :             append_attrname (access, attrstr, sizeof attrstr);
    3679              :         }
    3680              :     }
    3681              : 
    3682      2963917 :   if (*attrstr)
    3683              :     {
    3684          145 :       if (fndecl)
    3685          129 :         inform (get_location (fndecl),
    3686              :                 "in a call to function %qD declared with attribute %qs",
    3687              :                 fndecl, attrstr);
    3688              :       else
    3689           16 :         inform (get_location (stmt),
    3690              :                 "in a call with type %qT and attribute %qs",
    3691              :                 fntype, attrstr);
    3692              :     }
    3693      2963772 :   else if (opt_warned != no_warning)
    3694              :     {
    3695           91 :       if (fndecl)
    3696           91 :         inform (get_location (fndecl),
    3697              :                 "in a call to function %qD", fndecl);
    3698              :       else
    3699            0 :         inform (get_location (stmt),
    3700              :                 "in a call with type %qT", fntype);
    3701              :     }
    3702              : 
    3703              :   /* Set the bit in case it was cleared and not set above.  */
    3704          236 :   if (opt_warned != no_warning)
    3705          236 :     suppress_warning (stmt, opt_warned);
    3706      2963921 : }
    3707              : 
    3708              : /* Check call STMT to an ordinary (non-built-in) function for invalid
    3709              :    accesses.  Return true if a call has been handled.  */
    3710              : 
    3711              : bool
    3712     17238787 : pass_waccess::check_call_access (gcall *stmt)
    3713              : {
    3714     17238787 :   tree fntype = gimple_call_fntype (stmt);
    3715     16522656 :   if (!fntype)
    3716              :     return false;
    3717              : 
    3718     16522656 :   tree fntypeattrs = TYPE_ATTRIBUTES (fntype);
    3719     16522656 :   if (!fntypeattrs)
    3720              :     return false;
    3721              : 
    3722              :   /* Map of attribute access specifications for function arguments.  */
    3723      2983430 :   rdwr_map rdwr_idx;
    3724      2983430 :   init_attr_rdwr_indices (&rdwr_idx, fntypeattrs);
    3725              : 
    3726      2983430 :   unsigned nargs = call_nargs (stmt);
    3727      9228620 :   for (unsigned i = 0; i != nargs; ++i)
    3728              :     {
    3729      6245190 :       tree arg = call_arg (stmt, i);
    3730              : 
    3731              :       /* Save the actual argument that corresponds to the access attribute
    3732              :          operand for later processing.  */
    3733      6245190 :       if (attr_access *access = rdwr_idx.get (i))
    3734              :         {
    3735        64115 :           if (POINTER_TYPE_P (TREE_TYPE (arg)))
    3736              :             {
    3737        62353 :               access->ptr = arg;
    3738              :               /* A nonnull ACCESS->SIZE contains VLA bounds.  */
    3739              :             }
    3740              :           else
    3741              :             {
    3742         1762 :               access->size = arg;
    3743         1762 :               gcc_assert (access->ptr == NULL_TREE);
    3744              :             }
    3745              :         }
    3746              :     }
    3747              : 
    3748              :   /* Check attribute access arguments.  */
    3749      2983430 :   tree fndecl = gimple_call_fndecl (stmt);
    3750      2983430 :   maybe_check_access_sizes (&rdwr_idx, fndecl, fntype, stmt);
    3751              : 
    3752      2983430 :   check_alloc_size_call (stmt);
    3753      2983430 :   return true;
    3754      2983430 : }
    3755              : 
    3756              : /* Check arguments in a call STMT for attribute nonstring.  */
    3757              : 
    3758              : static void
    3759      6891397 : check_nonstring_args (gcall *stmt)
    3760              : {
    3761      6891397 :   tree fndecl = gimple_call_fndecl (stmt);
    3762              : 
    3763              :   /* Detect passing non-string arguments to functions expecting
    3764              :      nul-terminated strings.  */
    3765      6891397 :   maybe_warn_nonstring_arg (fndecl, stmt);
    3766      6891397 : }
    3767              : 
    3768              : /* Issue a warning if a deallocation function such as free, realloc,
    3769              :    or C++ operator delete is called with an argument not returned by
    3770              :    a matching allocation function such as malloc or the corresponding
    3771              :    form of C++ operator new.  */
    3772              : 
    3773              : void
    3774      6891397 : pass_waccess::maybe_check_dealloc_call (gcall *call)
    3775              : {
    3776      6891397 :   tree fndecl = gimple_call_fndecl (call);
    3777      6891397 :   if (!fndecl)
    3778      6681175 :     return;
    3779              : 
    3780      6483909 :   unsigned argno = fndecl_dealloc_argno (fndecl);
    3781      6483909 :   if ((unsigned) call_nargs (call) <= argno)
    3782              :     return;
    3783              : 
    3784       210905 :   tree ptr = gimple_call_arg (call, argno);
    3785       210905 :   if (integer_zerop (ptr))
    3786              :     return;
    3787              : 
    3788       210811 :   access_ref aref;
    3789       210811 :   if (!compute_objsize (ptr, call, 0, &aref, &m_ptr_qry))
    3790              :     return;
    3791              : 
    3792       210811 :   tree ref = aref.ref;
    3793       210811 :   if (integer_zerop (ref))
    3794              :     return;
    3795              : 
    3796       210699 :   tree dealloc_decl = fndecl;
    3797       210699 :   location_t loc = gimple_location (call);
    3798              : 
    3799       210699 :   if (DECL_P (ref) || EXPR_P (ref))
    3800              :     {
    3801              :       /* Diagnose freeing a declared object.  */
    3802       119671 :       if (aref.ref_declared ())
    3803              :         {
    3804          152 :           auto_diagnostic_group d;
    3805          152 :           if (warning_at (loc, OPT_Wfree_nonheap_object,
    3806              :                           "%qD called on unallocated object %qD",
    3807              :                           dealloc_decl, ref))
    3808              :             {
    3809          140 :               inform (get_location (ref), "declared here");
    3810          140 :               return;
    3811              :             }
    3812          152 :         }
    3813              : 
    3814              :       /* Diagnose freeing a pointer that includes a positive offset.
    3815              :          Such a pointer cannot refer to the beginning of an allocated
    3816              :          object.  A negative offset may refer to it.  */
    3817       119531 :       if (aref.sizrng[0] != aref.sizrng[1]
    3818       119531 :           && warn_dealloc_offset (loc, call, aref))
    3819              :         return;
    3820              :     }
    3821        91028 :   else if (CONSTANT_CLASS_P (ref))
    3822              :     {
    3823           38 :       auto_diagnostic_group d;
    3824           38 :       if (warning_at (loc, OPT_Wfree_nonheap_object,
    3825              :                       "%qD called on a pointer to an unallocated "
    3826              :                       "object %qE", dealloc_decl, ref))
    3827              :         {
    3828           38 :           if (TREE_CODE (ptr) == SSA_NAME)
    3829              :             {
    3830           12 :               gimple *def_stmt = SSA_NAME_DEF_STMT (ptr);
    3831           12 :               if (is_gimple_assign (def_stmt))
    3832              :                 {
    3833           12 :                   location_t loc = gimple_location (def_stmt);
    3834           12 :                   inform (loc, "assigned here");
    3835              :                 }
    3836              :             }
    3837           38 :           return;
    3838              :         }
    3839           38 :     }
    3840        90990 :   else if (TREE_CODE (ref) == SSA_NAME)
    3841              :     {
    3842              :       /* Also warn if the pointer argument refers to the result
    3843              :          of an allocation call like alloca or VLA.  */
    3844        90990 :       gimple *def_stmt = SSA_NAME_DEF_STMT (ref);
    3845        90990 :       if (!def_stmt)
    3846              :         return;
    3847              : 
    3848        90990 :       if (is_gimple_call (def_stmt))
    3849              :         {
    3850        46259 :           auto_diagnostic_group d;
    3851        46259 :           bool warned = false;
    3852        46259 :           if (gimple_call_alloc_p (def_stmt))
    3853              :             {
    3854        42380 :               if (matching_alloc_calls_p (def_stmt, dealloc_decl))
    3855              :                 {
    3856        41960 :                   if (warn_dealloc_offset (loc, call, aref))
    3857              :                     return;
    3858              :                 }
    3859              :               else
    3860              :                 {
    3861          420 :                   tree alloc_decl = gimple_call_fndecl (def_stmt);
    3862          420 :                   const opt_code opt =
    3863          420 :                     (DECL_IS_OPERATOR_NEW_P (alloc_decl)
    3864          172 :                      || DECL_IS_OPERATOR_DELETE_P (dealloc_decl)
    3865          420 :                      ? OPT_Wmismatched_new_delete
    3866              :                      : OPT_Wmismatched_dealloc);
    3867          420 :                   warned = warning_at (loc, opt,
    3868              :                                        "%qD called on pointer returned "
    3869              :                                        "from a mismatched allocation "
    3870              :                                        "function", dealloc_decl);
    3871              :                 }
    3872              :             }
    3873         3879 :           else if (gimple_call_builtin_p (def_stmt, BUILT_IN_ALLOCA)
    3874         3879 :                    || gimple_call_builtin_p (def_stmt,
    3875              :                                              BUILT_IN_ALLOCA_WITH_ALIGN))
    3876           20 :             warned = warning_at (loc, OPT_Wfree_nonheap_object,
    3877              :                                  "%qD called on pointer to "
    3878              :                                  "an unallocated object",
    3879              :                                  dealloc_decl);
    3880         3859 :           else if (warn_dealloc_offset (loc, call, aref))
    3881              :             return;
    3882              : 
    3883          440 :           if (warned)
    3884              :             {
    3885          230 :               tree fndecl = gimple_call_fndecl (def_stmt);
    3886          230 :               inform (gimple_location (def_stmt),
    3887              :                       "returned from %qD", fndecl);
    3888          230 :               return;
    3889              :             }
    3890        46259 :         }
    3891        44731 :       else if (gimple_nop_p (def_stmt))
    3892              :         {
    3893        14758 :           ref = SSA_NAME_VAR (ref);
    3894              :           /* Diagnose freeing a pointer that includes a positive offset.  */
    3895        14758 :           if (TREE_CODE (ref) == PARM_DECL
    3896        14667 :               && !aref.deref
    3897        14667 :               && aref.sizrng[0] != aref.sizrng[1]
    3898        14758 :               && aref.offrng[0] > 0 && aref.offrng[1] > 0
    3899        14764 :               && warn_dealloc_offset (loc, call, aref))
    3900            6 :             return;
    3901              :         }
    3902              :     }
    3903              : }
    3904              : 
    3905              : /* Return true if either USE_STMT's basic block (that of a pointer's use)
    3906              :    is dominated by INVAL_STMT's (that of a pointer's invalidating statement,
    3907              :    which is either a clobber or a deallocation call), or if they're in
    3908              :    the same block, USE_STMT follows INVAL_STMT.  */
    3909              : 
    3910              : bool
    3911      5178274 : pass_waccess::use_after_inval_p (gimple *inval_stmt, gimple *use_stmt,
    3912              :                                  bool last_block /* = false */)
    3913              : {
    3914      5178274 :   tree clobvar =
    3915      5178274 :     gimple_clobber_p (inval_stmt) ? gimple_assign_lhs (inval_stmt) : NULL_TREE;
    3916              : 
    3917      5178274 :   basic_block inval_bb = gimple_bb (inval_stmt);
    3918      5178274 :   basic_block use_bb = gimple_bb (use_stmt);
    3919              : 
    3920      5178274 :   if (!inval_bb || !use_bb)
    3921              :     return false;
    3922              : 
    3923      5177248 :   if (inval_bb != use_bb)
    3924              :     {
    3925      4513980 :       if (dominated_by_p (CDI_DOMINATORS, use_bb, inval_bb))
    3926              :         return true;
    3927              : 
    3928      4512965 :       if (!clobvar || !last_block)
    3929              :         return false;
    3930              : 
    3931              :       /* Proceed only when looking for uses of dangling pointers.  */
    3932      3268094 :       auto gsi = gsi_for_stmt (use_stmt);
    3933              : 
    3934              :       /* A use statement in the last basic block in a function or one that
    3935              :          falls through to it is after any other prior clobber of the used
    3936              :          variable unless it's followed by a clobber of the same variable. */
    3937      3268094 :       basic_block bb = use_bb;
    3938      3268094 :       while (bb != inval_bb
    3939      3971737 :              && single_succ_p (bb)
    3940      5474802 :              && !(single_succ_edge (bb)->flags
    3941      1245731 :                   & (EDGE_EH | EDGE_ABNORMAL | EDGE_DFS_BACK)))
    3942              :         {
    3943     10508555 :           for (; !gsi_end_p (gsi); gsi_next_nondebug (&gsi))
    3944              :             {
    3945      9547578 :               gimple *stmt = gsi_stmt (gsi);
    3946      9547578 :               if (gimple_clobber_p (stmt))
    3947              :                 {
    3948       291270 :                   if (clobvar == gimple_assign_lhs (stmt))
    3949              :                     /* The use is followed by a clobber.  */
    3950              :                     return false;
    3951              :                 }
    3952              :             }
    3953              : 
    3954       960977 :           bb = single_succ (bb);
    3955      1921954 :           gsi = gsi_start_bb (bb);
    3956              :         }
    3957              : 
    3958              :       /* The use is one of a dangling pointer if a clobber of the variable
    3959              :          [the pointer points to] has not been found before the function exit
    3960              :          point.  */
    3961      3251631 :       return bb == EXIT_BLOCK_PTR_FOR_FN (cfun);
    3962              :     }
    3963              : 
    3964       663268 :   if (bitmap_set_bit (m_bb_uids_set, inval_bb->index))
    3965              :     /* The first time this basic block is visited assign increasing ids
    3966              :        to consecutive statements in it.  Use the ids to determine which
    3967              :        precedes which.  This avoids the linear traversal on subsequent
    3968              :        visits to the same block.  */
    3969       341392 :     renumber_gimple_stmt_uids_in_block (m_func, inval_bb);
    3970              : 
    3971       663268 :   return gimple_uid (inval_stmt) < gimple_uid (use_stmt);
    3972              : }
    3973              : 
    3974              : /* Issue a warning for the USE_STMT of pointer or reference REF rendered
    3975              :    invalid by INVAL_STMT.  REF may be null when it's been optimized away.
    3976              :    When nonnull, INVAL_STMT is the deallocation function that rendered
    3977              :    the pointer or reference dangling.  Otherwise, VAR is the auto variable
    3978              :    (including an unnamed temporary such as a compound literal) whose
    3979              :    lifetime's rended it dangling.  MAYBE is true to issue the "maybe"
    3980              :    kind of warning.  EQUALITY is true when the pointer is used in
    3981              :    an equality expression.  */
    3982              : 
    3983              : void
    3984        18149 : pass_waccess::warn_invalid_pointer (tree ref, gimple *use_stmt,
    3985              :                                     gimple *inval_stmt, tree var,
    3986              :                                     bool maybe, bool equality /* = false */)
    3987              : {
    3988              :   /* Avoid printing the unhelpful "<unknown>" in the diagnostics.  */
    3989        18149 :   if (ref && TREE_CODE (ref) == SSA_NAME)
    3990              :     {
    3991        18122 :       tree var = SSA_NAME_VAR (ref);
    3992        17431 :       if (!var)
    3993              :         ref = NULL_TREE;
    3994              :       /* Don't warn for cases like when a cdtor returns 'this' on ARM.  */
    3995        17431 :       else if (warning_suppressed_p (var, OPT_Wuse_after_free))
    3996              :         return;
    3997        17431 :       else if (DECL_ARTIFICIAL (var))
    3998          727 :         ref = NULL_TREE;
    3999              :     }
    4000              : 
    4001        18149 :   location_t use_loc = gimple_location (use_stmt);
    4002        18149 :   if (use_loc == UNKNOWN_LOCATION)
    4003              :     {
    4004            0 :       use_loc = m_func->function_end_locus;
    4005            0 :       if (!ref)
    4006              :         /* Avoid issuing a warning with no context other than
    4007              :            the function.  That would make it difficult to debug
    4008              :            in any but very simple cases.  */
    4009              :         return;
    4010              :     }
    4011              : 
    4012        18149 :   if (is_gimple_call (inval_stmt))
    4013              :     {
    4014        17862 :       if (!m_early_checks_p
    4015         5878 :           || (equality && warn_use_after_free < 3)
    4016         5617 :           || (maybe && warn_use_after_free < 2)
    4017        23438 :           || warning_suppressed_p (use_stmt, OPT_Wuse_after_free))
    4018        12286 :         return;
    4019              : 
    4020         5576 :       const tree inval_decl = gimple_call_fndecl (inval_stmt);
    4021              : 
    4022         5576 :       auto_diagnostic_group d;
    4023        11030 :       if ((ref && warning_at (use_loc, OPT_Wuse_after_free,
    4024              :                               (maybe
    4025              :                                ? G_("pointer %qE may be used after %qD")
    4026              :                                : G_("pointer %qE used after %qD")),
    4027              :                               ref, inval_decl))
    4028        10800 :           || (!ref && warning_at (use_loc, OPT_Wuse_after_free,
    4029              :                               (maybe
    4030              :                                ? G_("pointer may be used after %qD")
    4031              :                                : G_("pointer used after %qD")),
    4032              :                                   inval_decl)))
    4033              :         {
    4034          355 :           location_t loc = gimple_location (inval_stmt);
    4035          355 :           inform (loc, "call to %qD here", inval_decl);
    4036          355 :           suppress_warning (use_stmt, OPT_Wuse_after_free);
    4037              :         }
    4038         5576 :       return;
    4039         5576 :     }
    4040              : 
    4041          287 :   if (equality
    4042          281 :       || (maybe && warn_dangling_pointer < 2)
    4043          563 :       || warning_suppressed_p (use_stmt, OPT_Wdangling_pointer_))
    4044           66 :     return;
    4045              : 
    4046          221 :   if (DECL_NAME (var))
    4047              :     {
    4048          207 :       auto_diagnostic_group d;
    4049          207 :       if ((ref
    4050          174 :            && warning_at (use_loc, OPT_Wdangling_pointer_,
    4051              :                           (maybe
    4052              :                            ? G_("dangling pointer %qE to %qD may be used")
    4053              :                            : G_("using dangling pointer %qE to %qD")),
    4054              :                           ref, var))
    4055          207 :           || (!ref
    4056          214 :               && warning_at (use_loc, OPT_Wdangling_pointer_,
    4057              :                              (maybe
    4058              :                               ? G_("dangling pointer to %qD may be used")
    4059              :                               : G_("using a dangling pointer to %qD")),
    4060              :                              var)))
    4061           98 :         inform (DECL_SOURCE_LOCATION (var),
    4062              :                 "%qD declared here", var);
    4063          207 :       suppress_warning (use_stmt, OPT_Wdangling_pointer_);
    4064          207 :       return;
    4065          207 :     }
    4066              : 
    4067           14 :   if ((ref
    4068           14 :        && warning_at (use_loc, OPT_Wdangling_pointer_,
    4069              :                       (maybe
    4070              :                        ? G_("dangling pointer %qE to an unnamed temporary "
    4071              :                             "may be used")
    4072              :                        : G_("using dangling pointer %qE to an unnamed "
    4073              :                             "temporary")),
    4074              :                       ref))
    4075           14 :       || (!ref
    4076           12 :           && warning_at (use_loc, OPT_Wdangling_pointer_,
    4077              :                          (maybe
    4078              :                           ? G_("dangling pointer to an unnamed temporary "
    4079              :                                "may be used")
    4080              :                           : G_("using a dangling pointer to an unnamed "
    4081              :                                "temporary")))))
    4082              :     {
    4083           14 :       inform (DECL_SOURCE_LOCATION (var),
    4084              :               "unnamed temporary defined here");
    4085           14 :       suppress_warning (use_stmt, OPT_Wdangling_pointer_);
    4086              :     }
    4087              : }
    4088              : 
    4089              : /* If STMT is a call to either the standard realloc or to a user-defined
    4090              :    reallocation function returns its LHS and set *PTR to the reallocated
    4091              :    pointer.  Otherwise return null.  */
    4092              : 
    4093              : static tree
    4094       565761 : get_realloc_lhs (gimple *stmt, tree *ptr)
    4095              : {
    4096       565761 :   if (gimple_call_builtin_p (stmt, BUILT_IN_REALLOC))
    4097              :     {
    4098        20966 :       *ptr = gimple_call_arg (stmt, 0);
    4099        20966 :       return gimple_call_lhs (stmt);
    4100              :     }
    4101              : 
    4102       920911 :   gcall *call = dyn_cast<gcall *>(stmt);
    4103       376256 :   if (!call)
    4104              :     return NULL_TREE;
    4105              : 
    4106       376256 :   tree fnattr = NULL_TREE;
    4107       376256 :   tree fndecl = gimple_call_fndecl (call);
    4108       376256 :   if (fndecl)
    4109       376256 :     fnattr = DECL_ATTRIBUTES (fndecl);
    4110              :   else
    4111              :     {
    4112            0 :       tree fntype = gimple_call_fntype (stmt);
    4113            0 :       if (!fntype)
    4114              :         return NULL_TREE;
    4115            0 :       fnattr = TYPE_ATTRIBUTES (fntype);
    4116              :     }
    4117              : 
    4118       376256 :   if (!fnattr)
    4119              :     return NULL_TREE;
    4120              : 
    4121       368967 :   for (tree ats = fnattr;  (ats = lookup_attribute ("*dealloc", ats));
    4122        12489 :        ats = TREE_CHAIN (ats))
    4123              :     {
    4124        12629 :       tree args = TREE_VALUE (ats);
    4125        12629 :       if (!args)
    4126            0 :         continue;
    4127              : 
    4128        12629 :       tree alloc = TREE_VALUE (args);
    4129        12629 :       if (!alloc)
    4130            0 :         continue;
    4131              : 
    4132        12629 :       if (alloc == DECL_NAME (fndecl))
    4133              :         {
    4134          140 :           unsigned argno = 0;
    4135          140 :           if (tree index = TREE_CHAIN (args))
    4136           82 :             argno = TREE_INT_CST_LOW (TREE_VALUE (index)) - 1;
    4137          140 :           *ptr = gimple_call_arg (stmt, argno);
    4138          140 :           return gimple_call_lhs (stmt);
    4139              :         }
    4140              :     }
    4141              : 
    4142              :   return NULL_TREE;
    4143              : }
    4144              : 
    4145              : /* Warn if STMT is a call to a deallocation function that's not a match
    4146              :    for the REALLOC_STMT call.  Return true if warned.  */
    4147              : 
    4148              : static bool
    4149        83327 : maybe_warn_mismatched_realloc (tree ptr, gimple *realloc_stmt, gimple *stmt)
    4150              : {
    4151        83327 :   if (!is_gimple_call (stmt))
    4152              :     return false;
    4153              : 
    4154        39513 :   tree fndecl = gimple_call_fndecl (stmt);
    4155        39513 :   if (!fndecl)
    4156              :     return false;
    4157              : 
    4158        39513 :   unsigned argno = fndecl_dealloc_argno (fndecl);
    4159        39513 :   if (call_nargs (stmt) <= argno)
    4160              :     return false;
    4161              : 
    4162         2344 :   if (matching_alloc_calls_p (realloc_stmt, fndecl))
    4163              :     return false;
    4164              : 
    4165              :   /* Avoid printing the unhelpful "<unknown>" in the diagnostics.  */
    4166           42 :   if (ptr && TREE_CODE (ptr) == SSA_NAME
    4167           84 :       && (!SSA_NAME_VAR (ptr) || DECL_ARTIFICIAL (SSA_NAME_VAR (ptr))))
    4168              :     ptr = NULL_TREE;
    4169              : 
    4170           42 :   location_t loc = gimple_location (stmt);
    4171           42 :   tree realloc_decl = gimple_call_fndecl (realloc_stmt);
    4172           42 :   tree dealloc_decl = gimple_call_fndecl (stmt);
    4173           42 :   if (ptr && !warning_at (loc, OPT_Wmismatched_dealloc,
    4174              :                           "%qD called on pointer %qE passed to mismatched "
    4175              :                           "allocation function %qD",
    4176              :                           dealloc_decl, ptr, realloc_decl))
    4177            3 :     return false;
    4178           39 :   if (!ptr && !warning_at (loc, OPT_Wmismatched_dealloc,
    4179              :                            "%qD called on a pointer passed to mismatched "
    4180              :                            "reallocation function %qD",
    4181              :                            dealloc_decl, realloc_decl))
    4182            0 :     return false;
    4183              : 
    4184           39 :   inform (gimple_location (realloc_stmt),
    4185              :           "call to %qD", realloc_decl);
    4186           39 :   return true;
    4187              : }
    4188              : 
    4189              : /* Return true if P and Q point to the same object, and false if they
    4190              :    either don't or their relationship cannot be determined.  */
    4191              : 
    4192              : static bool
    4193        83298 : pointers_related_p (gimple *stmt, tree p, tree q, pointer_query &qry,
    4194              :                     auto_bitmap &visited)
    4195              : {
    4196        83298 :   if (!ptr_derefs_may_alias_p (p, q))
    4197              :     return false;
    4198              : 
    4199              :   /* TODO: Work harder to rule out relatedness.  */
    4200        83298 :   access_ref pref, qref;
    4201        83298 :   if (!qry.get_ref (p, stmt, &pref, 0)
    4202        83298 :       || !qry.get_ref (q, stmt, &qref, 0))
    4203              :     /* GET_REF() only rarely fails.  When it does, it's likely because
    4204              :        it involves a self-referential PHI.  Return a conservative result.  */
    4205            0 :     return false;
    4206              : 
    4207        83298 :   if (pref.ref == qref.ref)
    4208              :     return true;
    4209              : 
    4210              :   /* If either pointer is a PHI, iterate over all its operands and
    4211              :      return true if they're all related to the other pointer.  */
    4212          108 :   tree ptr = q;
    4213          108 :   unsigned version;
    4214          108 :   gphi *phi = pref.phi ();
    4215          108 :   if (phi)
    4216          108 :     version = SSA_NAME_VERSION (pref.ref);
    4217              :   else
    4218              :     {
    4219            0 :       phi = qref.phi ();
    4220            0 :       if (!phi)
    4221              :         return false;
    4222              : 
    4223            0 :       ptr = p;
    4224            0 :       version = SSA_NAME_VERSION (qref.ref);
    4225              :     }
    4226              : 
    4227          108 :   if (!bitmap_set_bit (visited, version))
    4228              :     return true;
    4229              : 
    4230           60 :   unsigned nargs = gimple_phi_num_args (phi);
    4231          180 :   for (unsigned i = 0; i != nargs; ++i)
    4232              :     {
    4233          120 :       tree arg = gimple_phi_arg_def (phi, i);
    4234          120 :       if (!pointers_related_p (stmt, arg, ptr, qry, visited))
    4235              :         return false;
    4236              :     }
    4237              : 
    4238              :   return true;
    4239              : }
    4240              : 
    4241              : /* Convenience wrapper for the above.  */
    4242              : 
    4243              : static bool
    4244        83178 : pointers_related_p (gimple *stmt, tree p, tree q, pointer_query &qry)
    4245              : {
    4246        83178 :   auto_bitmap visited;
    4247        83178 :   return pointers_related_p (stmt, p, q, qry, visited);
    4248        83178 : }
    4249              : 
    4250              : /* For a STMT either a call to a deallocation function or a clobber, warn
    4251              :    for uses of the pointer PTR it was called with (including its copies
    4252              :    or others derived from it by pointer arithmetic).  If STMT is a clobber,
    4253              :    VAR is the decl of the clobbered variable.  When MAYBE is true use
    4254              :    a "maybe" form of diagnostic.  */
    4255              : 
    4256              : void
    4257       565761 : pass_waccess::check_pointer_uses (gimple *stmt, tree ptr,
    4258              :                                   tree var /* = NULL_TREE */,
    4259              :                                   bool maybe /* = false */)
    4260              : {
    4261       565761 :   gcc_assert (TREE_CODE (ptr) == SSA_NAME);
    4262              : 
    4263       565761 :   const bool check_dangling = !is_gimple_call (stmt);
    4264       565761 :   basic_block stmt_bb = gimple_bb (stmt);
    4265              : 
    4266              :   /* If STMT is a reallocation function set to the reallocated pointer
    4267              :      and the LHS of the call, respectively.  */
    4268       565761 :   tree realloc_ptr = NULL_TREE;
    4269       565761 :   tree realloc_lhs = get_realloc_lhs (stmt, &realloc_ptr);
    4270              : 
    4271       565761 :   auto_bitmap visited;
    4272              : 
    4273       565761 :   auto_vec<tree, 8> pointers;
    4274       565761 :   pointers.quick_push (ptr);
    4275       565761 :   hash_map<tree, int> *phi_map = nullptr;
    4276              : 
    4277              :   /* Starting with PTR, iterate over POINTERS added by the loop, and
    4278              :      either warn for their uses in basic blocks dominated by the STMT
    4279              :      or in statements that follow it in the same basic block, or add
    4280              :      them to POINTERS if they point into the same object as PTR (i.e.,
    4281              :      are obtained by pointer arithmetic on PTR).  */
    4282      2573906 :   for (unsigned i = 0; i != pointers.length (); ++i)
    4283              :     {
    4284       721192 :       tree ptr = pointers[i];
    4285       721192 :       if (!bitmap_set_bit (visited, SSA_NAME_VERSION (ptr)))
    4286              :         /* Avoid revisiting the same pointer.  */
    4287           43 :         continue;
    4288              : 
    4289       721149 :       use_operand_p use_p;
    4290       721149 :       imm_use_iterator iter;
    4291      4561741 :       FOR_EACH_IMM_USE_FAST (use_p, iter, ptr)
    4292              :         {
    4293      3119443 :           gimple *use_stmt = USE_STMT (use_p);
    4294      3119443 :           if (use_stmt == stmt || is_gimple_debug (use_stmt))
    4295      1377794 :             continue;
    4296              : 
    4297              :           /* A clobber isn't a use.  */
    4298      1741649 :           if (gimple_clobber_p (use_stmt))
    4299        63016 :             continue;
    4300              : 
    4301      1678633 :           if (realloc_lhs)
    4302              :             {
    4303              :               /* Check to see if USE_STMT is a mismatched deallocation
    4304              :                  call for the pointer passed to realloc.  That's a bug
    4305              :                  regardless of the pointer's value and so warn.  */
    4306        83327 :               if (maybe_warn_mismatched_realloc (*use_p->use, stmt, use_stmt))
    4307          149 :                 continue;
    4308              : 
    4309              :               /* Pointers passed to realloc that are used in basic blocks
    4310              :                  where the realloc call is known to have failed are valid.
    4311              :                  Ignore pointers that nothing is known about.  Those could
    4312              :                  have escaped along with their nullness.  */
    4313        83288 :               prange vr;
    4314        83288 :               if (m_ptr_qry.rvals->range_of_expr (vr, realloc_lhs, use_stmt))
    4315              :                 {
    4316        83288 :                   if (vr.zero_p ())
    4317          110 :                     continue;
    4318              : 
    4319        83178 :                   if (!pointers_related_p (stmt, ptr, realloc_ptr, m_ptr_qry))
    4320            0 :                     continue;
    4321              :                 }
    4322        83288 :             }
    4323              : 
    4324      1678699 :           if (check_dangling
    4325      1678484 :               && gimple_code (use_stmt) == GIMPLE_RETURN)
    4326              :             /* Avoid interfering with -Wreturn-local-addr (which runs only
    4327              :                with optimization enabled so it won't diagnose cases that
    4328              :                would be caught here when optimization is disabled).  */
    4329          215 :             continue;
    4330              : 
    4331      1678269 :           bool equality = false;
    4332      1678269 :           if (is_gimple_assign (use_stmt))
    4333              :             {
    4334       971222 :               tree_code code = gimple_assign_rhs_code (use_stmt);
    4335       971222 :               equality = code == EQ_EXPR || code == NE_EXPR;
    4336              :             }
    4337       707047 :           else if (gcond *cond = dyn_cast<gcond *>(use_stmt))
    4338              :             {
    4339       210548 :               tree_code code = gimple_cond_code (cond);
    4340       210548 :               equality = code == EQ_EXPR || code == NE_EXPR;
    4341              :             }
    4342       496499 :           else if (gphi *phi = dyn_cast <gphi *> (use_stmt))
    4343              :             {
    4344              :               /* Only add a PHI result to POINTERS if all its
    4345              :                  operands are related to PTR, otherwise continue.  The
    4346              :                  PHI result is related once we've reached all arguments
    4347              :                  through this iteration.  That also means any invariant
    4348              :                  argument will make the PHI not related.  For arguments
    4349              :                  flowing over natural loop backedges we are optimistic
    4350              :                  (and diagnose the first iteration).  */
    4351       125955 :               tree lhs = gimple_phi_result (phi);
    4352       125955 :               if (!phi_map)
    4353        44214 :                 phi_map = new hash_map<tree, int>;
    4354       125955 :               bool existed_p;
    4355       125955 :               int &related = phi_map->get_or_insert (lhs, &existed_p);
    4356       125955 :               if (!existed_p)
    4357              :                 {
    4358        65368 :                   related = gimple_phi_num_args (phi) - 1;
    4359       339049 :                   for (unsigned j = 0; j < gimple_phi_num_args (phi); ++j)
    4360              :                     {
    4361       273681 :                       if ((unsigned) phi_arg_index_from_use (use_p) == j)
    4362        65368 :                         continue;
    4363       208313 :                       tree arg = gimple_phi_arg_def (phi, j);
    4364       208313 :                       edge e = gimple_phi_arg_edge (phi, j);
    4365       208313 :                       basic_block arg_bb;
    4366       208313 :                       if (dominated_by_p (CDI_DOMINATORS, e->src, e->dest)
    4367              :                           /* Make sure we are not forward visiting a
    4368              :                              backedge argument.  */
    4369       208313 :                           && (TREE_CODE (arg) != SSA_NAME
    4370        24478 :                               || (!SSA_NAME_IS_DEFAULT_DEF (arg)
    4371        24478 :                                   && ((arg_bb
    4372        24478 :                                          = gimple_bb (SSA_NAME_DEF_STMT (arg)))
    4373        24478 :                                       != e->dest)
    4374        12888 :                                   && !dominated_by_p (CDI_DOMINATORS,
    4375              :                                                       e->dest, arg_bb))))
    4376        12889 :                         related--;
    4377              :                     }
    4378              :                 }
    4379              :               else
    4380        60587 :                 related--;
    4381              : 
    4382       125955 :               if (related == 0)
    4383        18061 :                 pointers.safe_push (lhs);
    4384       125955 :               continue;
    4385       125955 :             }
    4386              : 
    4387              :           /* Warn if USE_STMT is dominated by the deallocation STMT.
    4388              :              Otherwise, add the pointer to POINTERS so that the uses
    4389              :              of any other pointers derived from it can be checked.  */
    4390      1552314 :           if (use_after_inval_p (stmt, use_stmt, check_dangling))
    4391              :             {
    4392        18026 :               basic_block use_bb = gimple_bb (use_stmt);
    4393        18026 :               bool this_maybe
    4394              :                 = (maybe
    4395        18026 :                    || !dominated_by_p (CDI_POST_DOMINATORS, stmt_bb, use_bb));
    4396        18026 :               warn_invalid_pointer (*use_p->use, use_stmt, stmt, var,
    4397              :                                     this_maybe, equality);
    4398        18026 :               continue;
    4399        18026 :             }
    4400              : 
    4401      1534288 :           if (is_gimple_assign (use_stmt))
    4402              :             {
    4403       969377 :               tree lhs = gimple_assign_lhs (use_stmt);
    4404       969377 :               if (TREE_CODE (lhs) == SSA_NAME)
    4405              :                 {
    4406       638944 :                   tree_code rhs_code = gimple_assign_rhs_code (use_stmt);
    4407       638944 :                   if (rhs_code == POINTER_PLUS_EXPR || rhs_code == SSA_NAME)
    4408       136037 :                     pointers.safe_push (lhs);
    4409              :                 }
    4410       969377 :               continue;
    4411       969377 :             }
    4412              : 
    4413      3684354 :           if (gcall *call = dyn_cast <gcall *>(use_stmt))
    4414              :             {
    4415       353552 :               if (gimple_call_return_arg (call) == ptr)
    4416        35490 :                 if (tree lhs = gimple_call_lhs (call))
    4417         1333 :                   if (TREE_CODE (lhs) == SSA_NAME)
    4418         1333 :                     pointers.safe_push (lhs);
    4419       353552 :               continue;
    4420       353552 :             }
    4421       721149 :         }
    4422              :     }
    4423              : 
    4424       565761 :   if (phi_map)
    4425        44214 :     delete phi_map;
    4426       565761 : }
    4427              : 
    4428              : /* Check call STMT for invalid accesses.  */
    4429              : 
    4430              : void
    4431     23131828 : pass_waccess::check_call (gcall *stmt)
    4432              : {
    4433              :   /* Skip special calls generated by the compiler.  */
    4434     23131828 :   if (gimple_call_from_thunk_p (stmt))
    4435              :     return;
    4436              : 
    4437              :   /* .ASAN_MARK doesn't access any vars, only modifies shadow memory.  */
    4438     23128565 :   if (gimple_call_internal_p (stmt)
    4439     23128565 :       && gimple_call_internal_fn (stmt) == IFN_ASAN_MARK)
    4440              :     return;
    4441              : 
    4442     23115516 :   if (m_check_dangling_p)
    4443              :     {
    4444     16224119 :       check_call_dangling (stmt);
    4445              : 
    4446              :       /* Don't do any other checks when doing dangling pointer checks the
    4447              :          second time.  */
    4448     16224119 :       if (!m_early_checks_p)
    4449              :         return;
    4450              :     }
    4451              : 
    4452     17238787 :   if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
    4453      3566885 :     check_builtin (stmt);
    4454              : 
    4455     17238787 :   if (tree callee = gimple_call_fndecl (stmt))
    4456              :     {
    4457              :       /* Check for uses of the pointer passed to either a standard
    4458              :          or a user-defined deallocation function.  */
    4459     16176886 :       unsigned argno = fndecl_dealloc_argno (callee);
    4460     16176886 :       if (argno < (unsigned) call_nargs (stmt))
    4461              :         {
    4462       330430 :           tree arg = call_arg (stmt, argno);
    4463       330430 :           if (TREE_CODE (arg) == SSA_NAME)
    4464       330120 :             check_pointer_uses (stmt, arg);
    4465              :         }
    4466              :     }
    4467              : 
    4468     17238787 :   check_call_access (stmt);
    4469              : 
    4470     17238787 :   if (m_early_checks_p)
    4471              :     return;
    4472              : 
    4473      6891397 :   maybe_check_dealloc_call (stmt);
    4474      6891397 :   check_nonstring_args (stmt);
    4475              : }
    4476              : 
    4477              : /* Check non-call STMT for invalid accesses.  */
    4478              : 
    4479              : void
    4480    132426040 : pass_waccess::check_stmt (gimple *stmt)
    4481              : {
    4482    132426040 :   if (m_check_dangling_p
    4483    132426040 :       && gimple_clobber_p (stmt, CLOBBER_STORAGE_END))
    4484              :     {
    4485              :       /* Ignore clobber statements in blocks with exceptional edges.  */
    4486      3379197 :       basic_block bb = gimple_bb (stmt);
    4487      3379197 :       edge e = EDGE_PRED (bb, 0);
    4488      3379197 :       if (e->flags & EDGE_EH)
    4489              :         return;
    4490              : 
    4491      2614363 :       tree var = gimple_assign_lhs (stmt);
    4492      2614363 :       m_clobbers.put (var, stmt);
    4493      2614363 :       return;
    4494              :     }
    4495              : 
    4496    129046843 :   if (is_gimple_assign (stmt))
    4497              :     {
    4498              :       /* Clobbered unnamed temporaries such as compound literals can be
    4499              :          revived.  Check for an assignment to one and remove it from
    4500              :          M_CLOBBERS.  */
    4501     95961644 :       tree lhs = gimple_assign_lhs (stmt);
    4502    119829710 :       while (handled_component_p (lhs))
    4503     23868066 :         lhs = TREE_OPERAND (lhs, 0);
    4504              : 
    4505     95961644 :       if (auto_var_p (lhs))
    4506     15594648 :         m_clobbers.remove (lhs);
    4507     95961644 :       return;
    4508              :     }
    4509              : 
    4510     33085199 :   if (greturn *ret = dyn_cast <greturn *> (stmt))
    4511              :     {
    4512      5313814 :       if (optimize && flag_isolate_erroneous_paths_dereference)
    4513              :         /* Avoid interfering with -Wreturn-local-addr (which runs only
    4514              :            with optimization enabled).  */
    4515      5313813 :         return;
    4516              : 
    4517      1121013 :       tree arg = gimple_return_retval (ret);
    4518      1121013 :       if (!arg || TREE_CODE (arg) != ADDR_EXPR)
    4519              :         return;
    4520              : 
    4521          315 :       arg = TREE_OPERAND (arg, 0);
    4522          423 :       while (handled_component_p (arg))
    4523          108 :         arg = TREE_OPERAND (arg, 0);
    4524              : 
    4525          315 :       if (!auto_var_p (arg))
    4526              :         return;
    4527              : 
    4528            3 :       gimple **pclobber = m_clobbers.get (arg);
    4529            3 :       if (!pclobber)
    4530              :         return;
    4531              : 
    4532            1 :       if (!use_after_inval_p (*pclobber, stmt))
    4533              :         return;
    4534              : 
    4535            1 :       warn_invalid_pointer (NULL_TREE, stmt, *pclobber, arg, false);
    4536              :     }
    4537              : }
    4538              : 
    4539              : /* Check basic block BB for invalid accesses.  */
    4540              : 
    4541              : void
    4542     44267156 : pass_waccess::check_block (basic_block bb)
    4543              : {
    4544              :   /* Iterate over statements, looking for function calls.  */
    4545    244092180 :   for (auto si = gsi_start_bb (bb); !gsi_end_p (si);
    4546    155557868 :        gsi_next_nondebug (&si))
    4547              :     {
    4548    155557868 :       gimple *stmt = gsi_stmt (si);
    4549    155557868 :       if (gcall *call = dyn_cast <gcall *> (stmt))
    4550     23131828 :         check_call (call);
    4551              :       else
    4552    132426040 :         check_stmt (stmt);
    4553              :     }
    4554     44267156 : }
    4555              : 
    4556              : /* Return the argument that the call STMT to a built-in function returns
    4557              :    (including with an offset) or null if it doesn't.  */
    4558              : 
    4559              : tree
    4560      2359222 : pass_waccess::gimple_call_return_arg (gcall *call)
    4561              : {
    4562              :   /* Check for attribute fn spec to see if the function returns one
    4563              :      of its arguments.  */
    4564      2359222 :   attr_fnspec fnspec = gimple_call_fnspec (call);
    4565      2359222 :   unsigned int argno;
    4566      2359222 :   if (!fnspec.returns_arg (&argno))
    4567              :     {
    4568      2286142 :       if (gimple_call_num_args (call) < 1)
    4569              :         return NULL_TREE;
    4570              : 
    4571      2217155 :       if (!gimple_call_builtin_p (call, BUILT_IN_NORMAL))
    4572              :         return NULL_TREE;
    4573              : 
    4574       297191 :       tree fndecl = gimple_call_fndecl (call);
    4575       297191 :       switch (DECL_FUNCTION_CODE (fndecl))
    4576              :         {
    4577              :         case BUILT_IN_MEMPCPY:
    4578              :         case BUILT_IN_MEMPCPY_CHK:
    4579              :         case BUILT_IN_MEMCHR:
    4580              :         case BUILT_IN_STRCHR:
    4581              :         case BUILT_IN_STRRCHR:
    4582              :         case BUILT_IN_STRSTR:
    4583              :         case BUILT_IN_STPCPY:
    4584              :         case BUILT_IN_STPCPY_CHK:
    4585              :         case BUILT_IN_STPNCPY:
    4586              :         case BUILT_IN_STPNCPY_CHK:
    4587              :           argno = 0;
    4588              :           break;
    4589              : 
    4590              :         default:
    4591              :           return NULL_TREE;
    4592              :         }
    4593              :     }
    4594              : 
    4595        88474 :   if (gimple_call_num_args (call) <= argno)
    4596              :     return NULL_TREE;
    4597              : 
    4598        88474 :   return gimple_call_arg (call, argno);
    4599              : }
    4600              : 
    4601              : /* Check for and diagnose all uses of the dangling pointer VAR to the auto
    4602              :    object DECL whose lifetime has ended.  OBJREF is true when VAR denotes
    4603              :    an access to a DECL that may have been clobbered.  */
    4604              : 
    4605              : void
    4606     14622018 : pass_waccess::check_dangling_uses (tree var, tree decl, bool maybe /* = false */,
    4607              :                                    bool objref /* = false */)
    4608              : {
    4609     14622018 :   if (!decl || !auto_var_p (decl))
    4610      6511663 :     return;
    4611              : 
    4612      8110355 :   gimple **pclob = m_clobbers.get (decl);
    4613      8110355 :   if (!pclob)
    4614              :     return;
    4615              : 
    4616      3612223 :   if (!objref)
    4617              :     {
    4618       168539 :       check_pointer_uses (*pclob, var, decl, maybe);
    4619       168539 :       return;
    4620              :     }
    4621              : 
    4622      3443684 :   gimple *use_stmt = SSA_NAME_DEF_STMT (var);
    4623      3443684 :   if (!use_after_inval_p (*pclob, use_stmt, true))
    4624              :     return;
    4625              : 
    4626           96 :   basic_block use_bb = gimple_bb (use_stmt);
    4627           96 :   basic_block clob_bb = gimple_bb (*pclob);
    4628           96 :   maybe = maybe || !dominated_by_p (CDI_POST_DOMINATORS, clob_bb, use_bb);
    4629           96 :   warn_invalid_pointer (var, use_stmt, *pclob, decl, maybe, false);
    4630              : }
    4631              : 
    4632              : /* Diagnose stores in BB and (recursively) its predecessors of the addresses
    4633              :    of local variables into nonlocal pointers that are left dangling after
    4634              :    the function returns.  Returns true when we can continue walking
    4635              :    the CFG to predecessors.  */
    4636              : 
    4637              : bool
    4638     15753801 : pass_waccess::check_dangling_stores (basic_block bb,
    4639              :                                      hash_set<tree> &stores)
    4640              : {
    4641              :   /* Iterate backwards over the statements looking for a store of
    4642              :      the address of a local variable into a nonlocal pointer.  */
    4643     53000789 :   for (auto gsi = gsi_last_nondebug_bb (bb); ; gsi_prev_nondebug (&gsi))
    4644              :     {
    4645     53000789 :       gimple *stmt = gsi_stmt (gsi);
    4646     53000789 :       if (!stmt)
    4647              :         break;
    4648              : 
    4649     41104478 :       if (warning_suppressed_p (stmt, OPT_Wdangling_pointer_))
    4650     37246369 :         continue;
    4651              : 
    4652     41049696 :       if (is_gimple_call (stmt)
    4653     41049696 :           && !(gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE)))
    4654              :         /* Avoid looking before nonconst, nonpure calls since those might
    4655              :            use the escaped locals.  */
    4656      3857490 :         return false;
    4657              : 
    4658     37349883 :       if (!is_gimple_assign (stmt) || gimple_clobber_p (stmt)
    4659     61820399 :           || !gimple_store_p (stmt))
    4660     32126316 :         continue;
    4661              : 
    4662      5223567 :       access_ref lhs_ref;
    4663      5223567 :       tree lhs = gimple_assign_lhs (stmt);
    4664      5223567 :       if (!m_ptr_qry.get_ref (lhs, stmt, &lhs_ref, 0))
    4665         9369 :         continue;
    4666              : 
    4667      5214198 :       if (TREE_CODE (lhs_ref.ref) == MEM_REF)
    4668              :         {
    4669        23365 :           lhs_ref.ref = TREE_OPERAND (lhs_ref.ref, 0);
    4670        23365 :           ++lhs_ref.deref;
    4671              :         }
    4672      5214198 :       if (TREE_CODE (lhs_ref.ref) == ADDR_EXPR)
    4673              :         {
    4674        10618 :           lhs_ref.ref = TREE_OPERAND (lhs_ref.ref, 0);
    4675        10618 :           --lhs_ref.deref;
    4676              :         }
    4677      5214198 :       if (TREE_CODE (lhs_ref.ref) == SSA_NAME)
    4678              :         {
    4679      1082607 :           gimple *def_stmt = SSA_NAME_DEF_STMT (lhs_ref.ref);
    4680      1082607 :           if (!gimple_nop_p (def_stmt))
    4681              :             /* Avoid looking at or before stores into unknown objects.  */
    4682              :             return false;
    4683              : 
    4684       924930 :           lhs_ref.ref = SSA_NAME_VAR (lhs_ref.ref);
    4685              :         }
    4686              : 
    4687      5056521 :       if (TREE_CODE (lhs_ref.ref) == PARM_DECL
    4688      5056521 :           && (lhs_ref.deref - DECL_BY_REFERENCE (lhs_ref.ref)) > 0)
    4689              :         /* Assignment through a (real) pointer/reference parameter.  */;
    4690      7370022 :       else if (VAR_P (lhs_ref.ref)
    4691      4207751 :                && !auto_var_p (lhs_ref.ref))
    4692              :         /* Assignment to/through a non-local variable.  */;
    4693              :       else
    4694              :         /* Something else, don't warn.  */
    4695      3162271 :         continue;
    4696              : 
    4697      1894250 :       if (stores.add (lhs_ref.ref))
    4698      1292723 :         continue;
    4699              : 
    4700              :       /* FIXME: Handle stores of alloca() and VLA.  */
    4701       601527 :       access_ref rhs_ref;
    4702       601527 :       tree rhs = gimple_assign_rhs1 (stmt);
    4703       601527 :       if (!m_ptr_qry.get_ref (rhs, stmt, &rhs_ref, 0)
    4704       601527 :           || rhs_ref.deref != -1)
    4705       573881 :         continue;
    4706              : 
    4707        27646 :       if (!auto_var_p (rhs_ref.ref))
    4708        27027 :         continue;
    4709              : 
    4710          619 :       auto_diagnostic_group d;
    4711          619 :       location_t loc = gimple_location (stmt);
    4712          619 :       if (warning_at (loc, OPT_Wdangling_pointer_,
    4713              :                       "storing the address of local variable %qD in %qE",
    4714              :                       rhs_ref.ref, lhs))
    4715              :         {
    4716           45 :           suppress_warning (stmt, OPT_Wdangling_pointer_);
    4717              : 
    4718           45 :           location_t loc = DECL_SOURCE_LOCATION (rhs_ref.ref);
    4719           45 :           inform (loc, "%qD declared here", rhs_ref.ref);
    4720              : 
    4721           45 :           loc = DECL_SOURCE_LOCATION (lhs_ref.ref);
    4722           45 :           inform (loc, "%qD declared here", lhs_ref.ref);
    4723              :         }
    4724     37247607 :     }
    4725              : 
    4726     11896311 :   return true;
    4727              : }
    4728              : 
    4729              : /* Diagnose stores of the addresses of local variables into nonlocal
    4730              :    pointers that are left dangling after the function returns.  */
    4731              : 
    4732              : void
    4733      3921988 : pass_waccess::check_dangling_stores ()
    4734              : {
    4735      3921988 :   if (EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (m_func)->preds) == 0)
    4736        58229 :     return;
    4737              : 
    4738      3863759 :   auto_bitmap bbs;
    4739      3863759 :   hash_set<tree> stores;
    4740      3863759 :   auto_vec<edge_iterator, 8> worklist (n_basic_blocks_for_fn (cfun) + 1);
    4741      3863759 :   worklist.quick_push (ei_start (EXIT_BLOCK_PTR_FOR_FN (m_func)->preds));
    4742     34300442 :   do
    4743              :     {
    4744     34300442 :       edge_iterator ei = worklist.last ();
    4745     34300442 :       basic_block src = ei_edge (ei)->src;
    4746     34300442 :       if (bitmap_set_bit (bbs, src->index))
    4747              :         {
    4748     15753801 :           if (check_dangling_stores (src, stores)
    4749     15753801 :               && EDGE_COUNT (src->preds) > 0)
    4750     10325109 :             worklist.quick_push (ei_start (src->preds));
    4751              :         }
    4752              :       else
    4753              :         {
    4754     18546641 :           if (ei_one_before_end_p (ei))
    4755     14188868 :             worklist.pop ();
    4756              :           else
    4757      4357773 :             ei_next (&worklist.last ());
    4758              :         }
    4759              :     }
    4760     68600884 :   while (!worklist.is_empty ());
    4761      3863759 : }
    4762              : 
    4763              : /* Check for and diagnose uses of dangling pointers to auto objects
    4764              :    whose lifetime has ended.  */
    4765              : 
    4766              : void
    4767      3921988 : pass_waccess::check_dangling_uses ()
    4768              : {
    4769      3921988 :   tree var;
    4770      3921988 :   unsigned i;
    4771    115098083 :   FOR_EACH_SSA_NAME (i, var, m_func)
    4772              :     {
    4773              :       /* For each SSA_NAME pointer VAR find the object it points to.
    4774              :          If the object is a clobbered local variable, check to see
    4775              :          if any of VAR's uses (or those of other pointers derived
    4776              :          from VAR) happens after the clobber.  If so, warn.  */
    4777              : 
    4778    106270597 :       gimple *def_stmt = SSA_NAME_DEF_STMT (var);
    4779    106270597 :       if (is_gimple_assign (def_stmt))
    4780              :         {
    4781     67836075 :           tree rhs = gimple_assign_rhs1 (def_stmt);
    4782     67836075 :           if (TREE_CODE (rhs) == ADDR_EXPR)
    4783              :             {
    4784      4567649 :               if (!POINTER_TYPE_P (TREE_TYPE (var)))
    4785      2042002 :                 continue;
    4786      2525647 :               check_dangling_uses (var, TREE_OPERAND (rhs, 0));
    4787              :             }
    4788              :           else
    4789              :             {
    4790              :               /* For other expressions, check the base DECL to see
    4791              :                  if it's been clobbered, most likely as a result of
    4792              :                  inlining a reference to it.  */
    4793     63268426 :               tree decl = get_base_address (rhs);
    4794     63268426 :               if (DECL_P (decl))
    4795     11885204 :                 check_dangling_uses (var, decl, false, true);
    4796              :             }
    4797              :         }
    4798     38434522 :       else if (POINTER_TYPE_P (TREE_TYPE (var)))
    4799              :         {
    4800      6355289 :           if (gcall *call = dyn_cast<gcall *>(def_stmt))
    4801              :             {
    4802      2005670 :               if (tree arg = gimple_call_return_arg (call))
    4803              :                 {
    4804        31856 :                   access_ref aref;
    4805        31856 :                   if (m_ptr_qry.get_ref (arg, call, &aref, 0)
    4806        31856 :                       && aref.deref < 0)
    4807         9579 :                     check_dangling_uses (var, aref.ref);
    4808              :                 }
    4809              :             }
    4810    111774403 :           else if (gphi *phi = dyn_cast <gphi *>(def_stmt))
    4811              :             {
    4812       598308 :               unsigned nargs = gimple_phi_num_args (phi);
    4813      2051507 :               for (unsigned i = 0; i != nargs; ++i)
    4814              :                 {
    4815      1453199 :                   access_ref aref;
    4816      1453199 :                   tree arg = gimple_phi_arg_def (phi, i);
    4817      1453199 :                   if (m_ptr_qry.get_ref (arg, phi, &aref, 0)
    4818      1453199 :                       && aref.deref < 0)
    4819       201588 :                     check_dangling_uses (var, aref.ref, true);
    4820              :                 }
    4821              :             }
    4822              :         }
    4823              :     }
    4824      3921988 : }
    4825              : 
    4826              : /* Check CALL arguments for dangling pointers (those that have been
    4827              :    clobbered) and warn if found.  */
    4828              : 
    4829              : void
    4830     16224119 : pass_waccess::check_call_dangling (gcall *call)
    4831              : {
    4832     16224119 :   unsigned nargs = gimple_call_num_args (call);
    4833     47304148 :   for (unsigned i = 0; i != nargs; ++i)
    4834              :     {
    4835     31080029 :       tree arg = gimple_call_arg (call, i);
    4836     31080029 :       if (TREE_CODE (arg) != ADDR_EXPR)
    4837     31080003 :         continue;
    4838              : 
    4839      8662191 :       arg = TREE_OPERAND (arg, 0);
    4840      8662191 :       if (!DECL_P (arg))
    4841      2866698 :         continue;
    4842              : 
    4843      5795493 :       gimple **pclobber = m_clobbers.get (arg);
    4844      5795493 :       if (!pclobber)
    4845      5613218 :         continue;
    4846              : 
    4847       182275 :       if (!use_after_inval_p (*pclobber, call))
    4848       182249 :         continue;
    4849              : 
    4850           26 :       warn_invalid_pointer (NULL_TREE, call, *pclobber, arg, false);
    4851              :     }
    4852     16224119 : }
    4853              : 
    4854              : /* Check function FUN for invalid accesses.  */
    4855              : 
    4856              : unsigned
    4857      5402827 : pass_waccess::execute (function *fun)
    4858              : {
    4859      5402827 :   auto_urlify_attributes sentinel;
    4860              : 
    4861      5402827 :   calculate_dominance_info (CDI_DOMINATORS);
    4862      5402827 :   calculate_dominance_info (CDI_POST_DOMINATORS);
    4863              : 
    4864              :   /* Set or clear EDGE_DFS_BACK bits on back edges.  */
    4865      5402827 :   mark_dfs_back_edges (fun);
    4866              : 
    4867              :   /* Create a new ranger instance and associate it with FUN.  */
    4868      5402827 :   m_ptr_qry.rvals = enable_ranger (fun);
    4869      5402827 :   m_func = fun;
    4870              : 
    4871      5402827 :   auto_bitmap bb_uids_set (&bitmap_default_obstack);
    4872      5402827 :   m_bb_uids_set = bb_uids_set;
    4873              : 
    4874      5402827 :   set_gimple_stmt_max_uid (m_func, 0);
    4875              : 
    4876      5402827 :   basic_block bb;
    4877     49669983 :   FOR_EACH_BB_FN (bb, fun)
    4878     44267156 :     check_block (bb);
    4879              : 
    4880      5402827 :   if (m_check_dangling_p)
    4881              :     {
    4882      3921988 :       check_dangling_uses ();
    4883      3921988 :       check_dangling_stores ();
    4884              :     }
    4885              : 
    4886      5402827 :   if (dump_file)
    4887          167 :     m_ptr_qry.dump (dump_file, (dump_flags & TDF_DETAILS) != 0);
    4888              : 
    4889      5402827 :   m_ptr_qry.flush_cache ();
    4890              : 
    4891              :   /* Release the ranger instance and replace it with a global ranger.
    4892              :      Also reset the pointer since calling disable_ranger() deletes it.  */
    4893      5402827 :   disable_ranger (fun);
    4894      5402827 :   m_ptr_qry.rvals = NULL;
    4895              : 
    4896      5402827 :   m_clobbers.empty ();
    4897      5402827 :   m_bb_uids_set = NULL;
    4898              : 
    4899      5402827 :   free_dominance_info (CDI_POST_DOMINATORS);
    4900      5402827 :   free_dominance_info (CDI_DOMINATORS);
    4901      5402827 :   return 0;
    4902      5402827 : }
    4903              : 
    4904              : }   // namespace
    4905              : 
    4906              : /* Return a new instance of the pass.  */
    4907              : 
    4908              : gimple_opt_pass *
    4909       288775 : make_pass_warn_access (gcc::context *ctxt)
    4910              : {
    4911       288775 :   return new pass_waccess (ctxt);
    4912              : }
        

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.