LCOV - code coverage report
Current view: top level - gcc - gimple-ssa-sprintf.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.1 % 1800 1694
Test Date: 2026-02-28 14:20:25 Functions: 98.0 % 51 50
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Copyright (C) 2016-2026 Free Software Foundation, Inc.
       2              :    Contributed by Martin Sebor <msebor@redhat.com>.
       3              : 
       4              : This file is part of GCC.
       5              : 
       6              : GCC is free software; you can redistribute it and/or modify it under
       7              : the terms of the GNU General Public License as published by the Free
       8              : Software Foundation; either version 3, or (at your option) any later
       9              : version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : for more details.
      15              : 
      16              : You should have received a copy of the GNU General Public License
      17              : along with GCC; see the file COPYING3.  If not see
      18              : <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : /* This file implements the printf-return-value pass.  The pass does
      21              :    two things: 1) it analyzes calls to formatted output functions like
      22              :    sprintf looking for possible buffer overflows and calls to bounded
      23              :    functions like snprintf for early truncation (and under the control
      24              :    of the -Wformat-length option issues warnings), and 2) under the
      25              :    control of the -fprintf-return-value option it folds the return
      26              :    value of safe calls into constants, making it possible to eliminate
      27              :    code that depends on the value of those constants.
      28              : 
      29              :    For all functions (bounded or not) the pass uses the size of the
      30              :    destination object.  That means that it will diagnose calls to
      31              :    snprintf not on the basis of the size specified by the function's
      32              :    second argument but rather on the basis of the size the first
      33              :    argument points to (if possible).  For bound-checking built-ins
      34              :    like __builtin___snprintf_chk the pass uses the size typically
      35              :    determined by __builtin_object_size and passed to the built-in
      36              :    by the Glibc inline wrapper.
      37              : 
      38              :    The pass handles all forms standard sprintf format directives,
      39              :    including character, integer, floating point, pointer, and strings,
      40              :    with the standard C flags, widths, and precisions.  For integers
      41              :    and strings it computes the length of output itself.  For floating
      42              :    point it uses MPFR to format known constants with up and down
      43              :    rounding and uses the resulting range of output lengths.  For
      44              :    strings it uses the length of string literals and the sizes of
      45              :    character arrays that a character pointer may point to as a bound
      46              :    on the longest string.  */
      47              : 
      48              : #include "config.h"
      49              : #include "system.h"
      50              : #include "coretypes.h"
      51              : #include "backend.h"
      52              : #include "tree.h"
      53              : #include "gimple.h"
      54              : #include "tree-pass.h"
      55              : #include "ssa.h"
      56              : #include "gimple-iterator.h"
      57              : #include "gimple-fold.h"
      58              : #include "gimple-pretty-print.h"
      59              : #include "diagnostic-core.h"
      60              : #include "fold-const.h"
      61              : #include "tree-ssa.h"
      62              : #include "tree-object-size.h"
      63              : #include "tree-cfg.h"
      64              : #include "tree-ssa-propagate.h"
      65              : #include "calls.h"
      66              : #include "cfgloop.h"
      67              : #include "tree-scalar-evolution.h"
      68              : #include "tree-ssa-loop.h"
      69              : #include "intl.h"
      70              : #include "langhooks.h"
      71              : 
      72              : #include "attribs.h"
      73              : #include "builtins.h"
      74              : #include "pointer-query.h"
      75              : #include "stor-layout.h"
      76              : 
      77              : #include "realmpfr.h"
      78              : #include "target.h"
      79              : 
      80              : #include "cpplib.h"
      81              : #include "input.h"
      82              : #include "toplev.h"
      83              : #include "substring-locations.h"
      84              : #include "diagnostic.h"
      85              : #include "domwalk.h"
      86              : #include "alloc-pool.h"
      87              : #include "vr-values.h"
      88              : #include "tree-ssa-strlen.h"
      89              : #include "tree-dfa.h"
      90              : 
      91              : /* The likely worst case value of MB_LEN_MAX for the target, large enough
      92              :    for UTF-8.  Ideally, this would be obtained by a target hook if it were
      93              :    to be used for optimization but it's good enough as is for warnings.  */
      94              : #define target_mb_len_max()   6
      95              : 
      96              : /* The maximum number of bytes a single non-string directive can result
      97              :    in.  This is the result of printf("%.*Lf", INT_MAX, -LDBL_MAX) for
      98              :    LDBL_MAX_10_EXP of 4932.  */
      99              : #define IEEE_MAX_10_EXP    4932
     100              : #define target_dir_max()   (target_int_max () + IEEE_MAX_10_EXP + 2)
     101              : 
     102              : namespace {
     103              : 
     104              : /* Set to the warning level for the current function which is equal
     105              :    either to warn_format_trunc for bounded functions or to
     106              :    warn_format_overflow otherwise.  */
     107              : 
     108              : static int warn_level;
     109              : 
     110              : /* The minimum, maximum, likely, and unlikely maximum number of bytes
     111              :    of output either a formatting function or an individual directive
     112              :    can result in.  */
     113              : 
     114              : struct result_range
     115              : {
     116              :   /* The absolute minimum number of bytes.  The result of a successful
     117              :      conversion is guaranteed to be no less than this.  (An erroneous
     118              :      conversion can be indicated by MIN > HOST_WIDE_INT_MAX.)  */
     119              :   unsigned HOST_WIDE_INT min;
     120              :   /* The likely maximum result that is used in diagnostics.  In most
     121              :      cases MAX is the same as the worst case UNLIKELY result.  */
     122              :   unsigned HOST_WIDE_INT max;
     123              :   /* The likely result used to trigger diagnostics.  For conversions
     124              :      that result in a range of bytes [MIN, MAX], LIKELY is somewhere
     125              :      in that range.  */
     126              :   unsigned HOST_WIDE_INT likely;
     127              :   /* In rare cases (e.g., for multibyte characters) UNLIKELY gives
     128              :      the worst cases maximum result of a directive.  In most cases
     129              :      UNLIKELY == MAX.  UNLIKELY is used to control the return value
     130              :      optimization but not in diagnostics.  */
     131              :   unsigned HOST_WIDE_INT unlikely;
     132              : };
     133              : 
     134              : /* Return the value of INT_MIN for the target.  */
     135              : 
     136              : static inline HOST_WIDE_INT
     137       764730 : target_int_min ()
     138              : {
     139       764730 :   return tree_to_shwi (TYPE_MIN_VALUE (integer_type_node));
     140              : }
     141              : 
     142              : /* Return the value of INT_MAX for the target.  */
     143              : 
     144              : static inline unsigned HOST_WIDE_INT
     145      2416788 : target_int_max ()
     146              : {
     147      2416788 :   return tree_to_uhwi (TYPE_MAX_VALUE (integer_type_node));
     148              : }
     149              : 
     150              : /* Return the value of SIZE_MAX for the target.  */
     151              : 
     152              : static inline unsigned HOST_WIDE_INT
     153       262453 : target_size_max ()
     154              : {
     155       262453 :   return tree_to_uhwi (TYPE_MAX_VALUE (size_type_node));
     156              : }
     157              : 
     158              : /* A straightforward mapping from the execution character set to the host
     159              :    character set indexed by execution character.  */
     160              : 
     161              : static char target_to_host_charmap[256];
     162              : 
     163              : /* Initialize a mapping from the execution character set to the host
     164              :    character set.  */
     165              : 
     166              : static bool
     167      4891677 : init_target_to_host_charmap ()
     168              : {
     169              :   /* If the percent sign is non-zero the mapping has already been
     170              :      initialized.  */
     171      4891677 :   if (target_to_host_charmap['%'])
     172              :     return true;
     173              : 
     174              :   /* Initialize the target_percent character (done elsewhere).  */
     175       110966 :   if (!init_target_chars ())
     176              :     return false;
     177              : 
     178              :   /* The subset of the source character set used by printf conversion
     179              :      specifications (strictly speaking, not all letters are used but
     180              :      they are included here for the sake of simplicity).  The dollar
     181              :      sign must be included even though it's not in the basic source
     182              :      character set.  */
     183       110966 :   const char srcset[] = " 0123456789!\"#%&'()*+,-./:;<=>?[\\]^_{|}~$"
     184              :     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
     185              : 
     186              :   /* Set the mapping for all characters to some ordinary value (i,e.,
     187              :      not none used in printf conversion specifications) and overwrite
     188              :      those that are used by conversion specifications with their
     189              :      corresponding values.  */
     190       110966 :   memset (target_to_host_charmap + 1, '?', sizeof target_to_host_charmap - 1);
     191              : 
     192              :   /* Are the two sets of characters the same?  */
     193       110966 :   bool all_same_p = true;
     194              : 
     195     10430804 :   for (const char *pc = srcset; *pc; ++pc)
     196              :     {
     197              :       /* Slice off the high end bits in case target characters are
     198              :          signed.  All values are expected to be non-nul, otherwise
     199              :          there's a problem.  */
     200     10319838 :       if (unsigned char tc = lang_hooks.to_target_charset (*pc))
     201              :         {
     202     10319838 :           target_to_host_charmap[tc] = *pc;
     203     10319838 :           if (tc != *pc)
     204          279 :             all_same_p = false;
     205              :         }
     206              :       else
     207              :         return false;
     208              : 
     209              :     }
     210              : 
     211              :   /* Set the first element to a non-zero value if the mapping
     212              :      is 1-to-1, otherwise leave it clear (NUL is assumed to be
     213              :      the same in both character sets).  */
     214       110966 :   target_to_host_charmap[0] = all_same_p;
     215              : 
     216       110966 :   return true;
     217              : }
     218              : 
     219              : /* Return the host source character corresponding to the character
     220              :    CH in the execution character set if one exists, or some innocuous
     221              :    (non-special, non-nul) source character otherwise.  */
     222              : 
     223              : static inline unsigned char
     224      2896829 : target_to_host (unsigned char ch)
     225              : {
     226      2896829 :   return target_to_host_charmap[ch];
     227              : }
     228              : 
     229              : /* Convert an initial substring of the string TARGSTR consisting of
     230              :    characters in the execution character set into a string in the
     231              :    source character set on the host and store up to HOSTSZ characters
     232              :    in the buffer pointed to by HOSTR.  Return HOSTR.  */
     233              : 
     234              : static const char*
     235         5481 : target_to_host (char *hostr, size_t hostsz, const char *targstr)
     236              : {
     237              :   /* Make sure the buffer is reasonably big.  */
     238         5481 :   gcc_assert (hostsz > 4);
     239              : 
     240              :   /* The interesting subset of source and execution characters are
     241              :      the same so no conversion is necessary.  However, truncate
     242              :      overlong strings just like the translated strings are.  */
     243         5481 :   if (target_to_host_charmap['\0'] == 1)
     244              :     {
     245         5418 :       size_t len = strlen (targstr);
     246         5418 :       if (len >= hostsz)
     247              :         {
     248          322 :           memcpy (hostr, targstr, hostsz - 4);
     249          322 :           strcpy (hostr + hostsz - 4, "...");
     250              :         }
     251              :       else
     252         5096 :         memcpy (hostr, targstr, len + 1);
     253         5418 :       return hostr;
     254              :     }
     255              : 
     256              :   /* Convert the initial substring of TARGSTR to the corresponding
     257              :      characters in the host set, appending "..." if TARGSTR is too
     258              :      long to fit.  Using the static buffer assumes the function is
     259              :      not called in between sequence points (which it isn't).  */
     260          330 :   for (char *ph = hostr; ; ++targstr)
     261              :     {
     262          330 :       *ph++ = target_to_host (*targstr);
     263          393 :       if (!*targstr)
     264              :         break;
     265              : 
     266          331 :       if (size_t (ph - hostr) == hostsz)
     267              :         {
     268            1 :           strcpy (ph - 4, "...");
     269            1 :           break;
     270              :         }
     271              :     }
     272              : 
     273              :   return hostr;
     274              : }
     275              : 
     276              : /* Convert the sequence of decimal digits in the execution character
     277              :    starting at *PS to a HOST_WIDE_INT, analogously to strtol.  Return
     278              :    the result and set *PS to one past the last converted character.
     279              :    On range error set ERANGE to the digit that caused it.  */
     280              : 
     281              : static inline HOST_WIDE_INT
     282         2445 : target_strtowi (const char **ps, const char **erange)
     283              : {
     284         2445 :   unsigned HOST_WIDE_INT val = 0;
     285        10651 :   for ( ; ; ++*ps)
     286              :     {
     287         6548 :       unsigned char c = target_to_host (**ps);
     288         6548 :       if (ISDIGIT (c))
     289              :         {
     290         4105 :           c -= '0';
     291              : 
     292              :           /* Check for overflow.  */
     293         4105 :           if (val > ((unsigned HOST_WIDE_INT) HOST_WIDE_INT_MAX - c) / 10LU)
     294              :             {
     295            2 :               val = HOST_WIDE_INT_MAX;
     296            2 :               *erange = *ps;
     297              : 
     298              :               /* Skip the remaining digits.  */
     299            2 :               do
     300            2 :                 c = target_to_host (*++*ps);
     301            2 :               while (ISDIGIT (c));
     302              :               break;
     303              :             }
     304              :           else
     305         4103 :             val = val * 10 + c;
     306              :         }
     307              :       else
     308              :         break;
     309         4103 :     }
     310              : 
     311         2445 :   return val;
     312              : }
     313              : 
     314              : /* Given FORMAT, set *PLOC to the source location of the format string
     315              :    and return the format string if it is known or null otherwise.  */
     316              : 
     317              : static const char*
     318       142784 : get_format_string (tree format, location_t *ploc)
     319              : {
     320       142784 :   *ploc = EXPR_LOC_OR_LOC (format, input_location);
     321              : 
     322       142784 :   return c_getstr (format);
     323              : }
     324              : 
     325              : /* For convenience and brevity, shorter named entrypoints of
     326              :    format_string_diagnostic_t::emit_warning_va and
     327              :    format_string_diagnostic_t::emit_warning_n_va.
     328              :    These have to be functions with the attribute so that exgettext
     329              :    works properly.  */
     330              : 
     331              : static bool
     332              : ATTRIBUTE_GCC_DIAG (5, 6)
     333         5977 : fmtwarn (const substring_loc &fmt_loc, location_t param_loc,
     334              :          const char *corrected_substring, opt_code opt,
     335              :          const char *gmsgid, ...)
     336              : {
     337         5977 :   format_string_diagnostic_t diag (fmt_loc, NULL, param_loc, NULL,
     338         5977 :                                    corrected_substring);
     339         5977 :   va_list ap;
     340         5977 :   va_start (ap, gmsgid);
     341         5977 :   bool warned = diag.emit_warning_va (opt, gmsgid, &ap);
     342         5977 :   va_end (ap);
     343              : 
     344         5977 :   return warned;
     345              : }
     346              : 
     347              : static bool
     348              : ATTRIBUTE_GCC_DIAG (6, 8) ATTRIBUTE_GCC_DIAG (7, 8)
     349          548 : fmtwarn_n (const substring_loc &fmt_loc, location_t param_loc,
     350              :            const char *corrected_substring, opt_code opt,
     351              :            unsigned HOST_WIDE_INT n,
     352              :            const char *singular_gmsgid, const char *plural_gmsgid, ...)
     353              : {
     354          548 :   format_string_diagnostic_t diag (fmt_loc, NULL, param_loc, NULL,
     355          548 :                                    corrected_substring);
     356          548 :   va_list ap;
     357          548 :   va_start (ap, plural_gmsgid);
     358          548 :   bool warned = diag.emit_warning_n_va (opt, n, singular_gmsgid, plural_gmsgid,
     359              :                                         &ap);
     360          548 :   va_end (ap);
     361              : 
     362          548 :   return warned;
     363              : }
     364              : 
     365              : /* Format length modifiers.  */
     366              : 
     367              : enum format_lengths
     368              : {
     369              :   FMT_LEN_none,
     370              :   FMT_LEN_hh,    // char argument
     371              :   FMT_LEN_h,     // short
     372              :   FMT_LEN_l,     // long
     373              :   FMT_LEN_ll,    // long long
     374              :   FMT_LEN_L,     // long double (and GNU long long)
     375              :   FMT_LEN_z,     // size_t
     376              :   FMT_LEN_t,     // ptrdiff_t
     377              :   FMT_LEN_j      // intmax_t
     378              : };
     379              : 
     380              : 
     381              : /* Description of the result of conversion either of a single directive
     382              :    or the whole format string.  */
     383              : 
     384              : class fmtresult
     385              : {
     386              : public:
     387              :   /* Construct a FMTRESULT object with all counters initialized
     388              :      to MIN.  KNOWNRANGE is set when MIN is valid.  */
     389      1092648 :   fmtresult (unsigned HOST_WIDE_INT min = HOST_WIDE_INT_MAX)
     390      1092648 :   : argmin (), argmax (), dst_offset (HOST_WIDE_INT_MIN), nonstr (),
     391      1091020 :     knownrange (min < HOST_WIDE_INT_MAX),
     392      1092648 :     mayfail (), nullp ()
     393              :   {
     394      1092648 :     range.min = min;
     395      1092648 :     range.max = min;
     396      1092648 :     range.likely = min;
     397      1092648 :     range.unlikely = min;
     398          695 :   }
     399              : 
     400              :   /* Construct a FMTRESULT object with MIN, MAX, and LIKELY counters.
     401              :      KNOWNRANGE is set when both MIN and MAX are valid.   */
     402       255388 :   fmtresult (unsigned HOST_WIDE_INT min, unsigned HOST_WIDE_INT max,
     403              :              unsigned HOST_WIDE_INT likely = HOST_WIDE_INT_MAX)
     404       255388 :   : argmin (), argmax (), dst_offset (HOST_WIDE_INT_MIN), nonstr (),
     405       255388 :     knownrange (min < HOST_WIDE_INT_MAX && max < HOST_WIDE_INT_MAX),
     406       255388 :     mayfail (), nullp ()
     407              :   {
     408       255388 :     range.min = min;
     409       255388 :     range.max = max;
     410       255388 :     range.likely = max < likely ? min : likely;
     411       255388 :     range.unlikely = max;
     412              :   }
     413              : 
     414              :   /* Adjust result upward to reflect the RANGE of values the specified
     415              :      width or precision is known to be in.  */
     416              :   fmtresult& adjust_for_width_or_precision (const HOST_WIDE_INT[2],
     417              :                                             tree = NULL_TREE,
     418              :                                             unsigned = 0, unsigned = 0);
     419              : 
     420              :   /* Return the maximum number of decimal digits a value of TYPE
     421              :      formats as on output.  */
     422              :   static unsigned type_max_digits (tree, int);
     423              : 
     424              :   /* The range a directive's argument is in.  */
     425              :   tree argmin, argmax;
     426              : 
     427              :   /* The starting offset into the destination of the formatted function
     428              :      call of the %s argument that points into (aliases with) the same
     429              :      destination array.  */
     430              :   HOST_WIDE_INT dst_offset;
     431              : 
     432              :   /* The minimum and maximum number of bytes that a directive
     433              :      results in on output for an argument in the range above.  */
     434              :   result_range range;
     435              : 
     436              :   /* Non-nul when the argument of a string directive is not a nul
     437              :      terminated string.  */
     438              :   tree nonstr;
     439              : 
     440              :   /* True when the range above is obtained from a known value of
     441              :      a directive's argument or its bounds and not the result of
     442              :      heuristics that depend on warning levels.  */
     443              :   bool knownrange;
     444              : 
     445              :   /* True for a directive that may fail (such as wide character
     446              :      directives).  */
     447              :   bool mayfail;
     448              : 
     449              :   /* True when the argument is a null pointer.  */
     450              :   bool nullp;
     451              : };
     452              : 
     453              : /* Adjust result upward to reflect the range ADJUST of values the
     454              :    specified width or precision is known to be in.  When non-null,
     455              :    TYPE denotes the type of the directive whose result is being
     456              :    adjusted, BASE gives the base of the directive (octal, decimal,
     457              :    or hex), and ADJ denotes the additional adjustment to the LIKELY
     458              :    counter that may need to be added when ADJUST is a range.  */
     459              : 
     460              : fmtresult&
     461       769490 : fmtresult::adjust_for_width_or_precision (const HOST_WIDE_INT adjust[2],
     462              :                                           tree type /* = NULL_TREE */,
     463              :                                           unsigned base /* = 0 */,
     464              :                                           unsigned adj /* = 0 */)
     465              : {
     466       769490 :   bool minadjusted = false;
     467              : 
     468              :   /* Adjust the minimum and likely counters.  */
     469       769490 :   if (adjust[0] >= 0)
     470              :     {
     471         4760 :       if (range.min < (unsigned HOST_WIDE_INT)adjust[0])
     472              :         {
     473         1528 :           range.min = adjust[0];
     474         1528 :           minadjusted = true;
     475              :         }
     476              : 
     477              :       /* Adjust the likely counter.  */
     478         4760 :       if (range.likely < range.min)
     479         1371 :         range.likely = range.min;
     480              :     }
     481       764730 :   else if (adjust[0] == target_int_min ()
     482       764730 :            && (unsigned HOST_WIDE_INT)adjust[1] == target_int_max ())
     483            0 :     knownrange = false;
     484              : 
     485              :   /* Adjust the maximum counter.  */
     486       769490 :   if (adjust[1] > 0)
     487              :     {
     488         4803 :       if (range.max < (unsigned HOST_WIDE_INT)adjust[1])
     489              :         {
     490         1659 :           range.max = adjust[1];
     491              : 
     492              :           /* Set KNOWNRANGE if both the minimum and maximum have been
     493              :              adjusted.  Otherwise leave it at what it was before.  */
     494         1659 :           knownrange = minadjusted;
     495              :         }
     496              :     }
     497              : 
     498       769490 :   if (warn_level > 1 && type)
     499              :     {
     500              :       /* For large non-constant width or precision whose range spans
     501              :          the maximum number of digits produced by the directive for
     502              :          any argument, set the likely number of bytes to be at most
     503              :          the number digits plus other adjustment determined by the
     504              :          caller (one for sign or two for the hexadecimal "0x"
     505              :          prefix).  */
     506          904 :       unsigned dirdigs = type_max_digits (type, base);
     507          904 :       if (adjust[0] < dirdigs && dirdigs < adjust[1]
     508           28 :           && range.likely < dirdigs)
     509           16 :         range.likely = dirdigs + adj;
     510              :     }
     511       768586 :   else if (range.likely < (range.min ? range.min : 1))
     512              :     {
     513              :       /* Conservatively, set LIKELY to at least MIN but no less than
     514              :          1 unless MAX is zero.  */
     515        13405 :       range.likely = (range.min
     516        13405 :                       ? range.min
     517        12737 :                       : range.max && (range.max < HOST_WIDE_INT_MAX
     518        25871 :                                       || warn_level > 1) ? 1 : 0);
     519              :     }
     520              : 
     521              :   /* Finally adjust the unlikely counter to be at least as large as
     522              :      the maximum.  */
     523       769490 :   if (range.unlikely < range.max)
     524         1798 :     range.unlikely = range.max;
     525              : 
     526       769490 :   return *this;
     527              : }
     528              : 
     529              : /* Return the maximum number of digits a value of TYPE formats in
     530              :    BASE on output, not counting base prefix .  */
     531              : 
     532              : unsigned
     533          904 : fmtresult::type_max_digits (tree type, int base)
     534              : {
     535          904 :   unsigned prec = TYPE_PRECISION (type);
     536          904 :   switch (base)
     537              :     {
     538              :     case 2:
     539              :       return prec;
     540            0 :     case 8:
     541            0 :       return (prec + 2) / 3;
     542          904 :     case 10:
     543              :       /* Decimal approximation: yields 3, 5, 10, and 20 for precision
     544              :          of 8, 16, 32, and 64 bits.  */
     545          904 :       return prec * 301 / 1000 + 1;
     546            0 :     case 16:
     547            0 :       return prec / 4;
     548              :     }
     549              : 
     550            0 :   gcc_unreachable ();
     551              : }
     552              : 
     553              : static bool
     554              : get_int_range (tree, gimple *, HOST_WIDE_INT *, HOST_WIDE_INT *,
     555              :                bool, HOST_WIDE_INT, range_query *);
     556              : 
     557              : struct call_info;
     558              : 
     559              : /* Description of a format directive.  A directive is either a plain
     560              :    string or a conversion specification that starts with '%'.  */
     561              : 
     562              : struct directive
     563              : {
     564       966970 :   directive (const call_info *inf, unsigned dno)
     565       966970 :     : info (inf), dirno (dno), argno (), beg (), len (), flags (),
     566       966970 :     width (), prec (),  modifier (), specifier (), arg (), fmtfunc ()
     567       966970 :   { }
     568              : 
     569              :   /* Reference to the info structure describing the call that this
     570              :      directive is a part of.  */
     571              :   const call_info *info;
     572              : 
     573              :   /* The 1-based directive number (for debugging).  */
     574              :   unsigned dirno;
     575              : 
     576              :   /* The zero-based argument number of the directive's argument ARG in
     577              :      the function's argument list.  */
     578              :   unsigned argno;
     579              : 
     580              :   /* The first character of the directive and its length.  */
     581              :   const char *beg;
     582              :   size_t len;
     583              : 
     584              :   /* A bitmap of flags, one for each character.  */
     585              :   unsigned flags[256 / sizeof (int)];
     586              : 
     587              :   /* The range of values of the specified width, or -1 if not specified.  */
     588              :   HOST_WIDE_INT width[2];
     589              :   /* The range of values of the specified precision, or -1 if not
     590              :      specified.  */
     591              :   HOST_WIDE_INT prec[2];
     592              : 
     593              :   /* Length modifier.  */
     594              :   format_lengths modifier;
     595              : 
     596              :   /* Format specifier character.  */
     597              :   char specifier;
     598              : 
     599              :   /* The argument of the directive or null when the directive doesn't
     600              :      take one or when none is available (such as for vararg functions).  */
     601              :   tree arg;
     602              : 
     603              :   /* Format conversion function that given a directive and an argument
     604              :      returns the formatting result.  */
     605              :   fmtresult (*fmtfunc) (const directive &, tree, pointer_query &);
     606              : 
     607              :   /* Return True when the format flag CHR has been used.  */
     608       485218 :   bool get_flag (char chr) const
     609              :   {
     610       485218 :     unsigned char c = chr & 0xff;
     611       485218 :     return (flags[c / (CHAR_BIT * sizeof *flags)]
     612       485218 :             & (1U << (c % (CHAR_BIT * sizeof *flags))));
     613              :   }
     614              : 
     615              :   /* Make a record of the format flag CHR having been used.  */
     616         1787 :   void set_flag (char chr)
     617              :   {
     618         1787 :     unsigned char c = chr & 0xff;
     619         1787 :     flags[c / (CHAR_BIT * sizeof *flags)]
     620         1787 :       |= (1U << (c % (CHAR_BIT * sizeof *flags)));
     621         1787 :   }
     622              : 
     623              :   /* Reset the format flag CHR.  */
     624              :   void clear_flag (char chr)
     625              :   {
     626              :     unsigned char c = chr & 0xff;
     627              :     flags[c / (CHAR_BIT * sizeof *flags)]
     628              :       &= ~(1U << (c % (CHAR_BIT * sizeof *flags)));
     629              :   }
     630              : 
     631              :   /* Set both bounds of the width range to VAL.  */
     632       406335 :   void set_width (HOST_WIDE_INT val)
     633              :   {
     634       406335 :     width[0] = width[1] = val;
     635       406335 :   }
     636              : 
     637              :   /* Set the width range according to ARG, with both bounds being
     638              :      no less than 0.  For a constant ARG set both bounds to its value
     639              :      or 0, whichever is greater.  For a non-constant ARG in some range
     640              :      set width to its range adjusting each bound to -1 if it's less.
     641              :      For an indeterminate ARG set width to [0, INT_MAX].  */
     642              :   void set_width (tree arg, range_query *);
     643              : 
     644              :   /* Set both bounds of the precision range to VAL.  */
     645       406237 :   void set_precision (HOST_WIDE_INT val)
     646              :   {
     647       406237 :     prec[0] = prec[1] = val;
     648       406237 :   }
     649              : 
     650              :   /* Set the precision range according to ARG, with both bounds being
     651              :      no less than -1.  For a constant ARG set both bounds to its value
     652              :      or -1 whichever is greater.  For a non-constant ARG in some range
     653              :      set precision to its range adjusting each bound to -1 if it's less.
     654              :      For an indeterminate ARG set precision to [-1, INT_MAX].  */
     655              :   void set_precision (tree arg, range_query *query);
     656              : 
     657              :   /* Return true if both width and precision are known to be
     658              :      either constant or in some range, false otherwise.  */
     659        19548 :   bool known_width_and_precision () const
     660              :   {
     661        19548 :     return ((width[1] < 0
     662          293 :              || (unsigned HOST_WIDE_INT)width[1] <= target_int_max ())
     663        19811 :             && (prec[1] < 0
     664          163 :                 || (unsigned HOST_WIDE_INT)prec[1] < target_int_max ()));
     665              :   }
     666              : };
     667              : 
     668              : /* The result of a call to a formatted function.  */
     669              : 
     670              : struct format_result
     671              : {
     672       137471 :   format_result ()
     673       137471 :     : range (), aliases (), alias_count (), knownrange (), posunder4k (),
     674       137471 :     floating (), warned () { /* No-op.  */ }
     675              : 
     676       137471 :   ~format_result ()
     677              :   {
     678       137471 :     XDELETEVEC (aliases);
     679       137471 :   }
     680              : 
     681              :   /* Range of characters written by the formatted function.
     682              :      Setting the minimum to HOST_WIDE_INT_MAX disables all
     683              :      length tracking for the remainder of the format string.  */
     684              :   result_range range;
     685              : 
     686              :   struct alias_info
     687              :   {
     688              :     directive dir;          /* The directive that aliases the destination.  */
     689              :     HOST_WIDE_INT offset;   /* The offset at which it aliases it.  */
     690              :     result_range range;     /* The raw result of the directive.  */
     691              :   };
     692              : 
     693              :   /* An array of directives whose pointer argument aliases a part
     694              :      of the destination object of the formatted function.  */
     695              :   alias_info *aliases;
     696              :   unsigned alias_count;
     697              : 
     698              :   /* True when the range above is obtained from known values of
     699              :      directive arguments, or bounds on the amount of output such
     700              :      as width and precision, and not the result of  heuristics that
     701              :      depend on warning levels.  It's used to issue stricter diagnostics
     702              :      in cases where strings of unknown lengths are bounded by the arrays
     703              :      they are determined to refer to.  KNOWNRANGE must not be used for
     704              :      the return value optimization.  */
     705              :   bool knownrange;
     706              : 
     707              :   /* True if no individual directive could fail or result in more than
     708              :      4095 bytes of output (the total NUMBER_CHARS_{MIN,MAX} might be
     709              :      greater).  Implementations are not required to handle directives
     710              :      that produce more than 4K bytes (leading to undefined behavior)
     711              :      and so when one is found it disables the return value optimization.
     712              :      Similarly, directives that can fail (such as wide character
     713              :      directives) disable the optimization.  */
     714              :   bool posunder4k;
     715              : 
     716              :   /* True when a floating point directive has been seen in the format
     717              :      string.  */
     718              :   bool floating;
     719              : 
     720              :   /* True when an intermediate result has caused a warning.  Used to
     721              :      avoid issuing duplicate warnings while finishing the processing
     722              :      of a call.  WARNED also disables the return value optimization.  */
     723              :   bool warned;
     724              : 
     725              :   /* Preincrement the number of output characters by 1.  */
     726              :   format_result& operator++ ()
     727              :   {
     728              :     return *this += 1;
     729              :   }
     730              : 
     731              :   /* Postincrement the number of output characters by 1.  */
     732              :   format_result operator++ (int)
     733              :   {
     734              :     format_result prev (*this);
     735              :     *this += 1;
     736              :     return prev;
     737              :   }
     738              : 
     739              :   /* Increment the number of output characters by N.  */
     740              :   format_result& operator+= (unsigned HOST_WIDE_INT);
     741              : 
     742              :   /* Add a directive to the sequence of those with potentially aliasing
     743              :      arguments.  */
     744              :   void append_alias (const directive &, HOST_WIDE_INT, const result_range &);
     745              : 
     746              : private:
     747              :   /* Not copyable or assignable.  */
     748              :   format_result (format_result&);
     749              :   void operator= (format_result&);
     750              : };
     751              : 
     752              : format_result&
     753            0 : format_result::operator+= (unsigned HOST_WIDE_INT n)
     754              : {
     755            0 :   gcc_assert (n < HOST_WIDE_INT_MAX);
     756              : 
     757            0 :   if (range.min < HOST_WIDE_INT_MAX)
     758            0 :     range.min += n;
     759              : 
     760            0 :   if (range.max < HOST_WIDE_INT_MAX)
     761            0 :     range.max += n;
     762              : 
     763            0 :   if (range.likely < HOST_WIDE_INT_MAX)
     764            0 :     range.likely += n;
     765              : 
     766            0 :   if (range.unlikely < HOST_WIDE_INT_MAX)
     767            0 :     range.unlikely += n;
     768              : 
     769            0 :   return *this;
     770              : }
     771              : 
     772              : void
     773          262 : format_result::append_alias (const directive &d, HOST_WIDE_INT off,
     774              :                              const result_range &resrng)
     775              : {
     776          262 :   unsigned cnt = alias_count + 1;
     777          262 :   alias_info *ar = XNEWVEC (alias_info, cnt);
     778              : 
     779          266 :   for (unsigned i = 0; i != alias_count; ++i)
     780            4 :     ar[i] = aliases[i];
     781              : 
     782          262 :   ar[alias_count].dir = d;
     783          262 :   ar[alias_count].offset = off;
     784          262 :   ar[alias_count].range = resrng;
     785              : 
     786          262 :   XDELETEVEC (aliases);
     787              : 
     788          262 :   alias_count = cnt;
     789          262 :   aliases = ar;
     790          262 : }
     791              : 
     792              : /* Return the logarithm of X in BASE.  */
     793              : 
     794              : static int
     795       205124 : ilog (unsigned HOST_WIDE_INT x, int base)
     796              : {
     797            0 :   int res = 0;
     798       960828 :   do
     799              :     {
     800       960828 :       ++res;
     801       960828 :       x /= base;
     802       960828 :     } while (x);
     803       205124 :   return res;
     804              : }
     805              : 
     806              : /* Return the number of bytes resulting from converting into a string
     807              :    the INTEGER_CST tree node X in BASE with a minimum of PREC digits.
     808              :    PLUS indicates whether 1 for a plus sign should be added for positive
     809              :    numbers, and PREFIX whether the length of an octal ('0') or hexadecimal
     810              :    ('0x') or binary ('0b') prefix should be added for nonzero numbers.
     811              :    Return -1 if X cannot be represented.  */
     812              : 
     813              : static HOST_WIDE_INT
     814       205124 : tree_digits (tree x, int base, HOST_WIDE_INT prec, bool plus, bool prefix)
     815              : {
     816       205124 :   unsigned HOST_WIDE_INT absval;
     817              : 
     818       205124 :   HOST_WIDE_INT res;
     819              : 
     820       205124 :   if (TYPE_UNSIGNED (TREE_TYPE (x)))
     821              :     {
     822        12690 :       if (tree_fits_uhwi_p (x))
     823              :         {
     824        12690 :           absval = tree_to_uhwi (x);
     825        12690 :           res = plus;
     826              :         }
     827              :       else
     828              :         return -1;
     829              :     }
     830              :   else
     831              :     {
     832       192434 :       if (tree_fits_shwi_p (x))
     833              :         {
     834       192434 :           HOST_WIDE_INT i = tree_to_shwi (x);
     835       192434 :          if (HOST_WIDE_INT_MIN == i)
     836              :            {
     837              :              /* Avoid undefined behavior due to negating a minimum.  */
     838              :              absval = HOST_WIDE_INT_MAX;
     839              :              res = 1;
     840              :            }
     841       188152 :          else if (i < 0)
     842              :            {
     843        26715 :              absval = -i;
     844        26715 :              res = 1;
     845              :            }
     846              :          else
     847              :            {
     848       161437 :              absval = i;
     849       161437 :              res = plus;
     850              :            }
     851              :         }
     852              :       else
     853              :         return -1;
     854              :     }
     855              : 
     856       205124 :   int ndigs = ilog (absval, base);
     857              : 
     858       205124 :   res += prec < ndigs ? ndigs : prec;
     859              : 
     860              :   /* Adjust a non-zero value for the base prefix, either hexadecimal,
     861              :      or, unless precision has resulted in a leading zero, also octal.  */
     862       205124 :   if (prefix && absval)
     863              :     {
     864          421 :       if (base == 8 && prec <= ndigs)
     865          141 :         res += 1;
     866          280 :       else if (base == 16 || base == 2) /* 0x...(0X...) or 0b...(0B...).  */
     867          247 :         res += 2;
     868              :     }
     869              : 
     870              :   return res;
     871              : }
     872              : 
     873              : /* Description of a call to a formatted function.  */
     874              : 
     875              : struct call_info
     876              : {
     877              :   /* Function call statement.  */
     878              :   gimple *callstmt;
     879              : 
     880              :   /* Function called.  */
     881              :   tree func;
     882              : 
     883              :   /* Called built-in function code.  */
     884              :   built_in_function fncode;
     885              : 
     886              :   /* The "origin" of the destination pointer argument, which is either
     887              :      the DECL of the destination buffer being written into or a pointer
     888              :      that points to it, plus some offset.  */
     889              :   tree dst_origin;
     890              : 
     891              :   /* For a destination pointing to a struct array member, the offset of
     892              :      the member.  */
     893              :   HOST_WIDE_INT dst_field;
     894              : 
     895              :   /* The offset into the destination buffer.  */
     896              :   HOST_WIDE_INT dst_offset;
     897              : 
     898              :   /* Format argument and format string extracted from it.  */
     899              :   tree format;
     900              :   const char *fmtstr;
     901              : 
     902              :   /* The location of the format argument.  */
     903              :   location_t fmtloc;
     904              : 
     905              :   /* The destination object size for __builtin___xxx_chk functions
     906              :      typically determined by __builtin_object_size, or -1 if unknown.  */
     907              :   unsigned HOST_WIDE_INT objsize;
     908              : 
     909              :   /* Number of the first variable argument.  */
     910              :   unsigned HOST_WIDE_INT argidx;
     911              : 
     912              :   /* True for functions like snprintf that specify the size of
     913              :      the destination, false for others like sprintf that don't.  */
     914              :   bool bounded;
     915              : 
     916              :   /* True for bounded functions like snprintf that specify a zero-size
     917              :      buffer as a request to compute the size of output without actually
     918              :      writing any.  NOWRITE is cleared in response to the %n directive
     919              :      which has side-effects similar to writing output.  */
     920              :   bool nowrite;
     921              : 
     922              :   /* Return true if the called function's return value is used.  */
     923       129308 :   bool retval_used () const
     924              :   {
     925         2227 :     return gimple_get_lhs (callstmt);
     926              :   }
     927              : 
     928              :   /* Return the warning option corresponding to the called function.  */
     929         8313 :   opt_code warnopt () const
     930              :   {
     931         5667 :     return bounded ? OPT_Wformat_truncation_ : OPT_Wformat_overflow_;
     932              :   }
     933              : 
     934              :   /* Return true for calls to file formatted functions.  */
     935              :   bool is_file_func () const
     936              :   {
     937              :     return (fncode == BUILT_IN_FPRINTF
     938              :             || fncode == BUILT_IN_FPRINTF_CHK
     939              :             || fncode == BUILT_IN_FPRINTF_UNLOCKED
     940              :             || fncode == BUILT_IN_VFPRINTF
     941              :             || fncode == BUILT_IN_VFPRINTF_CHK);
     942              :   }
     943              : 
     944              :   /* Return true for calls to string formatted functions.  */
     945         1382 :   bool is_string_func () const
     946              :   {
     947         1382 :     return (fncode == BUILT_IN_SPRINTF
     948         1382 :             || fncode == BUILT_IN_SPRINTF_CHK
     949         1229 :             || fncode == BUILT_IN_SNPRINTF
     950          985 :             || fncode == BUILT_IN_SNPRINTF_CHK
     951          985 :             || fncode == BUILT_IN_VSPRINTF
     952          985 :             || fncode == BUILT_IN_VSPRINTF_CHK
     953          985 :             || fncode == BUILT_IN_VSNPRINTF
     954         2367 :             || fncode == BUILT_IN_VSNPRINTF_CHK);
     955              :   }
     956              : };
     957              : 
     958              : void
     959          783 : directive::set_width (tree arg, range_query *query)
     960              : {
     961          783 :   get_int_range (arg, info->callstmt, width, width + 1, true, 0, query);
     962          783 : }
     963              : 
     964              : void
     965          872 : directive::set_precision (tree arg, range_query *query)
     966              : {
     967          872 :   get_int_range (arg, info->callstmt, prec, prec + 1, false, -1, query);
     968          872 : }
     969              : 
     970              : /* Return the result of formatting a no-op directive (such as '%n').  */
     971              : 
     972              : static fmtresult
     973           77 : format_none (const directive &, tree, pointer_query &)
     974              : {
     975           77 :   fmtresult res (0);
     976           77 :   return res;
     977              : }
     978              : 
     979              : /* Return the result of formatting the '%%' directive.  */
     980              : 
     981              : static fmtresult
     982           88 : format_percent (const directive &, tree, pointer_query &)
     983              : {
     984           88 :   fmtresult res (1);
     985           88 :   return res;
     986              : }
     987              : 
     988              : 
     989              : /* Compute intmax_type_node and uintmax_type_node similarly to how
     990              :    tree.cc builds size_type_node.  */
     991              : 
     992              : static void
     993          122 : build_intmax_type_nodes (tree *pintmax, tree *puintmax)
     994              : {
     995          122 :   if (strcmp (UINTMAX_TYPE, "unsigned int") == 0)
     996              :     {
     997            0 :       *pintmax = integer_type_node;
     998            0 :       *puintmax = unsigned_type_node;
     999              :     }
    1000          122 :   else if (strcmp (UINTMAX_TYPE, "long unsigned int") == 0)
    1001              :     {
    1002          122 :       *pintmax = long_integer_type_node;
    1003          122 :       *puintmax = long_unsigned_type_node;
    1004              :     }
    1005            0 :   else if (strcmp (UINTMAX_TYPE, "long long unsigned int") == 0)
    1006              :     {
    1007            0 :       *pintmax = long_long_integer_type_node;
    1008            0 :       *puintmax = long_long_unsigned_type_node;
    1009              :     }
    1010              :   else
    1011              :     {
    1012            0 :       for (int i = 0; i < NUM_INT_N_ENTS; i++)
    1013            0 :         if (int_n_enabled_p[i])
    1014              :           {
    1015            0 :             char name[50], altname[50];
    1016            0 :             sprintf (name, "__int%d unsigned", int_n_data[i].bitsize);
    1017            0 :             sprintf (altname, "__int%d__ unsigned", int_n_data[i].bitsize);
    1018              : 
    1019            0 :             if (strcmp (name, UINTMAX_TYPE) == 0
    1020            0 :                 || strcmp (altname, UINTMAX_TYPE) == 0)
    1021              :               {
    1022            0 :                 *pintmax = int_n_trees[i].signed_type;
    1023            0 :                 *puintmax = int_n_trees[i].unsigned_type;
    1024            0 :                 return;
    1025              :               }
    1026              :           }
    1027            0 :       gcc_unreachable ();
    1028              :     }
    1029              : }
    1030              : 
    1031              : /* Determine the range [*PMIN, *PMAX] that the expression ARG is
    1032              :    in and that is representable in type int.
    1033              :    Return true when the range is a subrange of that of int.
    1034              :    When ARG is null it is as if it had the full range of int.
    1035              :    When ABSOLUTE is true the range reflects the absolute value of
    1036              :    the argument.  When ABSOLUTE is false, negative bounds of
    1037              :    the determined range are replaced with NEGBOUND.  */
    1038              : 
    1039              : static bool
    1040         2244 : get_int_range (tree arg, gimple *stmt,
    1041              :                HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax,
    1042              :                bool absolute, HOST_WIDE_INT negbound,
    1043              :                range_query *query)
    1044              : {
    1045              :   /* The type of the result.  */
    1046         2244 :   const_tree type = integer_type_node;
    1047              : 
    1048         2244 :   bool knownrange = false;
    1049              : 
    1050         2244 :   if (!arg)
    1051              :     {
    1052          473 :       *pmin = tree_to_shwi (TYPE_MIN_VALUE (type));
    1053          473 :       *pmax = tree_to_shwi (TYPE_MAX_VALUE (type));
    1054              :     }
    1055         1771 :   else if (TREE_CODE (arg) == INTEGER_CST
    1056         1771 :            && TYPE_PRECISION (TREE_TYPE (arg)) <= TYPE_PRECISION (type))
    1057              :     {
    1058              :       /* For a constant argument return its value adjusted as specified
    1059              :          by NEGATIVE and NEGBOUND and return true to indicate that the
    1060              :          result is known.  */
    1061          694 :       *pmin = tree_fits_shwi_p (arg) ? tree_to_shwi (arg) : tree_to_uhwi (arg);
    1062          694 :       *pmax = *pmin;
    1063          694 :       knownrange = true;
    1064              :     }
    1065              :   else
    1066              :     {
    1067              :       /* True if the argument's range cannot be determined.  */
    1068         1077 :       bool unknown = true;
    1069              : 
    1070         1077 :       tree argtype = TREE_TYPE (arg);
    1071              : 
    1072              :       /* Ignore invalid arguments with greater precision that that
    1073              :          of the expected type (e.g., in sprintf("%*i", 12LL, i)).
    1074              :          They will have been detected and diagnosed by -Wformat and
    1075              :          so it's not important to complicate this code to try to deal
    1076              :          with them again.  */
    1077         1077 :       if (TREE_CODE (arg) == SSA_NAME
    1078         1073 :           && INTEGRAL_TYPE_P (argtype)
    1079         2148 :           && TYPE_PRECISION (argtype) <= TYPE_PRECISION (type))
    1080              :         {
    1081              :           /* Try to determine the range of values of the integer argument.  */
    1082         1014 :           int_range_max vr;
    1083         1014 :           query->range_of_expr (vr, arg, stmt);
    1084              : 
    1085         1014 :           if (!vr.undefined_p () && !vr.varying_p ())
    1086              :             {
    1087          615 :               HOST_WIDE_INT type_min
    1088          615 :                 = (TYPE_UNSIGNED (argtype)
    1089          615 :                    ? tree_to_uhwi (TYPE_MIN_VALUE (argtype))
    1090          615 :                    : tree_to_shwi (TYPE_MIN_VALUE (argtype)));
    1091              : 
    1092          615 :               HOST_WIDE_INT type_max = tree_to_uhwi (TYPE_MAX_VALUE (argtype));
    1093              : 
    1094          615 :               tree type = TREE_TYPE (arg);
    1095          615 :               tree tmin = wide_int_to_tree (type, vr.lower_bound ());
    1096          615 :               tree tmax = wide_int_to_tree (type, vr.upper_bound ());
    1097          615 :               *pmin = TREE_INT_CST_LOW (tmin);
    1098          615 :               *pmax = TREE_INT_CST_LOW (tmax);
    1099              : 
    1100          615 :               if (*pmin < *pmax)
    1101              :                 {
    1102              :                   /* Return true if the adjusted range is a subrange of
    1103              :                      the full range of the argument's type.  *PMAX may
    1104              :                      be less than *PMIN when the argument is unsigned
    1105              :                      and its upper bound is in excess of TYPE_MAX.  In
    1106              :                      that (invalid) case disregard the range and use that
    1107              :                      of the expected type instead.  */
    1108          615 :                   knownrange = type_min < *pmin || *pmax < type_max;
    1109              : 
    1110              :                   unknown = false;
    1111              :                 }
    1112              :             }
    1113         1014 :         }
    1114              : 
    1115              :       /* Handle an argument with an unknown range as if none had been
    1116              :          provided.  */
    1117         1014 :       if (unknown)
    1118          462 :         return get_int_range (NULL_TREE, NULL, pmin, pmax, absolute,
    1119          462 :                               negbound, query);
    1120              :     }
    1121              : 
    1122              :   /* Adjust each bound as specified by ABSOLUTE and NEGBOUND.  */
    1123         1782 :   if (absolute)
    1124              :     {
    1125          783 :       if (*pmin < 0)
    1126              :         {
    1127          309 :           if (*pmin == *pmax)
    1128           24 :             *pmin = *pmax = -*pmin;
    1129              :           else
    1130              :             {
    1131              :               /* Make sure signed overlow is avoided.  */
    1132          285 :               gcc_assert (*pmin != HOST_WIDE_INT_MIN);
    1133              : 
    1134          285 :               HOST_WIDE_INT tmp = -*pmin;
    1135          285 :               *pmin = 0;
    1136          285 :               if (*pmax < tmp)
    1137          267 :                 *pmax = tmp;
    1138              :             }
    1139              :         }
    1140              :     }
    1141          999 :   else if (*pmin < negbound)
    1142          426 :     *pmin = negbound;
    1143              : 
    1144              :   return knownrange;
    1145              : }
    1146              : 
    1147              : /* With the range [*ARGMIN, *ARGMAX] of an integer directive's actual
    1148              :    argument, due to the conversion from either *ARGMIN or *ARGMAX to
    1149              :    the type of the directive's formal argument it's possible for both
    1150              :    to result in the same number of bytes or a range of bytes that's
    1151              :    less than the number of bytes that would result from formatting
    1152              :    some other value in the range [*ARGMIN, *ARGMAX].  This can be
    1153              :    determined by checking for the actual argument being in the range
    1154              :    of the type of the directive.  If it isn't it must be assumed to
    1155              :    take on the full range of the directive's type.
    1156              :    Return true when the range has been adjusted to the full range
    1157              :    of DIRTYPE, and false otherwise.  */
    1158              : 
    1159              : static bool
    1160        42268 : adjust_range_for_overflow (tree dirtype, tree *argmin, tree *argmax)
    1161              : {
    1162        42268 :   tree argtype = TREE_TYPE (*argmin);
    1163        42268 :   unsigned argprec = TYPE_PRECISION (argtype);
    1164        42268 :   unsigned dirprec = TYPE_PRECISION (dirtype);
    1165              : 
    1166              :   /* If the actual argument and the directive's argument have the same
    1167              :      precision and sign there can be no overflow and so there is nothing
    1168              :      to adjust.  */
    1169        42268 :   if (argprec == dirprec && TYPE_SIGN (argtype) == TYPE_SIGN (dirtype))
    1170              :     return false;
    1171              : 
    1172              :   /* The logic below was inspired/lifted from the CONVERT_EXPR_CODE_P
    1173              :      branch in the extract_range_from_unary_expr function in tree-vrp.cc.  */
    1174              : 
    1175         4802 :   if (TREE_CODE (*argmin) == INTEGER_CST
    1176         4802 :       && TREE_CODE (*argmax) == INTEGER_CST
    1177         9604 :       && (dirprec >= argprec
    1178         1779 :           || integer_zerop (int_const_binop (RSHIFT_EXPR,
    1179         1779 :                                              int_const_binop (MINUS_EXPR,
    1180              :                                                               *argmax,
    1181              :                                                               *argmin),
    1182         3224 :                                              size_int (dirprec)))))
    1183              :     {
    1184         3357 :       unsigned int maxprec = MAX (argprec, dirprec);
    1185         3357 :       *argmin = force_fit_type (dirtype,
    1186         3357 :                                 wide_int::from (wi::to_wide (*argmin), maxprec,
    1187         3357 :                                                 TYPE_SIGN (argtype)),
    1188              :                                 0, false);
    1189         3357 :       *argmax = force_fit_type (dirtype,
    1190         3357 :                                 wide_int::from (wi::to_wide (*argmax), maxprec,
    1191         3357 :                                                 TYPE_SIGN (argtype)),
    1192              :                                 0, false);
    1193              : 
    1194              :       /* If *ARGMIN is still less than *ARGMAX the conversion above
    1195              :          is safe.  Otherwise, it has overflowed and would be unsafe.  */
    1196         3357 :       if (tree_int_cst_le (*argmin, *argmax))
    1197              :         return false;
    1198              :     }
    1199              : 
    1200         2778 :   *argmin = TYPE_MIN_VALUE (dirtype);
    1201         2778 :   *argmax = TYPE_MAX_VALUE (dirtype);
    1202         2778 :   return true;
    1203              : }
    1204              : 
    1205              : /* Return a range representing the minimum and maximum number of bytes
    1206              :    that the format directive DIR will output for any argument given
    1207              :    the WIDTH and PRECISION (extracted from DIR).  This function is
    1208              :    used when the directive argument or its value isn't known.  */
    1209              : 
    1210              : static fmtresult
    1211       247459 : format_integer (const directive &dir, tree arg, pointer_query &ptr_qry)
    1212              : {
    1213       247459 :   tree intmax_type_node;
    1214       247459 :   tree uintmax_type_node;
    1215              : 
    1216              :   /* Base to format the number in.  */
    1217       247459 :   int base;
    1218              : 
    1219              :   /* True when a conversion is preceded by a prefix indicating the base
    1220              :      of the argument (octal or hexadecimal).  */
    1221       247459 :   const bool maybebase = dir.get_flag ('#');
    1222              : 
    1223              :   /* True when a signed conversion is preceded by a sign or space.  */
    1224       247459 :   bool maybesign = false;
    1225              : 
    1226              :   /* True for signed conversions (i.e., 'd' and 'i').  */
    1227       247459 :   bool sign = false;
    1228              : 
    1229       247459 :   switch (dir.specifier)
    1230              :     {
    1231       230209 :     case 'd':
    1232       230209 :     case 'i':
    1233              :       /* Space and '+' are  only meaningful for signed conversions.  */
    1234       230209 :       maybesign = dir.get_flag (' ') | dir.get_flag ('+');
    1235       230209 :       sign = true;
    1236       230209 :       base = 10;
    1237       230209 :       break;
    1238              :     case 'u':
    1239              :       base = 10;
    1240              :       break;
    1241          240 :     case 'b':
    1242          240 :     case 'B':
    1243          240 :       base = 2;
    1244          240 :       break;
    1245          808 :     case 'o':
    1246          808 :       base = 8;
    1247          808 :       break;
    1248         5354 :     case 'X':
    1249         5354 :     case 'x':
    1250         5354 :       base = 16;
    1251         5354 :       break;
    1252            0 :     default:
    1253            0 :       gcc_unreachable ();
    1254              :     }
    1255              : 
    1256       247459 :   const unsigned adj = (sign | maybebase) + (base == 2 || base == 16);
    1257              : 
    1258              :   /* The type of the "formal" argument expected by the directive.  */
    1259       247459 :   tree dirtype = NULL_TREE;
    1260              : 
    1261              :   /* Determine the expected type of the argument from the length
    1262              :      modifier.  */
    1263       247459 :   switch (dir.modifier)
    1264              :     {
    1265       180832 :     case FMT_LEN_none:
    1266       180832 :       if (dir.specifier == 'p')
    1267              :         dirtype = ptr_type_node;
    1268              :       else
    1269       180832 :         dirtype = sign ? integer_type_node : unsigned_type_node;
    1270              :       break;
    1271              : 
    1272          770 :     case FMT_LEN_h:
    1273          770 :       dirtype = sign ? short_integer_type_node : short_unsigned_type_node;
    1274              :       break;
    1275              : 
    1276         1616 :     case FMT_LEN_hh:
    1277         1616 :       dirtype = sign ? signed_char_type_node : unsigned_char_type_node;
    1278              :       break;
    1279              : 
    1280        56460 :     case FMT_LEN_l:
    1281        56460 :       dirtype = sign ? long_integer_type_node : long_unsigned_type_node;
    1282              :       break;
    1283              : 
    1284         2380 :     case FMT_LEN_L:
    1285         2380 :     case FMT_LEN_ll:
    1286         2380 :       dirtype = (sign
    1287         2380 :                  ? long_long_integer_type_node
    1288              :                  : long_long_unsigned_type_node);
    1289              :       break;
    1290              : 
    1291         5218 :     case FMT_LEN_z:
    1292         5218 :       dirtype = signed_or_unsigned_type_for (!sign, size_type_node);
    1293         5218 :       break;
    1294              : 
    1295           61 :     case FMT_LEN_t:
    1296           61 :       dirtype = signed_or_unsigned_type_for (!sign, ptrdiff_type_node);
    1297           61 :       break;
    1298              : 
    1299          122 :     case FMT_LEN_j:
    1300          122 :       build_intmax_type_nodes (&intmax_type_node, &uintmax_type_node);
    1301          122 :       dirtype = sign ? intmax_type_node : uintmax_type_node;
    1302              :       break;
    1303              : 
    1304            0 :     default:
    1305            0 :       return fmtresult ();
    1306              :     }
    1307              : 
    1308              :   /* The type of the argument to the directive, either deduced from
    1309              :      the actual non-constant argument if one is known, or from
    1310              :      the directive itself when none has been provided because it's
    1311              :      a va_list.  */
    1312       247459 :   tree argtype = NULL_TREE;
    1313              : 
    1314       247459 :   if (!arg)
    1315              :     {
    1316              :       /* When the argument has not been provided, use the type of
    1317              :          the directive's argument as an approximation.  This will
    1318              :          result in false positives for directives like %i with
    1319              :          arguments with smaller precision (such as short or char).  */
    1320              :       argtype = dirtype;
    1321              :     }
    1322       247146 :   else if (TREE_CODE (arg) == INTEGER_CST)
    1323              :     {
    1324              :       /* When a constant argument has been provided use its value
    1325              :          rather than type to determine the length of the output.  */
    1326       205165 :       fmtresult res;
    1327              : 
    1328       205165 :       if ((dir.prec[0] <= 0 && dir.prec[1] >= 0) && integer_zerop (arg))
    1329              :         {
    1330              :           /* As a special case, a precision of zero with a zero argument
    1331              :              results in zero bytes except in base 8 when the '#' flag is
    1332              :              specified, and for signed conversions in base 8 and 10 when
    1333              :              either the space or '+' flag has been specified and it results
    1334              :              in just one byte (with width having the normal effect).  This
    1335              :              must extend to the case of a specified precision with
    1336              :              an unknown value because it can be zero.  */
    1337          219 :           res.range.min = ((base == 8 && dir.get_flag ('#')) || maybesign);
    1338          219 :           if (res.range.min == 0 && dir.prec[0] != dir.prec[1])
    1339              :             {
    1340           96 :               res.range.max = 1;
    1341           96 :               res.range.likely = 1;
    1342              :             }
    1343              :           else
    1344              :             {
    1345          123 :               res.range.max = res.range.min;
    1346          123 :               res.range.likely = res.range.min;
    1347              :             }
    1348              :         }
    1349              :       else
    1350              :         {
    1351              :           /* Convert the argument to the type of the directive.  */
    1352       204946 :           arg = fold_convert (dirtype, arg);
    1353              : 
    1354       204946 :           res.range.min = tree_digits (arg, base, dir.prec[0],
    1355              :                                        maybesign, maybebase);
    1356       204946 :           if (dir.prec[0] == dir.prec[1])
    1357       204768 :             res.range.max = res.range.min;
    1358              :           else
    1359          178 :             res.range.max = tree_digits (arg, base, dir.prec[1],
    1360              :                                          maybesign, maybebase);
    1361       204946 :           res.range.likely = res.range.min;
    1362       204946 :           res.knownrange = true;
    1363              :         }
    1364              : 
    1365       205165 :       res.range.unlikely = res.range.max;
    1366              : 
    1367              :       /* Bump up the counters if WIDTH is greater than LEN.  */
    1368       205165 :       res.adjust_for_width_or_precision (dir.width, dirtype, base, adj);
    1369              :       /* Bump up the counters again if PRECision is greater still.  */
    1370       205165 :       res.adjust_for_width_or_precision (dir.prec, dirtype, base, adj);
    1371              : 
    1372       205165 :       return res;
    1373              :     }
    1374        83952 :   else if (INTEGRAL_TYPE_P (TREE_TYPE (arg))
    1375        42247 :            || POINTER_TYPE_P (TREE_TYPE (arg)))
    1376              :     /* Determine the type of the provided non-constant argument.  */
    1377        41956 :     argtype = TREE_TYPE (arg);
    1378              :   else
    1379              :     /* Don't bother with invalid arguments since they likely would
    1380              :        have already been diagnosed, and disable any further checking
    1381              :        of the format string by returning [-1, -1].  */
    1382           25 :     return fmtresult ();
    1383              : 
    1384        42269 :   fmtresult res;
    1385              : 
    1386              :   /* Using either the range the non-constant argument is in, or its
    1387              :      type (either "formal" or actual), create a range of values that
    1388              :      constrain the length of output given the warning level.  */
    1389        42269 :   tree argmin = NULL_TREE;
    1390        42269 :   tree argmax = NULL_TREE;
    1391              : 
    1392        42269 :   if (arg
    1393        41956 :       && TREE_CODE (arg) == SSA_NAME
    1394        41928 :       && INTEGRAL_TYPE_P (argtype))
    1395              :     {
    1396              :       /* Try to determine the range of values of the integer argument
    1397              :          (range information is not available for pointers).  */
    1398        41715 :       int_range_max vr;
    1399        41715 :       ptr_qry.rvals->range_of_expr (vr, arg, dir.info->callstmt);
    1400              : 
    1401        41715 :       if (!vr.varying_p () && !vr.undefined_p ())
    1402              :         {
    1403        20942 :           argmin = wide_int_to_tree (TREE_TYPE (arg), vr.lower_bound ());
    1404        20942 :           argmax = wide_int_to_tree (TREE_TYPE (arg), vr.upper_bound ());
    1405              : 
    1406              :           /* Set KNOWNRANGE if the argument is in a known subrange
    1407              :              of the directive's type and neither width nor precision
    1408              :              is unknown.  (KNOWNRANGE may be reset below).  */
    1409        20942 :           res.knownrange
    1410        20942 :             = ((!tree_int_cst_equal (TYPE_MIN_VALUE (dirtype), argmin)
    1411         3552 :                 || !tree_int_cst_equal (TYPE_MAX_VALUE (dirtype), argmax))
    1412        22517 :                && dir.known_width_and_precision ());
    1413              : 
    1414        20942 :           res.argmin = argmin;
    1415        20942 :           res.argmax = argmax;
    1416              :         }
    1417              :       else
    1418              :         {
    1419              :           /* The argument here may be the result of promoting the actual
    1420              :              argument to int.  Try to determine the type of the actual
    1421              :              argument before promotion and narrow down its range that
    1422              :              way.  */
    1423        20773 :           gimple *def = SSA_NAME_DEF_STMT (arg);
    1424        20773 :           if (is_gimple_assign (def))
    1425              :             {
    1426        11372 :               tree_code code = gimple_assign_rhs_code (def);
    1427        11372 :               if (code == INTEGER_CST)
    1428              :                 {
    1429            1 :                   arg = gimple_assign_rhs1 (def);
    1430            1 :                   return format_integer (dir, arg, ptr_qry);
    1431              :                 }
    1432              : 
    1433        11371 :               if (code == NOP_EXPR)
    1434              :                 {
    1435          978 :                   tree type = TREE_TYPE (gimple_assign_rhs1 (def));
    1436          978 :                   if (INTEGRAL_TYPE_P (type)
    1437          978 :                       || POINTER_TYPE_P (type))
    1438        41714 :                     argtype = type;
    1439              :                 }
    1440              :             }
    1441              :         }
    1442        41715 :     }
    1443              : 
    1444        42268 :   if (!argmin)
    1445              :     {
    1446        21326 :       if (POINTER_TYPE_P (argtype))
    1447              :         {
    1448          286 :           argmin = build_int_cst (pointer_sized_int_node, 0);
    1449          286 :           argmax = build_all_ones_cst (pointer_sized_int_node);
    1450              :         }
    1451              :       else
    1452              :         {
    1453        21040 :           argmin = TYPE_MIN_VALUE (argtype);
    1454        21040 :           argmax = TYPE_MAX_VALUE (argtype);
    1455              :         }
    1456              :     }
    1457              : 
    1458              :   /* Clear KNOWNRANGE if the range has been adjusted to the maximum
    1459              :      of the directive.  If it has been cleared then since ARGMIN and/or
    1460              :      ARGMAX have been adjusted also adjust the corresponding ARGMIN and
    1461              :      ARGMAX in the result to include in diagnostics.  */
    1462        42268 :   if (adjust_range_for_overflow (dirtype, &argmin, &argmax))
    1463              :     {
    1464         2778 :       res.knownrange = false;
    1465         2778 :       res.argmin = argmin;
    1466         2778 :       res.argmax = argmax;
    1467              :     }
    1468              : 
    1469              :   /* Recursively compute the minimum and maximum from the known range.  */
    1470        42268 :   if (TYPE_UNSIGNED (dirtype) || tree_int_cst_sgn (argmin) >= 0)
    1471              :     {
    1472              :       /* For unsigned conversions/directives or signed when
    1473              :          the minimum is positive, use the minimum and maximum to compute
    1474              :          the shortest and longest output, respectively.  */
    1475        11544 :       res.range.min = format_integer (dir, argmin, ptr_qry).range.min;
    1476        11544 :       res.range.max = format_integer (dir, argmax, ptr_qry).range.max;
    1477              :     }
    1478        30724 :   else if (tree_int_cst_sgn (argmax) < 0)
    1479              :     {
    1480              :       /* For signed conversions/directives if maximum is negative,
    1481              :          use the minimum as the longest output and maximum as the
    1482              :          shortest output.  */
    1483           25 :       res.range.min = format_integer (dir, argmax, ptr_qry).range.min;
    1484           25 :       res.range.max = format_integer (dir, argmin, ptr_qry).range.max;
    1485              :     }
    1486              :   else
    1487              :     {
    1488              :       /* Otherwise, 0 is inside of the range and minimum negative.  Use 0
    1489              :          as the shortest output and for the longest output compute the
    1490              :          length of the output of both minimum and maximum and pick the
    1491              :          longer.  */
    1492        30699 :       unsigned HOST_WIDE_INT max1
    1493        30699 :         = format_integer (dir, argmin, ptr_qry).range.max;
    1494        30699 :       unsigned HOST_WIDE_INT max2
    1495        30699 :         = format_integer (dir, argmax, ptr_qry).range.max;
    1496        30699 :       res.range.min
    1497        30699 :         = format_integer (dir, integer_zero_node, ptr_qry).range.min;
    1498        30699 :       res.range.max = MAX (max1, max2);
    1499              :     }
    1500              : 
    1501              :   /* If the range is known, use the maximum as the likely length.  */
    1502        42268 :   if (res.knownrange)
    1503        18566 :     res.range.likely = res.range.max;
    1504              :   else
    1505              :     {
    1506              :       /* Otherwise, use the minimum.  Except for the case where for %#x or
    1507              :          %#o the minimum is just for a single value in the range (0) and
    1508              :          for all other values it is something longer, like 0x1 or 01.
    1509              :           Use the length for value 1 in that case instead as the likely
    1510              :           length.  */
    1511        23702 :       res.range.likely = res.range.min;
    1512        23702 :       if (maybebase
    1513        23702 :           && base != 10
    1514        23702 :           && (tree_int_cst_sgn (argmin) < 0 || tree_int_cst_sgn (argmax) > 0))
    1515              :         {
    1516          222 :           if (res.range.min == 1)
    1517          308 :             res.range.likely += base == 8 ? 1 : 2;
    1518           36 :           else if (res.range.min == 2
    1519           12 :                    && (base == 16 || base == 2)
    1520            5 :                    && (dir.width[0] == 2 || dir.prec[0] == 2))
    1521            5 :             ++res.range.likely;
    1522              :         }
    1523              :     }
    1524              : 
    1525        42268 :   res.range.unlikely = res.range.max;
    1526        42268 :   res.adjust_for_width_or_precision (dir.width, dirtype, base, adj);
    1527        42268 :   res.adjust_for_width_or_precision (dir.prec, dirtype, base, adj);
    1528              : 
    1529        42268 :   return res;
    1530              : }
    1531              : 
    1532              : /* Return the number of bytes that a format directive consisting of FLAGS,
    1533              :    PRECision, format SPECification, and MPFR rounding specifier RNDSPEC,
    1534              :    would result for argument X under ideal conditions (i.e., if PREC
    1535              :    weren't excessive).  MPFR 3.1 allocates large amounts of memory for
    1536              :    values of PREC with large magnitude and can fail (see MPFR bug #21056).
    1537              :    This function works around those problems.  */
    1538              : 
    1539              : static unsigned HOST_WIDE_INT
    1540         5823 : get_mpfr_format_length (mpfr_ptr x, const char *flags, HOST_WIDE_INT prec,
    1541              :                         char spec, char rndspec)
    1542              : {
    1543         5823 :   char fmtstr[40];
    1544              : 
    1545         5823 :   HOST_WIDE_INT len = strlen (flags);
    1546              : 
    1547         5823 :   fmtstr[0] = '%';
    1548         5823 :   memcpy (fmtstr + 1, flags, len);
    1549         5823 :   memcpy (fmtstr + 1 + len, ".*R", 3);
    1550         5823 :   fmtstr[len + 4] = rndspec;
    1551         5823 :   fmtstr[len + 5] = spec;
    1552         5823 :   fmtstr[len + 6] = '\0';
    1553              : 
    1554         5823 :   spec = TOUPPER (spec);
    1555         5823 :   if (spec == 'E' || spec == 'F')
    1556              :     {
    1557              :       /* For %e, specify the precision explicitly since mpfr_sprintf
    1558              :          does its own thing just to be different (see MPFR bug 21088).  */
    1559         4107 :       if (prec < 0)
    1560         5823 :         prec = 6;
    1561              :     }
    1562              :   else
    1563              :     {
    1564              :       /* Avoid passing negative precisions with larger magnitude to MPFR
    1565              :          to avoid exposing its bugs.  (A negative precision is supposed
    1566              :          to be ignored.)  */
    1567         1716 :       if (prec < 0)
    1568         5823 :         prec = -1;
    1569              :     }
    1570              : 
    1571         5823 :   HOST_WIDE_INT p = prec;
    1572              : 
    1573         5823 :   if (spec == 'G' && !strchr (flags, '#'))
    1574              :     {
    1575              :       /* For G/g without the pound flag, precision gives the maximum number
    1576              :          of significant digits which is bounded by LDBL_MAX_10_EXP, or, for
    1577              :          a 128 bit IEEE extended precision, 4932.  Using twice as much here
    1578              :          should be more than sufficient for any real format.  */
    1579         1475 :       if ((IEEE_MAX_10_EXP * 2) < prec)
    1580           18 :         prec = IEEE_MAX_10_EXP * 2;
    1581              :       p = prec;
    1582              :     }
    1583              :   else
    1584              :     {
    1585              :       /* Cap precision arbitrarily at 1KB and add the difference
    1586              :          (if any) to the MPFR result.  */
    1587         4348 :       if (prec > 1024)
    1588              :         p = 1024;
    1589              :     }
    1590              : 
    1591         5823 :   len = mpfr_snprintf (NULL, 0, fmtstr, (int)p, x);
    1592              : 
    1593              :   /* Handle the unlikely (impossible?) error by returning more than
    1594              :      the maximum dictated by the function's return type.  */
    1595         5823 :   if (len < 0)
    1596            0 :     return target_dir_max () + 1;
    1597              : 
    1598              :   /* Adjust the return value by the difference.  */
    1599         5823 :   if (p < prec)
    1600          158 :     len += prec - p;
    1601              : 
    1602         5823 :   return len;
    1603              : }
    1604              : 
    1605              : /* Return the number of bytes to format using the format specifier
    1606              :    SPEC and the precision PREC the largest value in the real floating
    1607              :    TYPE.  */
    1608              : 
    1609              : static unsigned HOST_WIDE_INT
    1610         4697 : format_floating_max (tree type, char spec, HOST_WIDE_INT prec)
    1611              : {
    1612         4697 :   machine_mode mode = TYPE_MODE (type);
    1613              : 
    1614              :   /* IBM Extended mode.  */
    1615        32879 :   if (MODE_COMPOSITE_P (mode))
    1616            0 :     mode = DFmode;
    1617              : 
    1618              :   /* Get the real type format description for the target.  */
    1619         4697 :   const real_format *rfmt = REAL_MODE_FORMAT (mode);
    1620         4697 :   REAL_VALUE_TYPE rv;
    1621              : 
    1622         4697 :   real_maxval (&rv, 0, mode);
    1623              : 
    1624              :   /* Convert the GCC real value representation with the precision
    1625              :      of the real type to the mpfr_t format with the GCC default
    1626              :      round-to-nearest mode.  */
    1627         4697 :   mpfr_t x;
    1628         4697 :   mpfr_init2 (x, rfmt->p);
    1629         4697 :   mpfr_from_real (x, &rv, MPFR_RNDN);
    1630              : 
    1631              :   /* Return a value one greater to account for the leading minus sign.  */
    1632         4697 :   unsigned HOST_WIDE_INT r
    1633         4697 :     = 1 + get_mpfr_format_length (x, "", prec, spec, 'D');
    1634         4697 :   mpfr_clear (x);
    1635         4697 :   return r;
    1636              : }
    1637              : 
    1638              : /* Return a range representing the minimum and maximum number of bytes
    1639              :    that the directive DIR will output for any argument.  PREC gives
    1640              :    the adjusted precision range to account for negative precisions
    1641              :    meaning the default 6.  This function is used when the directive
    1642              :    argument or its value isn't known.  */
    1643              : 
    1644              : static fmtresult
    1645         4789 : format_floating (const directive &dir, const HOST_WIDE_INT prec[2])
    1646              : {
    1647         4789 :   tree type;
    1648              : 
    1649         4789 :   switch (dir.modifier)
    1650              :     {
    1651         4318 :     case FMT_LEN_l:
    1652         4318 :     case FMT_LEN_none:
    1653         4318 :       type = double_type_node;
    1654         4318 :       break;
    1655              : 
    1656          361 :     case FMT_LEN_L:
    1657          361 :       type = long_double_type_node;
    1658          361 :       break;
    1659              : 
    1660           18 :     case FMT_LEN_ll:
    1661           18 :       type = long_double_type_node;
    1662           18 :       break;
    1663              : 
    1664           92 :     default:
    1665           92 :       return fmtresult ();
    1666              :     }
    1667              : 
    1668              :   /* The minimum and maximum number of bytes produced by the directive.  */
    1669         4697 :   fmtresult res;
    1670              : 
    1671              :   /* The minimum output as determined by flags.  It's always at least 1.
    1672              :      When plus or space are set the output is preceded by either a sign
    1673              :      or a space.  */
    1674         4697 :   unsigned flagmin = (1 /* for the first digit */
    1675         4697 :                       + (dir.get_flag ('+') | dir.get_flag (' ')));
    1676              : 
    1677              :   /* The minimum is 3 for "inf" and "nan" for all specifiers, plus 1
    1678              :      for the plus sign/space with the '+' and ' ' flags, respectively,
    1679              :      unless reduced below.  */
    1680         4697 :   res.range.min = 2 + flagmin;
    1681              : 
    1682              :   /* When the pound flag is set the decimal point is included in output
    1683              :      regardless of precision.  Whether or not a decimal point is included
    1684              :      otherwise depends on the specification and precision.  */
    1685         4697 :   bool radix = dir.get_flag ('#');
    1686              : 
    1687         4697 :   switch (dir.specifier)
    1688              :     {
    1689          115 :     case 'A':
    1690          115 :     case 'a':
    1691          115 :       {
    1692          115 :         HOST_WIDE_INT minprec = 6 + !radix /* decimal point */;
    1693          115 :         if (dir.prec[0] <= 0)
    1694              :           minprec = 0;
    1695           24 :         else if (dir.prec[0] > 0)
    1696           24 :           minprec = dir.prec[0] + !radix /* decimal point */;
    1697              : 
    1698          115 :         res.range.likely = (2 /* 0x */
    1699              :                             + flagmin
    1700          115 :                             + radix
    1701          115 :                             + minprec
    1702          115 :                             + 3 /* p+0 */);
    1703              : 
    1704          115 :         res.range.max = format_floating_max (type, 'a', prec[1]);
    1705              : 
    1706              :         /* The unlikely maximum accounts for the longest multibyte
    1707              :            decimal point character.  */
    1708          115 :         res.range.unlikely = res.range.max;
    1709          115 :         if (dir.prec[1] > 0)
    1710           38 :           res.range.unlikely += target_mb_len_max () - 1;
    1711              : 
    1712              :         break;
    1713              :       }
    1714              : 
    1715          305 :     case 'E':
    1716          305 :     case 'e':
    1717          305 :       {
    1718              :         /* Minimum output attributable to precision and, when it's
    1719              :            non-zero, decimal point.  */
    1720          305 :         HOST_WIDE_INT minprec = prec[0] ? prec[0] + !radix : 0;
    1721              : 
    1722              :         /* The likely minimum output is "[-+]1.234567e+00" regardless
    1723              :            of the value of the actual argument.  */
    1724          305 :         res.range.likely = (flagmin
    1725          305 :                             + radix
    1726          305 :                             + minprec
    1727          305 :                             + 2 /* e+ */ + 2);
    1728              : 
    1729          305 :         res.range.max = format_floating_max (type, 'e', prec[1]);
    1730              : 
    1731              :         /* The unlikely maximum accounts for the longest multibyte
    1732              :            decimal point character.  */
    1733          305 :         if (dir.prec[0] != dir.prec[1]
    1734          255 :             || dir.prec[0] == -1 || dir.prec[0] > 0)
    1735          264 :           res.range.unlikely = res.range.max + target_mb_len_max () -1;
    1736              :         else
    1737           41 :           res.range.unlikely = res.range.max;
    1738              :         break;
    1739              :       }
    1740              : 
    1741         2931 :     case 'F':
    1742         2931 :     case 'f':
    1743         2931 :       {
    1744              :         /* Minimum output attributable to precision and, when it's non-zero,
    1745              :            decimal point.  */
    1746         2931 :         HOST_WIDE_INT minprec = prec[0] ? prec[0] + !radix : 0;
    1747              : 
    1748              :         /* For finite numbers (i.e., not infinity or NaN) the lower bound
    1749              :            when precision isn't specified is 8 bytes ("1.23456" since
    1750              :            precision is taken to be 6).  When precision is zero, the lower
    1751              :            bound is 1 byte (e.g., "1").  Otherwise, when precision is greater
    1752              :            than zero, then the lower bound is 2 plus precision (plus flags).
    1753              :            But in all cases, the lower bound is no greater than 3.  */
    1754         2931 :         unsigned HOST_WIDE_INT min = flagmin + radix + minprec;
    1755         2931 :         if (min < res.range.min)
    1756          162 :           res.range.min = min;
    1757              : 
    1758              :         /* Compute the upper bound for -TYPE_MAX.  */
    1759         2931 :         res.range.max = format_floating_max (type, 'f', prec[1]);
    1760              : 
    1761              :         /* The minimum output with unknown precision is a single byte
    1762              :            (e.g., "0") but the more likely output is 3 bytes ("0.0").  */
    1763         2931 :         if (dir.prec[0] < 0 && dir.prec[1] > 0)
    1764           44 :           res.range.likely = 3;
    1765              :         else
    1766         2887 :           res.range.likely = min;
    1767              : 
    1768              :         /* The unlikely maximum accounts for the longest multibyte
    1769              :            decimal point character.  */
    1770         2931 :         if (dir.prec[0] != dir.prec[1]
    1771         2884 :             || dir.prec[0] == -1 || dir.prec[0] > 0)
    1772         2814 :           res.range.unlikely = res.range.max + target_mb_len_max () - 1;
    1773              :         break;
    1774              :       }
    1775              : 
    1776         1346 :     case 'G':
    1777         1346 :     case 'g':
    1778         1346 :       {
    1779              :         /* The %g output depends on precision and the exponent of
    1780              :            the argument.  Since the value of the argument isn't known
    1781              :            the lower bound on the range of bytes (not counting flags
    1782              :            or width) is 1 plus radix (i.e., either "0" or "0." for
    1783              :            "%g" and "%#g", respectively, with a zero argument).  */
    1784         1346 :         unsigned HOST_WIDE_INT min = flagmin + radix;
    1785         1346 :         if (min < res.range.min)
    1786         1346 :           res.range.min = min;
    1787              : 
    1788         1346 :         char spec = 'g';
    1789         1346 :         HOST_WIDE_INT maxprec = dir.prec[1];
    1790         1346 :         if (radix && maxprec)
    1791              :           {
    1792              :             /* When the pound flag (radix) is set, trailing zeros aren't
    1793              :                trimmed and so the longest output is the same as for %e,
    1794              :                except with precision minus 1 (as specified in C11).  */
    1795           19 :             spec = 'e';
    1796           19 :             if (maxprec > 0)
    1797            8 :               --maxprec;
    1798              :             else if (maxprec < 0)
    1799              :               maxprec = 5;
    1800              :           }
    1801              :         else
    1802         1327 :           maxprec = prec[1];
    1803              : 
    1804         1346 :         res.range.max = format_floating_max (type, spec, maxprec);
    1805              : 
    1806              :         /* The likely output is either the maximum computed above
    1807              :            minus 1 (assuming the maximum is positive) when precision
    1808              :            is known (or unspecified), or the same minimum as for %e
    1809              :            (which is computed for a non-negative argument).  Unlike
    1810              :            for the other specifiers above the likely output isn't
    1811              :            the minimum because for %g that's 1 which is unlikely.  */
    1812         1346 :         if (dir.prec[1] < 0
    1813         1346 :             || (unsigned HOST_WIDE_INT)dir.prec[1] < target_int_max ())
    1814         1332 :           res.range.likely = res.range.max - 1;
    1815              :         else
    1816              :           {
    1817           14 :             HOST_WIDE_INT minprec = 6 + !radix /* decimal point */;
    1818           14 :             res.range.likely = (flagmin
    1819           14 :                                 + radix
    1820           14 :                                 + minprec
    1821           14 :                                 + 2 /* e+ */ + 2);
    1822              :           }
    1823              : 
    1824              :         /* The unlikely maximum accounts for the longest multibyte
    1825              :            decimal point character.  */
    1826         1346 :         res.range.unlikely = res.range.max + target_mb_len_max () - 1;
    1827         1346 :         break;
    1828              :       }
    1829              : 
    1830            0 :     default:
    1831            0 :       return fmtresult ();
    1832              :     }
    1833              : 
    1834              :   /* Bump up the byte counters if WIDTH is greater.  */
    1835         4697 :   res.adjust_for_width_or_precision (dir.width);
    1836         4697 :   return res;
    1837              : }
    1838              : 
    1839              : /* Return a range representing the minimum and maximum number of bytes
    1840              :    that the directive DIR will write on output for the floating argument
    1841              :    ARG.  */
    1842              : 
    1843              : static fmtresult
    1844         5372 : format_floating (const directive &dir, tree arg, pointer_query &)
    1845              : {
    1846         5372 :   HOST_WIDE_INT prec[] = { dir.prec[0], dir.prec[1] };
    1847         5372 :   tree type = (dir.modifier == FMT_LEN_L || dir.modifier == FMT_LEN_ll
    1848         5372 :                ? long_double_type_node : double_type_node);
    1849              : 
    1850              :   /* For an indeterminate precision the lower bound must be assumed
    1851              :      to be zero.  */
    1852         5372 :   if (TOUPPER (dir.specifier) == 'A')
    1853              :     {
    1854              :       /* Get the number of fractional decimal digits needed to represent
    1855              :          the argument without a loss of accuracy.  */
    1856          195 :       unsigned fmtprec
    1857          195 :         = REAL_MODE_FORMAT (TYPE_MODE (type))->p;
    1858              : 
    1859              :       /* The precision of the IEEE 754 double format is 53.
    1860              :          The precision of all other GCC binary double formats
    1861              :          is 56 or less.  */
    1862          195 :       unsigned maxprec = fmtprec <= 56 ? 13 : 15;
    1863              : 
    1864              :       /* For %a, leave the minimum precision unspecified to let
    1865              :          MFPR trim trailing zeros (as it and many other systems
    1866              :          including Glibc happen to do) and set the maximum
    1867              :          precision to reflect what it would be with trailing zeros
    1868              :          present (as Solaris and derived systems do).  */
    1869          195 :       if (dir.prec[1] < 0)
    1870              :         {
    1871              :           /* Both bounds are negative implies that precision has
    1872              :              not been specified.  */
    1873           98 :           prec[0] = maxprec;
    1874           98 :           prec[1] = -1;
    1875              :         }
    1876           97 :       else if (dir.prec[0] < 0)
    1877              :         {
    1878              :           /* With a negative lower bound and a non-negative upper
    1879              :              bound set the minimum precision to zero and the maximum
    1880              :              to the greater of the maximum precision (i.e., with
    1881              :              trailing zeros present) and the specified upper bound.  */
    1882           21 :           prec[0] = 0;
    1883           21 :           prec[1] = dir.prec[1] < maxprec ? maxprec : dir.prec[1];
    1884              :         }
    1885              :     }
    1886         5177 :   else if (dir.prec[0] < 0)
    1887              :     {
    1888         4674 :       if (dir.prec[1] < 0)
    1889              :         {
    1890              :           /* A precision in a strictly negative range is ignored and
    1891              :              the default of 6 is used instead.  */
    1892         4541 :           prec[0] = prec[1] = 6;
    1893              :         }
    1894              :       else
    1895              :         {
    1896              :           /* For a precision in a partly negative range, the lower bound
    1897              :              must be assumed to be zero and the new upper bound is the
    1898              :              greater of 6 (the default precision used when the specified
    1899              :              precision is negative) and the upper bound of the specified
    1900              :              range.  */
    1901          133 :           prec[0] = 0;
    1902          133 :           prec[1] = dir.prec[1] < 6 ? 6 : dir.prec[1];
    1903              :         }
    1904              :     }
    1905              : 
    1906         5372 :   if (!arg
    1907         5273 :       || TREE_CODE (arg) != REAL_CST
    1908         5956 :       || !useless_type_conversion_p (type, TREE_TYPE (arg)))
    1909         4789 :     return format_floating (dir, prec);
    1910              : 
    1911              :   /* The minimum and maximum number of bytes produced by the directive.  */
    1912          583 :   fmtresult res;
    1913              : 
    1914              :   /* Get the real type format description for the target.  */
    1915          583 :   const REAL_VALUE_TYPE *rvp = TREE_REAL_CST_PTR (arg);
    1916          583 :   const real_format *rfmt = REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg)));
    1917              : 
    1918          583 :   if (!real_isfinite (rvp))
    1919              :     {
    1920              :       /* The format for Infinity and NaN is "[-]inf"/"[-]infinity"
    1921              :          and "[-]nan" with the choice being implementation-defined
    1922              :          but not locale dependent.  */
    1923           20 :       bool sign = dir.get_flag ('+') || real_isneg (rvp);
    1924           20 :       res.range.min = 3 + sign;
    1925              : 
    1926           20 :       res.range.likely = res.range.min;
    1927           20 :       res.range.max = res.range.min;
    1928              :       /* The unlikely maximum is "[-/+]infinity" or "[-/+][qs]nan".
    1929              :          For NaN, the C/POSIX standards specify two formats:
    1930              :            "[-/+]nan"
    1931              :          and
    1932              :            "[-/+]nan(n-char-sequence)"
    1933              :          No known printf implementation outputs the latter format but AIX
    1934              :          outputs QNaN and SNaN for quiet and signalling NaN, respectively,
    1935              :          so the unlikely maximum reflects that.  */
    1936           20 :       res.range.unlikely = sign + (real_isinf (rvp) ? 8 : 4);
    1937              : 
    1938              :       /* The range for infinity and NaN is known unless either width
    1939              :          or precision is unknown.  Width has the same effect regardless
    1940              :          of whether the argument is finite.  Precision is either ignored
    1941              :          (e.g., Glibc) or can have an effect on the short vs long format
    1942              :          such as inf/infinity (e.g., Solaris).  */
    1943           20 :       res.knownrange = dir.known_width_and_precision ();
    1944              : 
    1945              :       /* Adjust the range for width but ignore precision.  */
    1946           20 :       res.adjust_for_width_or_precision (dir.width);
    1947              : 
    1948           20 :       return res;
    1949              :     }
    1950              : 
    1951              :   char fmtstr [40];
    1952              :   char *pfmt = fmtstr;
    1953              : 
    1954              :   /* Append flags.  */
    1955         3378 :   for (const char *pf = "-+ #0"; *pf; ++pf)
    1956         2815 :     if (dir.get_flag (*pf))
    1957           12 :       *pfmt++ = *pf;
    1958              : 
    1959          563 :   *pfmt = '\0';
    1960              : 
    1961          563 :   {
    1962              :     /* Set up an array to easily iterate over.  */
    1963          563 :     unsigned HOST_WIDE_INT* const minmax[] = {
    1964              :       &res.range.min, &res.range.max
    1965          563 :     };
    1966              : 
    1967         1689 :     for (int i = 0; i != ARRAY_SIZE (minmax); ++i)
    1968              :       {
    1969              :         /* Convert the GCC real value representation with the precision
    1970              :            of the real type to the mpfr_t format rounding down in the
    1971              :            first iteration that computes the minimum and up in the second
    1972              :            that computes the maximum.  This order is arbitrary because
    1973              :            rounding in either direction can result in longer output.  */
    1974         1126 :         mpfr_t mpfrval;
    1975         1126 :         mpfr_init2 (mpfrval, rfmt->p);
    1976         1689 :         mpfr_from_real (mpfrval, rvp, i ? MPFR_RNDU : MPFR_RNDD);
    1977              : 
    1978              :         /* Use the MPFR rounding specifier to round down in the first
    1979              :            iteration and then up.  In most but not all cases this will
    1980              :            result in the same number of bytes.  */
    1981         1126 :         char rndspec = "DU"[i];
    1982              : 
    1983              :         /* Format it and store the result in the corresponding member
    1984              :            of the result struct.  */
    1985         2252 :         *minmax[i] = get_mpfr_format_length (mpfrval, fmtstr, prec[i],
    1986         1126 :                                              dir.specifier, rndspec);
    1987         1126 :         mpfr_clear (mpfrval);
    1988              :       }
    1989              :   }
    1990              : 
    1991              :   /* Make sure the minimum is less than the maximum (MPFR rounding
    1992              :      in the call to mpfr_snprintf can result in the reverse.  */
    1993          563 :   if (res.range.max < res.range.min)
    1994              :     {
    1995           30 :       unsigned HOST_WIDE_INT tmp = res.range.min;
    1996           30 :       res.range.min = res.range.max;
    1997           30 :       res.range.max = tmp;
    1998              :     }
    1999              : 
    2000              :   /* The range is known unless either width or precision is unknown.  */
    2001          563 :   res.knownrange = dir.known_width_and_precision ();
    2002              : 
    2003              :   /* For the same floating point constant, unless width or precision
    2004              :      is unknown, use the longer output as the likely maximum since
    2005              :      with round to nearest either is equally likely.  Otherwise, when
    2006              :      precision is unknown, use the greater of the minimum and 3 as
    2007              :      the likely output (for "0.0" since zero precision is unlikely).  */
    2008          563 :   if (res.knownrange)
    2009          521 :     res.range.likely = res.range.max;
    2010           42 :   else if (res.range.min < 3
    2011           17 :            && dir.prec[0] < 0
    2012           57 :            && (unsigned HOST_WIDE_INT)dir.prec[1] == target_int_max ())
    2013           13 :     res.range.likely = 3;
    2014              :   else
    2015           29 :     res.range.likely = res.range.min;
    2016              : 
    2017          563 :   res.range.unlikely = res.range.max;
    2018              : 
    2019          563 :   if (res.range.max > 2 && (prec[0] != 0 || prec[1] != 0))
    2020              :     {
    2021              :       /* Unless the precision is zero output longer than 2 bytes may
    2022              :          include the decimal point which must be a single character
    2023              :          up to MB_LEN_MAX in length.  This is overly conservative
    2024              :          since in some conversions some constants result in no decimal
    2025              :          point (e.g., in %g).  */
    2026          512 :       res.range.unlikely += target_mb_len_max () - 1;
    2027              :     }
    2028              : 
    2029          563 :   res.adjust_for_width_or_precision (dir.width);
    2030          563 :   return res;
    2031              : }
    2032              : 
    2033              : /* Return a FMTRESULT struct set to the lengths of the shortest and longest
    2034              :    strings referenced by the expression STR, or (-1, -1) when not known.
    2035              :    Used by the format_string function below.  */
    2036              : 
    2037              : static fmtresult
    2038       268332 : get_string_length (tree str, gimple *stmt, unsigned HOST_WIDE_INT max_size,
    2039              :                    unsigned eltsize, pointer_query &ptr_qry)
    2040              : {
    2041       268332 :   if (!str)
    2042          578 :     return fmtresult ();
    2043              : 
    2044              :   /* Try to determine the dynamic string length first.
    2045              :      Set MAXBOUND to an arbitrary non-null non-integer node as a request
    2046              :      to have it set to the length of the longest string in a PHI.  */
    2047       267754 :   c_strlen_data lendata = { };
    2048       267754 :   lendata.maxbound = str;
    2049       267754 :   if (eltsize == 1)
    2050       267454 :     get_range_strlen_dynamic (str, stmt, &lendata, ptr_qry);
    2051              :   else
    2052              :     {
    2053              :       /* Determine the length of the shortest and longest string referenced
    2054              :          by STR.  Strings of unknown lengths are bounded by the sizes of
    2055              :          arrays that subexpressions of STR may refer to.  Pointers that
    2056              :          aren't known to point any such arrays result in LENDATA.MAXLEN
    2057              :          set to SIZE_MAX.  */
    2058          300 :       get_range_strlen (str, &lendata, eltsize);
    2059              :     }
    2060              : 
    2061              :   /* If LENDATA.MAXBOUND is not equal to .MINLEN it corresponds to the bound
    2062              :      of the largest array STR refers to, if known, or it's set to SIZE_MAX
    2063              :      otherwise.  */
    2064              : 
    2065              :   /* Return the default result when nothing is known about the string.  */
    2066       267754 :   if ((lendata.maxbound && !tree_fits_uhwi_p (lendata.maxbound))
    2067       267754 :       || !tree_fits_uhwi_p (lendata.maxlen))
    2068              :     {
    2069            0 :       fmtresult res;
    2070            0 :       res.nonstr = lendata.decl;
    2071            0 :       return res;
    2072              :     }
    2073              : 
    2074       267754 :   unsigned HOST_WIDE_INT lenmax = tree_to_uhwi (max_object_size ()) - 2;
    2075       267754 :   if (integer_zerop (lendata.minlen)
    2076        18737 :       && (!lendata.maxbound || lenmax <= tree_to_uhwi (lendata.maxbound))
    2077       280160 :       && lenmax <= tree_to_uhwi (lendata.maxlen))
    2078              :     {
    2079        12400 :       if (max_size > 0 && max_size < HOST_WIDE_INT_MAX)
    2080              :         {
    2081              :           /* Adjust the conservative unknown/unbounded result if MAX_SIZE
    2082              :              is valid.  Set UNLIKELY to maximum in case MAX_SIZE refers
    2083              :              to a subobject.
    2084              :              TODO: This is overly conservative.  Set UNLIKELY to the size
    2085              :              of the outermost enclosing declared object.  */
    2086           34 :           fmtresult res (0, max_size - 1);
    2087           34 :           res.nonstr = lendata.decl;
    2088           34 :           res.range.likely = res.range.max;
    2089           34 :           res.range.unlikely = HOST_WIDE_INT_MAX;
    2090           34 :           return res;
    2091              :         }
    2092              : 
    2093        12366 :       fmtresult res;
    2094        12366 :       res.nonstr = lendata.decl;
    2095        12366 :       return res;
    2096              :     }
    2097              : 
    2098              :   /* The minimum length of the string.  */
    2099       510708 :   HOST_WIDE_INT min
    2100       255354 :     = (tree_fits_uhwi_p (lendata.minlen)
    2101       255354 :        ? tree_to_uhwi (lendata.minlen)
    2102              :        : 0);
    2103              : 
    2104              :   /* The maximum length of the string; initially set to MAXBOUND which
    2105              :      may be less than MAXLEN, but may be adjusted up below.  */
    2106       510697 :   HOST_WIDE_INT max
    2107       255343 :     = (lendata.maxbound && tree_fits_uhwi_p (lendata.maxbound)
    2108       510697 :        ? tree_to_uhwi (lendata.maxbound)
    2109              :        : HOST_WIDE_INT_M1U);
    2110              : 
    2111              :   /* True if either the maximum length is unknown or (conservatively)
    2112              :      the array bound is less than the maximum length.  That can happen
    2113              :      when the length of the string is unknown but the array in which
    2114              :      the string is stored is a member of a struct.  The warning uses
    2115              :      the size of the member as the upper bound but the optimization
    2116              :      doesn't.  The optimization could still use the size of
    2117              :      enclosing object as the upper bound but that's not done here.  */
    2118       255354 :   const bool unbounded
    2119       255354 :     = (integer_all_onesp (lendata.maxlen)
    2120       255354 :        || (lendata.maxbound
    2121       254349 :            && tree_int_cst_lt (lendata.maxbound, lendata.maxlen)));
    2122              : 
    2123              :   /* Set the max/likely counters to unbounded when a minimum is known
    2124              :      but the maximum length isn't bounded.  This implies that STR is
    2125              :      a conditional expression involving a string of known length and
    2126              :      an expression of unknown/unbounded length.  */
    2127       255354 :   if (min
    2128       255354 :       && (unsigned HOST_WIDE_INT)min < HOST_WIDE_INT_M1U
    2129       249017 :       && unbounded)
    2130       255354 :     max = HOST_WIDE_INT_M1U;
    2131              : 
    2132              :   /* get_range_strlen() returns the target value of SIZE_MAX for
    2133              :      strings of unknown length.  Bump it up to HOST_WIDE_INT_M1U
    2134              :      which may be bigger.  */
    2135       255354 :   if ((unsigned HOST_WIDE_INT)min == target_size_max ())
    2136            0 :     min = HOST_WIDE_INT_M1U;
    2137       255354 :   if ((unsigned HOST_WIDE_INT)max == target_size_max ())
    2138          155 :     max = HOST_WIDE_INT_M1U;
    2139              : 
    2140       255354 :   fmtresult res (min, max);
    2141       255354 :   res.nonstr = lendata.decl;
    2142              : 
    2143              :   /* Set RES.KNOWNRANGE to true if and only if all strings referenced
    2144              :      by STR are known to be bounded (though not necessarily by their
    2145              :      actual length but perhaps by their maximum possible length).  */
    2146       255354 :   if (res.range.max < target_int_max ())
    2147              :     {
    2148              :       res.knownrange = true;
    2149              :       /* When the length of the longest string is known and not
    2150              :          excessive use it as the likely length of the string(s).  */
    2151              :       res.range.likely = res.range.max;
    2152              :     }
    2153              :   else
    2154              :     {
    2155              :       /* When the upper bound is unknown (it can be zero or excessive)
    2156              :          set the likely length to the greater of 1.  If MAXBOUND is
    2157              :          known, also reset the length of the lower bound to zero.  */
    2158          184 :       res.range.likely = res.range.min ? res.range.min : warn_level > 1;
    2159          184 :       if (lendata.maxbound && !integer_all_onesp (lendata.maxbound))
    2160              :         res.range.min = 0;
    2161              :     }
    2162              : 
    2163       255354 :   res.range.unlikely = unbounded ? HOST_WIDE_INT_MAX : res.range.max;
    2164              : 
    2165       255354 :   return res;
    2166              : }
    2167              : 
    2168              : /* Return the minimum and maximum number of characters formatted
    2169              :    by the '%c' format directives and its wide character form for
    2170              :    the argument ARG.  ARG can be null (for functions such as
    2171              :    vsprinf).  */
    2172              : 
    2173              : static fmtresult
    2174         1045 : format_character (const directive &dir, tree arg, pointer_query &ptr_qry)
    2175              : {
    2176         1045 :   fmtresult res;
    2177              : 
    2178         1045 :   res.knownrange = true;
    2179              : 
    2180         1045 :   if (dir.specifier == 'C' || dir.modifier == FMT_LEN_l)
    2181              :     {
    2182              :       /* A wide character can result in as few as zero bytes.  */
    2183          127 :       res.range.min = 0;
    2184              : 
    2185          127 :       HOST_WIDE_INT min, max;
    2186          127 :       if (get_int_range (arg, dir.info->callstmt, &min, &max, false, 0,
    2187              :                          ptr_qry.rvals))
    2188              :         {
    2189           66 :           if (min == 0 && max == 0)
    2190              :             {
    2191              :               /* In strict reading of older ISO C or POSIX, this required
    2192              :                  no characters to be emitted.  ISO C23 changes that, so
    2193              :                  does POSIX, to match what has been implemented in most of the
    2194              :                  implementations, namely emitting a single NUL character.
    2195              :                  Let's use 0 for minimum and 1 for all the other values.  */
    2196           23 :               res.range.max = 1;
    2197           23 :               res.range.likely = res.range.unlikely = 1;
    2198              :             }
    2199           43 :           else if (min >= 0 && min < 128)
    2200              :             {
    2201              :               /* Be conservative if the target execution character set
    2202              :                  is not a 1-to-1 mapping to the source character set or
    2203              :                  if the source set is not ASCII.  */
    2204           36 :               bool one_2_one_ascii
    2205           36 :                 = (target_to_host_charmap[0] == 1
    2206           36 :                    && target_to_host ('a') == 97);
    2207              : 
    2208              :               /* A wide character in the ASCII range most likely results
    2209              :                  in a single byte, and only unlikely in up to MB_LEN_MAX.  */
    2210           36 :               res.range.max = one_2_one_ascii ? 1 : target_mb_len_max ();
    2211           36 :               res.range.likely = 1;
    2212           36 :               res.range.unlikely = target_mb_len_max ();
    2213           36 :               res.mayfail = !one_2_one_ascii;
    2214              :             }
    2215              :           else
    2216              :             {
    2217              :               /* A wide character outside the ASCII range likely results
    2218              :                  in up to two bytes, and only unlikely in up to MB_LEN_MAX.  */
    2219            7 :               res.range.max = target_mb_len_max ();
    2220            7 :               res.range.likely = 2;
    2221            7 :               res.range.unlikely = res.range.max;
    2222              :               /* Converting such a character may fail.  */
    2223            7 :               res.mayfail = true;
    2224              :             }
    2225              :         }
    2226              :       else
    2227              :         {
    2228              :           /* An unknown wide character is treated the same as a wide
    2229              :              character outside the ASCII range.  */
    2230           61 :           res.range.max = target_mb_len_max ();
    2231           61 :           res.range.likely = 2;
    2232           61 :           res.range.unlikely = res.range.max;
    2233           61 :           res.mayfail = true;
    2234              :         }
    2235          127 :     }
    2236              :   else
    2237              :     {
    2238              :       /* A plain '%c' directive.  Its output is exactly 1.  */
    2239          918 :       res.range.min = res.range.max = 1;
    2240          918 :       res.range.likely = res.range.unlikely = 1;
    2241              :     }
    2242              : 
    2243              :   /* Bump up the byte counters if WIDTH is greater.  */
    2244         1045 :   return res.adjust_for_width_or_precision (dir.width);
    2245              : }
    2246              : 
    2247              : /* If TYPE is an array or struct or union, increment *FLDOFF by the starting
    2248              :    offset of the member that *OFF points into if one can be determined and
    2249              :    set *FLDSIZE to its size in bytes and decrement *OFF by the same.
    2250              :    Otherwise do nothing.  */
    2251              : 
    2252              : static void
    2253         3784 : set_aggregate_size_and_offset (tree type, HOST_WIDE_INT *fldoff,
    2254              :                                HOST_WIDE_INT *fldsize, HOST_WIDE_INT *off)
    2255              : {
    2256              :   /* The byte offset of the most basic struct member the byte
    2257              :      offset *OFF corresponds to, or for a (multidimensional)
    2258              :      array member, the byte offset of the array element.  */
    2259         3784 :   if (TREE_CODE (type) == ARRAY_TYPE
    2260         3784 :       && TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
    2261              :     {
    2262           32 :       HOST_WIDE_INT index = 0, arrsize = 0;
    2263           32 :       if (array_elt_at_offset (type, *off, &index, &arrsize))
    2264              :         {
    2265           16 :           *fldoff += index;
    2266           16 :           *fldsize = arrsize;
    2267              :         }
    2268              :       /* Otherwise leave *FLDOFF et al. unchanged.  */
    2269              :     }
    2270         3752 :   else if (RECORD_OR_UNION_TYPE_P (type))
    2271              :     {
    2272          547 :       HOST_WIDE_INT index = 0;
    2273          547 :       tree sub = field_at_offset (type, NULL_TREE, *off, &index);
    2274          547 :       if (sub)
    2275              :         {
    2276          533 :           tree subsize = DECL_SIZE_UNIT (sub);
    2277          533 :           if (*fldsize < HOST_WIDE_INT_MAX
    2278          533 :               && subsize
    2279          524 :               && tree_fits_uhwi_p (subsize))
    2280          524 :             *fldsize = tree_to_uhwi (subsize);
    2281              :           else
    2282            9 :             *fldsize = HOST_WIDE_INT_MAX;
    2283          533 :           *fldoff += index;
    2284          533 :           *off -= index;
    2285              :         }
    2286              :       /* Otherwise leave *FLDOFF et al. unchanged.  */
    2287              :     }
    2288         3784 : }
    2289              : 
    2290              : /* For an expression X of pointer type, recursively try to find its origin
    2291              :    (either object DECL or pointer such as PARM_DECL) Y and return such a Y.
    2292              :    When X refers to an array element or struct member, set *FLDOFF to
    2293              :    the offset of the element or member from the beginning of the "most
    2294              :    derived" object and *FLDSIZE to its size.  When nonnull, set *OFF to
    2295              :    the overall offset from the beginning of the object so that
    2296              :    *FLDOFF <= *OFF.  */
    2297              : 
    2298              : static tree
    2299        24392 : get_origin_and_offset_r (tree x, HOST_WIDE_INT *fldoff, HOST_WIDE_INT *fldsize,
    2300              :                          HOST_WIDE_INT *off)
    2301              : {
    2302        24392 :   HOST_WIDE_INT sizebuf = -1;
    2303        24392 :   if (!fldsize)
    2304         2053 :     fldsize = &sizebuf;
    2305              : 
    2306        24392 :   if (DECL_P (x))
    2307              :     {
    2308              :       /* Set the size if it hasn't been set yet.  */
    2309         5985 :       if (tree size = DECL_SIZE_UNIT (x))
    2310         4780 :         if (*fldsize < 0 && tree_fits_shwi_p (size))
    2311         4727 :           *fldsize = tree_to_shwi (size);
    2312         5985 :       return x;
    2313              :     }
    2314              : 
    2315        18407 :   switch (TREE_CODE (x))
    2316              :     {
    2317         6084 :     case ADDR_EXPR:
    2318         6084 :       x = TREE_OPERAND (x, 0);
    2319         6084 :       return get_origin_and_offset_r (x, fldoff, fldsize, off);
    2320              : 
    2321         4632 :     case ARRAY_REF:
    2322         4632 :       {
    2323         4632 :         tree sub = TREE_OPERAND (x, 1);
    2324         4632 :         unsigned HOST_WIDE_INT idx =
    2325         4632 :           tree_fits_uhwi_p (sub) ? tree_to_uhwi (sub) : HOST_WIDE_INT_MAX;
    2326              : 
    2327         4632 :         tree elsz = array_ref_element_size (x);
    2328         9264 :         unsigned HOST_WIDE_INT elbytes =
    2329         4632 :           tree_fits_shwi_p (elsz) ? tree_to_shwi (elsz) : HOST_WIDE_INT_MAX;
    2330              : 
    2331         4632 :         unsigned HOST_WIDE_INT byteoff = idx * elbytes;
    2332              : 
    2333         4632 :         if (byteoff < HOST_WIDE_INT_MAX
    2334         4632 :             && elbytes < HOST_WIDE_INT_MAX
    2335         4632 :             && (elbytes == 0 || byteoff / elbytes == idx))
    2336              :           {
    2337              :             /* For in-bounds constant offsets into constant-sized arrays
    2338              :                bump up *OFF, and for what's likely arrays or structs of
    2339              :                arrays, also *FLDOFF, as necessary.  */
    2340         4632 :             if (off)
    2341         4632 :               *off += byteoff;
    2342         4632 :             if (elbytes > 1)
    2343         4580 :               *fldoff += byteoff;
    2344              :           }
    2345              :         else
    2346            0 :           *fldoff = HOST_WIDE_INT_MAX;
    2347              : 
    2348         4632 :         x = TREE_OPERAND (x, 0);
    2349         4632 :         return get_origin_and_offset_r (x, fldoff, fldsize, off);
    2350              :       }
    2351              : 
    2352         1494 :     case MEM_REF:
    2353         1494 :       if (off)
    2354              :         {
    2355         1494 :           tree offset = TREE_OPERAND (x, 1);
    2356         1494 :           *off = (tree_fits_uhwi_p (offset)
    2357         1494 :                   ? tree_to_uhwi (offset) : HOST_WIDE_INT_MAX);
    2358              :         }
    2359              : 
    2360         1494 :       x = TREE_OPERAND (x, 0);
    2361              : 
    2362         1494 :       if (off)
    2363              :         {
    2364         1494 :           tree xtype
    2365         1494 :             = (TREE_CODE (x) == ADDR_EXPR
    2366         1494 :                ? TREE_TYPE (TREE_OPERAND (x, 0)) : TREE_TYPE (TREE_TYPE (x)));
    2367              : 
    2368         1494 :           set_aggregate_size_and_offset (xtype, fldoff, fldsize, off);
    2369              :         }
    2370              : 
    2371         1494 :       return get_origin_and_offset_r (x, fldoff, fldsize, nullptr);
    2372              : 
    2373         2053 :     case COMPONENT_REF:
    2374         2053 :       {
    2375         2053 :         tree foff = component_ref_field_offset (x);
    2376         2053 :         tree fld = TREE_OPERAND (x, 1);
    2377         2053 :         if (!tree_fits_shwi_p (foff)
    2378         4106 :             || !tree_fits_shwi_p (DECL_FIELD_BIT_OFFSET (fld)))
    2379              :           return x;
    2380         2053 :         *fldoff += (tree_to_shwi (foff)
    2381         2053 :                     + (tree_to_shwi (DECL_FIELD_BIT_OFFSET (fld))
    2382         2053 :                        / BITS_PER_UNIT));
    2383              : 
    2384         2053 :         get_origin_and_offset_r (fld, fldoff, fldsize, off);
    2385         2053 :         x = TREE_OPERAND (x, 0);
    2386         2053 :         return get_origin_and_offset_r (x, fldoff, nullptr, off);
    2387              :       }
    2388              : 
    2389         3198 :     case SSA_NAME:
    2390         3198 :       {
    2391         3198 :         gimple *def = SSA_NAME_DEF_STMT (x);
    2392         3198 :         if (is_gimple_assign (def))
    2393              :           {
    2394         1532 :             tree_code code = gimple_assign_rhs_code (def);
    2395         1532 :             if (code == ADDR_EXPR)
    2396              :               {
    2397          419 :                 x = gimple_assign_rhs1 (def);
    2398          419 :                 return get_origin_and_offset_r (x, fldoff, fldsize, off);
    2399              :               }
    2400              : 
    2401         1113 :             if (code == POINTER_PLUS_EXPR)
    2402              :               {
    2403          374 :                 tree offset = gimple_assign_rhs2 (def);
    2404          374 :                 if (off && tree_fits_uhwi_p (offset))
    2405          163 :                   *off = tree_to_uhwi (offset);
    2406              : 
    2407          374 :                 x = gimple_assign_rhs1 (def);
    2408          374 :                 x = get_origin_and_offset_r (x, fldoff, fldsize, off);
    2409          374 :                 if (off && !tree_fits_uhwi_p (offset))
    2410          208 :                   *off = HOST_WIDE_INT_MAX;
    2411          208 :                 if (off)
    2412              :                   {
    2413          371 :                     tree xtype = TREE_TYPE (x);
    2414          371 :                     set_aggregate_size_and_offset (xtype, fldoff, fldsize, off);
    2415              :                   }
    2416          374 :                 return x;
    2417              :               }
    2418          739 :             else if (code == VAR_DECL)
    2419              :               {
    2420           86 :                 x = gimple_assign_rhs1 (def);
    2421           86 :                 return get_origin_and_offset_r (x, fldoff, fldsize, off);
    2422              :               }
    2423              :           }
    2424         1666 :         else if (gimple_nop_p (def) && SSA_NAME_VAR (x))
    2425              :           x = SSA_NAME_VAR (x);
    2426              : 
    2427         2319 :         tree xtype = TREE_TYPE (x);
    2428         2319 :         if (POINTER_TYPE_P (xtype))
    2429         2305 :           xtype = TREE_TYPE (xtype);
    2430              : 
    2431         2319 :         if (off)
    2432         1919 :           set_aggregate_size_and_offset (xtype, fldoff, fldsize, off);
    2433              :       }
    2434              : 
    2435              :     default:
    2436              :       break;
    2437              :     }
    2438              : 
    2439              :   return x;
    2440              : }
    2441              : 
    2442              : /* Nonrecursive version of the above.
    2443              :    The function never returns null unless X is null to begin with.  */
    2444              : 
    2445              : static tree
    2446        37544 : get_origin_and_offset (tree x, HOST_WIDE_INT *fldoff, HOST_WIDE_INT *off,
    2447              :                        HOST_WIDE_INT *fldsize = nullptr)
    2448              : {
    2449        37544 :   if (!x)
    2450              :     return NULL_TREE;
    2451              : 
    2452         7197 :   HOST_WIDE_INT sizebuf;
    2453         7197 :   if (!fldsize)
    2454         3994 :     fldsize = &sizebuf;
    2455              : 
    2456              :   /* Invalidate *FLDSIZE.  */
    2457         7197 :   *fldsize = -1;
    2458         7197 :   *fldoff = *off = 0;
    2459              : 
    2460         7197 :   return get_origin_and_offset_r (x, fldoff, fldsize, off);
    2461              : }
    2462              : 
    2463              : /* If ARG refers to the same (sub)object or array element as described
    2464              :    by DST and DST_FLD, return the byte offset into the struct member or
    2465              :    array element referenced by ARG and set *ARG_SIZE to the size of
    2466              :    the (sub)object.  Otherwise return HOST_WIDE_INT_MIN to indicate
    2467              :    that ARG and DST do not refer to the same object.  */
    2468              : 
    2469              : static HOST_WIDE_INT
    2470        18994 : alias_offset (tree arg, HOST_WIDE_INT *arg_size,
    2471              :               tree dst, HOST_WIDE_INT dst_fld)
    2472              : {
    2473              :   /* See if the argument refers to the same base object as the destination
    2474              :      of the formatted function call, and if so, try to determine if they
    2475              :      can alias.  */
    2476        18994 :   if (!arg || !dst || !ptr_derefs_may_alias_p (arg, dst))
    2477        15791 :     return HOST_WIDE_INT_MIN;
    2478              : 
    2479              :   /* The two arguments may refer to the same object.  If they both refer
    2480              :      to a struct member, see if the members are one and the same.  If so,
    2481              :      return the offset into the member.  */
    2482         3203 :   HOST_WIDE_INT arg_off = 0, arg_fld = 0;
    2483              : 
    2484         3203 :   tree arg_orig = get_origin_and_offset (arg, &arg_fld, &arg_off, arg_size);
    2485              : 
    2486         3203 :   if (arg_orig == dst && arg_fld == dst_fld)
    2487          262 :     return arg_off;
    2488              : 
    2489              :   return HOST_WIDE_INT_MIN;
    2490              : }
    2491              : 
    2492              : /* Return the minimum and maximum number of characters formatted
    2493              :    by the '%s' format directive and its wide character form for
    2494              :    the argument ARG.  ARG can be null (for functions such as
    2495              :    vsprinf).  */
    2496              : 
    2497              : static fmtresult
    2498       268332 : format_string (const directive &dir, tree arg, pointer_query &ptr_qry)
    2499              : {
    2500       268332 :   fmtresult res;
    2501              : 
    2502              :   /* The size of the (sub)object ARG refers to.  Used to adjust
    2503              :      the conservative get_string_length() result.  */
    2504       268332 :   HOST_WIDE_INT arg_size = 0;
    2505              : 
    2506       268332 :   if (warn_restrict)
    2507              :     {
    2508              :       /* See if ARG might alias the destination of the call with
    2509              :          DST_ORIGIN and DST_FIELD.  If so, store the starting offset
    2510              :          so that the overlap can be determined for certain later,
    2511              :          when the amount of output of the call (including subsequent
    2512              :          directives) has been computed.  Otherwise, store HWI_MIN.  */
    2513        37988 :       res.dst_offset = alias_offset (arg, &arg_size, dir.info->dst_origin,
    2514        18994 :                                      dir.info->dst_field);
    2515        18994 :       if (res.dst_offset >= 0 && res.dst_offset <= arg_size)
    2516          140 :         arg_size -= res.dst_offset;
    2517              :       else
    2518        18854 :         arg_size = 0;
    2519              :     }
    2520              : 
    2521              :   /* Compute the range the argument's length can be in.  */
    2522       268332 :   int count_by = 1;
    2523       268332 :   if (dir.specifier == 'S' || dir.modifier == FMT_LEN_l)
    2524              :     {
    2525              :       /* Get a node for a C type that will be the same size
    2526              :          as a wchar_t on the target.  */
    2527          300 :       tree node = get_typenode_from_name (MODIFIED_WCHAR_TYPE);
    2528              : 
    2529              :       /* Now that we have a suitable node, get the number of
    2530              :          bytes it occupies.  */
    2531          300 :       count_by = int_size_in_bytes (node);
    2532          300 :       gcc_checking_assert (count_by == 2 || count_by == 4);
    2533              :     }
    2534              : 
    2535       268332 :   fmtresult slen =
    2536       268332 :     get_string_length (arg, dir.info->callstmt, arg_size, count_by, ptr_qry);
    2537       268332 :   if (slen.range.min == slen.range.max
    2538       261725 :       && slen.range.min < HOST_WIDE_INT_MAX)
    2539              :     {
    2540              :       /* The argument is either a string constant or it refers
    2541              :          to one of a number of strings of the same length.  */
    2542              : 
    2543              :       /* A '%s' directive with a string argument with constant length.  */
    2544       248781 :       res.range = slen.range;
    2545              : 
    2546       248781 :       if (dir.specifier == 'S'
    2547       248777 :           || dir.modifier == FMT_LEN_l)
    2548              :         {
    2549              :           /* In the worst case the length of output of a wide string S
    2550              :              is bounded by MB_LEN_MAX * wcslen (S).  */
    2551          116 :           res.range.max *= target_mb_len_max ();
    2552          116 :           res.range.unlikely = res.range.max;
    2553              :           /* It's likely that the total length is not more that
    2554              :              2 * wcslen (S).*/
    2555          116 :           res.range.likely = res.range.min * 2;
    2556              : 
    2557          116 :           if (dir.prec[1] >= 0
    2558           57 :               && (unsigned HOST_WIDE_INT)dir.prec[1] < res.range.max)
    2559              :             {
    2560           51 :               res.range.max = dir.prec[1];
    2561           51 :               res.range.likely = dir.prec[1];
    2562           51 :               res.range.unlikely = dir.prec[1];
    2563              :             }
    2564              : 
    2565          116 :           if (dir.prec[0] < 0 && dir.prec[1] > -1)
    2566              :             res.range.min = 0;
    2567          112 :           else if (dir.prec[0] >= 0)
    2568           53 :             res.range.likely = dir.prec[0];
    2569              : 
    2570              :           /* Even a non-empty wide character string need not convert into
    2571              :              any bytes.  */
    2572          116 :           res.range.min = 0;
    2573              : 
    2574              :           /* A non-empty wide character conversion may fail.  */
    2575          116 :           if (slen.range.max > 0)
    2576           80 :             res.mayfail = true;
    2577              :         }
    2578              :       else
    2579              :         {
    2580       248665 :           res.knownrange = true;
    2581              : 
    2582       248665 :           if (dir.prec[0] < 0 && dir.prec[1] > -1)
    2583           16 :             res.range.min = 0;
    2584       248649 :           else if ((unsigned HOST_WIDE_INT)dir.prec[0] < res.range.min)
    2585           65 :             res.range.min = dir.prec[0];
    2586              : 
    2587       248665 :           if ((unsigned HOST_WIDE_INT)dir.prec[1] < res.range.max)
    2588              :             {
    2589           47 :               res.range.max = dir.prec[1];
    2590           47 :               res.range.likely = dir.prec[1];
    2591           47 :               res.range.unlikely = dir.prec[1];
    2592              :             }
    2593              :         }
    2594              :     }
    2595        19551 :   else if (arg && integer_zerop (arg))
    2596              :     {
    2597              :       /* Handle null pointer argument.  */
    2598              : 
    2599           33 :       fmtresult res (0);
    2600           33 :       res.nullp = true;
    2601           33 :       return res;
    2602              :     }
    2603              :   else
    2604              :     {
    2605              :       /* For a '%s' and '%ls' directive with a non-constant string (either
    2606              :          one of a number of strings of known length or an unknown string)
    2607              :          the minimum number of characters is lesser of PRECISION[0] and
    2608              :          the length of the shortest known string or zero, and the maximum
    2609              :          is the lesser of the length of the longest known string or
    2610              :          PTRDIFF_MAX and PRECISION[1].  The likely length is either
    2611              :          the minimum at level 1 and the greater of the minimum and 1
    2612              :          at level 2.  This result is adjust upward for width (if it's
    2613              :          specified).  */
    2614              : 
    2615        19518 :       if (dir.specifier == 'S'
    2616        19483 :           || dir.modifier == FMT_LEN_l)
    2617              :         {
    2618              :           /* A wide character converts to as few as zero bytes.  */
    2619          178 :           slen.range.min = 0;
    2620          178 :           if (slen.range.max < target_int_max ())
    2621           43 :             slen.range.max *= target_mb_len_max ();
    2622              : 
    2623          178 :           if (slen.range.likely < target_int_max ())
    2624           50 :             slen.range.likely *= 2;
    2625              : 
    2626          178 :           if (slen.range.unlikely < target_int_max ())
    2627           42 :             slen.range.unlikely *= target_mb_len_max ();
    2628              : 
    2629              :           /* A non-empty wide character conversion may fail.  */
    2630          178 :           if (slen.range.max > 0)
    2631          178 :             res.mayfail = true;
    2632              :         }
    2633              : 
    2634        19518 :       res.range = slen.range;
    2635              : 
    2636        19518 :       if (dir.prec[0] >= 0)
    2637              :         {
    2638              :           /* Adjust the minimum to zero if the string length is unknown,
    2639              :              or at most the lower bound of the precision otherwise.  */
    2640          293 :           if (slen.range.min >= target_int_max ())
    2641          137 :             res.range.min = 0;
    2642          156 :           else if ((unsigned HOST_WIDE_INT)dir.prec[0] < slen.range.min)
    2643           21 :             res.range.min = dir.prec[0];
    2644              : 
    2645              :           /* Make both maxima no greater than the upper bound of precision.  */
    2646          293 :           if ((unsigned HOST_WIDE_INT)dir.prec[1] < slen.range.max
    2647          293 :               || slen.range.max >= target_int_max ())
    2648              :             {
    2649          223 :               res.range.max = dir.prec[1];
    2650          223 :               res.range.unlikely = dir.prec[1];
    2651              :             }
    2652              : 
    2653              :           /* If precision is constant, set the likely counter to the lesser
    2654              :              of it and the maximum string length.  Otherwise, if the lower
    2655              :              bound of precision is greater than zero, set the likely counter
    2656              :              to the minimum.  Otherwise set it to zero or one based on
    2657              :              the warning level.  */
    2658          293 :           if (dir.prec[0] == dir.prec[1])
    2659          158 :             res.range.likely
    2660          158 :               = ((unsigned HOST_WIDE_INT)dir.prec[0] < slen.range.max
    2661          158 :                  ? dir.prec[0] : slen.range.max);
    2662          135 :           else if (dir.prec[0] > 0)
    2663           38 :             res.range.likely = res.range.min;
    2664              :           else
    2665           97 :             res.range.likely = warn_level > 1;
    2666              :         }
    2667        19225 :       else if (dir.prec[1] >= 0)
    2668              :         {
    2669           92 :           res.range.min = 0;
    2670           92 :           if ((unsigned HOST_WIDE_INT)dir.prec[1] < slen.range.max)
    2671           92 :             res.range.max = dir.prec[1];
    2672           92 :           res.range.likely = dir.prec[1] ? warn_level > 1 : 0;
    2673           92 :           if ((unsigned HOST_WIDE_INT)dir.prec[1] < slen.range.unlikely)
    2674           92 :             res.range.unlikely = dir.prec[1];
    2675              :         }
    2676        19133 :       else if (slen.range.min >= target_int_max ())
    2677              :         {
    2678        12568 :           res.range.min = 0;
    2679        12568 :           res.range.max = HOST_WIDE_INT_MAX;
    2680              :           /* At level 1 strings of unknown length are assumed to be
    2681              :              empty, while at level 1 they are assumed to be one byte
    2682              :              long.  */
    2683        12568 :           res.range.likely = warn_level > 1;
    2684        12568 :           res.range.unlikely = HOST_WIDE_INT_MAX;
    2685              :         }
    2686              :       else
    2687              :         {
    2688              :           /* A string of unknown length unconstrained by precision is
    2689              :              assumed to be empty at level 1 and just one character long
    2690              :              at higher levels.  */
    2691         6565 :           if (res.range.likely >= target_int_max ())
    2692          115 :             res.range.likely = warn_level > 1;
    2693              :         }
    2694              :     }
    2695              : 
    2696              :   /* If the argument isn't a nul-terminated string and the number
    2697              :      of bytes on output isn't bounded by precision, set NONSTR.  */
    2698       268299 :   if (slen.nonstr && slen.range.min < (unsigned HOST_WIDE_INT)dir.prec[0])
    2699          135 :     res.nonstr = slen.nonstr;
    2700              : 
    2701              :   /* Bump up the byte counters if WIDTH is greater.  */
    2702       268299 :   return res.adjust_for_width_or_precision (dir.width);
    2703              : }
    2704              : 
    2705              : /* Format plain string (part of the format string itself).  */
    2706              : 
    2707              : static fmtresult
    2708       557298 : format_plain (const directive &dir, tree, pointer_query &)
    2709              : {
    2710       557298 :   fmtresult res (dir.len);
    2711       557298 :   return res;
    2712              : }
    2713              : 
    2714              : /* Return true if the RESULT of a directive in a call describe by INFO
    2715              :    should be diagnosed given the AVAILable space in the destination.  */
    2716              : 
    2717              : static bool
    2718       962903 : should_warn_p (const call_info &info,
    2719              :                const result_range &avail, const result_range &result)
    2720              : {
    2721       962903 :   if (result.max <= avail.min)
    2722              :     {
    2723              :       /* The least amount of space remaining in the destination is big
    2724              :          enough for the longest output.  */
    2725              :       return false;
    2726              :     }
    2727              : 
    2728        16214 :   if (info.bounded)
    2729              :     {
    2730         1192 :       if (warn_format_trunc == 1 && result.min <= avail.max
    2731         2955 :           && info.retval_used ())
    2732              :         {
    2733              :           /* The likely amount of space remaining in the destination is big
    2734              :              enough for the least output and the return value is used.  */
    2735              :           return false;
    2736              :         }
    2737              : 
    2738         1130 :       if (warn_format_trunc == 1 && result.likely <= avail.likely
    2739         2804 :           && !info.retval_used ())
    2740              :         {
    2741              :           /* The likely amount of space remaining in the destination is big
    2742              :              enough for the likely output and the return value is unused.  */
    2743              :           return false;
    2744              :         }
    2745              : 
    2746          666 :       if (warn_format_trunc == 2
    2747           84 :           && result.likely <= avail.min
    2748           69 :           && (result.max <= avail.min
    2749           69 :               || result.max > HOST_WIDE_INT_MAX))
    2750              :         {
    2751              :           /* The minimum amount of space remaining in the destination is big
    2752              :              enough for the longest output.  */
    2753              :           return false;
    2754              :         }
    2755              :     }
    2756              :   else
    2757              :     {
    2758        14417 :       if (warn_level == 1 && result.likely <= avail.likely)
    2759              :         {
    2760              :           /* The likely amount of space remaining in the destination is big
    2761              :              enough for the likely output.  */
    2762              :           return false;
    2763              :         }
    2764              : 
    2765         5748 :       if (warn_level == 2
    2766          301 :           && result.likely <= avail.min
    2767              :           && (result.max <= avail.min
    2768          183 :               || result.max > HOST_WIDE_INT_MAX))
    2769              :         {
    2770              :           /* The minimum amount of space remaining in the destination is big
    2771              :              enough for the longest output.  */
    2772              :           return false;
    2773              :         }
    2774              :     }
    2775              : 
    2776              :   return true;
    2777              : }
    2778              : 
    2779              : /* At format string location describe by DIRLOC in a call described
    2780              :    by INFO, issue a warning for a directive DIR whose output may be
    2781              :    in excess of the available space AVAIL_RANGE in the destination
    2782              :    given the formatting result FMTRES.  This function does nothing
    2783              :    except decide whether to issue a warning for a possible write
    2784              :    past the end or truncation and, if so, format the warning.
    2785              :    Return true if a warning has been issued.  */
    2786              : 
    2787              : static bool
    2788       962903 : maybe_warn (substring_loc &dirloc, location_t argloc,
    2789              :             const call_info &info,
    2790              :             const result_range &avail_range, const result_range &res,
    2791              :             const directive &dir)
    2792              : {
    2793       962903 :   if (!should_warn_p (info, avail_range, res))
    2794              :     return false;
    2795              : 
    2796              :   /* A warning will definitely be issued below.  */
    2797              : 
    2798              :   /* The maximum byte count to reference in the warning.  Larger counts
    2799              :      imply that the upper bound is unknown (and could be anywhere between
    2800              :      RES.MIN + 1 and SIZE_MAX / 2) are printed as "N or more bytes" rather
    2801              :      than "between N and X" where X is some huge number.  */
    2802         6215 :   unsigned HOST_WIDE_INT maxbytes = target_dir_max ();
    2803              : 
    2804              :   /* True when there is enough room in the destination for the least
    2805              :      amount of a directive's output but not enough for its likely or
    2806              :      maximum output.  */
    2807        12430 :   bool maybe = (res.min <= avail_range.max
    2808         6215 :                 && (avail_range.min < res.likely
    2809         3612 :                     || (res.max < HOST_WIDE_INT_MAX
    2810          229 :                         && avail_range.min < res.max)));
    2811              : 
    2812              :   /* Buffer for the directive in the host character set (used when
    2813              :      the source character set is different).  */
    2814         6215 :   char hostdir[32];
    2815              : 
    2816         6215 :   if (avail_range.min == avail_range.max)
    2817              :     {
    2818              :       /* The size of the destination region is exact.  */
    2819         5410 :       unsigned HOST_WIDE_INT navail = avail_range.max;
    2820              : 
    2821         5410 :       if (target_to_host (*dir.beg) != '%')
    2822              :         {
    2823              :           /* For plain character directives (i.e., the format string itself)
    2824              :              but not others, point the caret at the first character that's
    2825              :              past the end of the destination.  */
    2826          641 :           if (navail < dir.len)
    2827          641 :             dirloc.set_caret_index (dirloc.get_caret_idx () + navail);
    2828              :         }
    2829              : 
    2830         5410 :       if (*dir.beg == '\0')
    2831              :         {
    2832              :           /* This is the terminating nul.  */
    2833          585 :           gcc_assert (res.min == 1 && res.min == res.max);
    2834              : 
    2835          585 :           return fmtwarn (dirloc, UNKNOWN_LOCATION, NULL, info.warnopt (),
    2836          585 :                           info.bounded
    2837              :                           ? (maybe
    2838          137 :                              ? G_("%qE output may be truncated before the "
    2839              :                                   "last format character")
    2840              :                              : G_("%qE output truncated before the last "
    2841              :                                   "format character"))
    2842              :                           : (maybe
    2843          448 :                              ? G_("%qE may write a terminating nul past the "
    2844              :                                   "end of the destination")
    2845              :                              : G_("%qE writing a terminating nul past the "
    2846              :                                   "end of the destination")),
    2847         1170 :                           info.func);
    2848              :         }
    2849              : 
    2850         4825 :       if (res.min == res.max)
    2851              :         {
    2852          399 :           const char *d = target_to_host (hostdir, sizeof hostdir, dir.beg);
    2853          399 :           if (!info.bounded)
    2854          349 :             return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min,
    2855              :                               "%<%.*s%> directive writing %wu byte into a "
    2856              :                               "region of size %wu",
    2857              :                               "%<%.*s%> directive writing %wu bytes into a "
    2858              :                               "region of size %wu",
    2859          349 :                               (int) dir.len, d, res.min, navail);
    2860           50 :           else if (maybe)
    2861            0 :             return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min,
    2862              :                               "%<%.*s%> directive output may be truncated "
    2863              :                               "writing %wu byte into a region of size %wu",
    2864              :                               "%<%.*s%> directive output may be truncated "
    2865              :                               "writing %wu bytes into a region of size %wu",
    2866            0 :                               (int) dir.len, d, res.min, navail);
    2867              :           else
    2868           50 :             return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min,
    2869              :                               "%<%.*s%> directive output truncated writing "
    2870              :                               "%wu byte into a region of size %wu",
    2871              :                               "%<%.*s%> directive output truncated writing "
    2872              :                               "%wu bytes into a region of size %wu",
    2873           50 :                               (int) dir.len, d, res.min, navail);
    2874              :         }
    2875         4426 :       if (res.min == 0 && res.max < maxbytes)
    2876          418 :         return fmtwarn (dirloc, argloc, NULL,
    2877              :                         info.warnopt (),
    2878          209 :                         info.bounded
    2879              :                         ? (maybe
    2880            5 :                            ? G_("%<%.*s%> directive output may be truncated "
    2881              :                                 "writing up to %wu bytes into a region of "
    2882              :                                 "size %wu")
    2883              :                            : G_("%<%.*s%> directive output truncated writing "
    2884              :                                 "up to %wu bytes into a region of size %wu"))
    2885              :                         : G_("%<%.*s%> directive writing up to %wu bytes "
    2886          209 :                              "into a region of size %wu"), (int) dir.len,
    2887              :                         target_to_host (hostdir, sizeof hostdir, dir.beg),
    2888          209 :                         res.max, navail);
    2889              : 
    2890         4217 :       if (res.min == 0 && maxbytes <= res.max)
    2891              :         /* This is a special case to avoid issuing the potentially
    2892              :            confusing warning:
    2893              :              writing 0 or more bytes into a region of size 0.  */
    2894         3387 :         return fmtwarn (dirloc, argloc, NULL, info.warnopt (),
    2895         3387 :                         info.bounded
    2896              :                         ? (maybe
    2897          171 :                            ? G_("%<%.*s%> directive output may be truncated "
    2898              :                                 "writing likely %wu or more bytes into a "
    2899              :                                 "region of size %wu")
    2900              :                            : G_("%<%.*s%> directive output truncated writing "
    2901              :                                 "likely %wu or more bytes into a region of "
    2902              :                                 "size %wu"))
    2903              :                         : G_("%<%.*s%> directive writing likely %wu or more "
    2904         3387 :                              "bytes into a region of size %wu"), (int) dir.len,
    2905              :                         target_to_host (hostdir, sizeof hostdir, dir.beg),
    2906         6774 :                         res.likely, navail);
    2907              : 
    2908          830 :       if (res.max < maxbytes)
    2909         1644 :         return fmtwarn (dirloc, argloc, NULL, info.warnopt (),
    2910          822 :                         info.bounded
    2911              :                         ? (maybe
    2912           72 :                            ? G_("%<%.*s%> directive output may be truncated "
    2913              :                                 "writing between %wu and %wu bytes into a "
    2914              :                                 "region of size %wu")
    2915              :                            : G_("%<%.*s%> directive output truncated "
    2916              :                                 "writing between %wu and %wu bytes into a "
    2917              :                                 "region of size %wu"))
    2918              :                         : G_("%<%.*s%> directive writing between %wu and "
    2919              :                              "%wu bytes into a region of size %wu"),
    2920          822 :                         (int) dir.len,
    2921              :                         target_to_host (hostdir, sizeof hostdir, dir.beg),
    2922          822 :                         res.min, res.max, navail);
    2923              : 
    2924           16 :       return fmtwarn (dirloc, argloc, NULL, info.warnopt (),
    2925            8 :                       info.bounded
    2926              :                       ? (maybe
    2927            3 :                          ? G_("%<%.*s%> directive output may be truncated "
    2928              :                               "writing %wu or more bytes into a region of "
    2929              :                               "size %wu")
    2930              :                          : G_("%<%.*s%> directive output truncated writing "
    2931              :                               "%wu or more bytes into a region of size %wu"))
    2932              :                       : G_("%<%.*s%> directive writing %wu or more bytes "
    2933            8 :                            "into a region of size %wu"), (int) dir.len,
    2934              :                       target_to_host (hostdir, sizeof hostdir, dir.beg),
    2935            8 :                       res.min, navail);
    2936              :     }
    2937              : 
    2938              :   /* The size of the destination region is a range.  */
    2939              : 
    2940          805 :   if (target_to_host (*dir.beg) != '%')
    2941              :     {
    2942          606 :       unsigned HOST_WIDE_INT navail = avail_range.max;
    2943              : 
    2944              :       /* For plain character directives (i.e., the format string itself)
    2945              :          but not others, point the caret at the first character that's
    2946              :          past the end of the destination.  */
    2947          606 :       if (navail < dir.len)
    2948            1 :         dirloc.set_caret_index (dirloc.get_caret_idx () + navail);
    2949              :     }
    2950              : 
    2951          805 :   if (*dir.beg == '\0')
    2952              :     {
    2953          459 :       gcc_assert (res.min == 1 && res.min == res.max);
    2954              : 
    2955          459 :       return fmtwarn (dirloc, UNKNOWN_LOCATION, NULL, info.warnopt (),
    2956          459 :                       info.bounded
    2957              :                       ? (maybe
    2958           84 :                          ? G_("%qE output may be truncated before the last "
    2959              :                               "format character")
    2960              :                          : G_("%qE output truncated before the last format "
    2961              :                               "character"))
    2962              :                       : (maybe
    2963          375 :                          ? G_("%qE may write a terminating nul past the end "
    2964              :                               "of the destination")
    2965              :                          : G_("%qE writing a terminating nul past the end "
    2966          918 :                               "of the destination")), info.func);
    2967              :     }
    2968              : 
    2969          346 :   if (res.min == res.max)
    2970              :     {
    2971          149 :       const char *d = target_to_host (hostdir, sizeof hostdir, dir.beg);
    2972          149 :       if (!info.bounded)
    2973          133 :         return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min,
    2974              :                           "%<%.*s%> directive writing %wu byte into a region "
    2975              :                           "of size between %wu and %wu",
    2976              :                           "%<%.*s%> directive writing %wu bytes into a region "
    2977          133 :                           "of size between %wu and %wu", (int) dir.len, d,
    2978          133 :                           res.min, avail_range.min, avail_range.max);
    2979           16 :       else if (maybe)
    2980           15 :         return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min,
    2981              :                           "%<%.*s%> directive output may be truncated writing "
    2982              :                           "%wu byte into a region of size between %wu and %wu",
    2983              :                           "%<%.*s%> directive output may be truncated writing "
    2984              :                           "%wu bytes into a region of size between %wu and "
    2985           15 :                           "%wu", (int) dir.len, d, res.min, avail_range.min,
    2986           15 :                           avail_range.max);
    2987              :       else
    2988            1 :         return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min,
    2989              :                           "%<%.*s%> directive output truncated writing %wu "
    2990              :                           "byte into a region of size between %wu and %wu",
    2991              :                           "%<%.*s%> directive output truncated writing %wu "
    2992              :                           "bytes into a region of size between %wu and %wu",
    2993            1 :                           (int) dir.len, d, res.min, avail_range.min,
    2994            1 :                           avail_range.max);
    2995              :     }
    2996              : 
    2997          197 :   if (res.min == 0 && res.max < maxbytes)
    2998            6 :     return fmtwarn (dirloc, argloc, NULL, info.warnopt (),
    2999            3 :                     info.bounded
    3000              :                     ? (maybe
    3001            0 :                        ? G_("%<%.*s%> directive output may be truncated "
    3002              :                             "writing up to %wu bytes into a region of size "
    3003              :                             "between %wu and %wu")
    3004              :                        : G_("%<%.*s%> directive output truncated writing "
    3005              :                             "up to %wu bytes into a region of size between "
    3006              :                             "%wu and %wu"))
    3007              :                     : G_("%<%.*s%> directive writing up to %wu bytes "
    3008              :                          "into a region of size between %wu and %wu"),
    3009            3 :                     (int) dir.len,
    3010              :                     target_to_host (hostdir, sizeof hostdir, dir.beg),
    3011            3 :                     res.max, avail_range.min, avail_range.max);
    3012              : 
    3013          194 :   if (res.min == 0 && maxbytes <= res.max)
    3014              :     /* This is a special case to avoid issuing the potentially confusing
    3015              :        warning:
    3016              :          writing 0 or more bytes into a region of size between 0 and N.  */
    3017            1 :     return fmtwarn (dirloc, argloc, NULL, info.warnopt (),
    3018            1 :                     info.bounded
    3019              :                     ? (maybe
    3020            0 :                        ? G_("%<%.*s%> directive output may be truncated "
    3021              :                             "writing likely %wu or more bytes into a region "
    3022              :                             "of size between %wu and %wu")
    3023              :                        : G_("%<%.*s%> directive output truncated writing "
    3024              :                             "likely %wu or more bytes into a region of size "
    3025              :                             "between %wu and %wu"))
    3026              :                     : G_("%<%.*s%> directive writing likely %wu or more bytes "
    3027              :                          "into a region of size between %wu and %wu"),
    3028            1 :                     (int) dir.len,
    3029              :                     target_to_host (hostdir, sizeof hostdir, dir.beg),
    3030            2 :                     res.likely, avail_range.min, avail_range.max);
    3031              : 
    3032          193 :   if (res.max < maxbytes)
    3033          386 :     return fmtwarn (dirloc, argloc, NULL, info.warnopt (),
    3034          193 :                     info.bounded
    3035              :                     ? (maybe
    3036           59 :                        ? G_("%<%.*s%> directive output may be truncated "
    3037              :                             "writing between %wu and %wu bytes into a region "
    3038              :                             "of size between %wu and %wu")
    3039              :                        : G_("%<%.*s%> directive output truncated writing "
    3040              :                             "between %wu and %wu bytes into a region of size "
    3041              :                             "between %wu and %wu"))
    3042              :                     : G_("%<%.*s%> directive writing between %wu and "
    3043              :                          "%wu bytes into a region of size between %wu and "
    3044          193 :                          "%wu"), (int) dir.len,
    3045              :                     target_to_host (hostdir, sizeof hostdir, dir.beg),
    3046          193 :                     res.min, res.max, avail_range.min, avail_range.max);
    3047              : 
    3048            0 :   return fmtwarn (dirloc, argloc, NULL, info.warnopt (),
    3049            0 :                   info.bounded
    3050              :                   ? (maybe
    3051            0 :                      ? G_("%<%.*s%> directive output may be truncated writing "
    3052              :                           "%wu or more bytes into a region of size between "
    3053              :                           "%wu and %wu")
    3054              :                      : G_("%<%.*s%> directive output truncated writing "
    3055              :                           "%wu or more bytes into a region of size between "
    3056              :                           "%wu and %wu"))
    3057              :                   : G_("%<%.*s%> directive writing %wu or more bytes "
    3058              :                        "into a region of size between %wu and %wu"),
    3059            0 :                   (int) dir.len,
    3060              :                   target_to_host (hostdir, sizeof hostdir, dir.beg),
    3061            0 :                   res.min, avail_range.min, avail_range.max);
    3062              : }
    3063              : 
    3064              : /* Given the formatting result described by RES and NAVAIL, the number
    3065              :    of available bytes in the destination, return the range of bytes
    3066              :    remaining in the destination.  */
    3067              : 
    3068              : static inline result_range
    3069       964285 : bytes_remaining (unsigned HOST_WIDE_INT navail, const format_result &res)
    3070              : {
    3071       964285 :   result_range range;
    3072              : 
    3073       964285 :   if (HOST_WIDE_INT_MAX <= navail)
    3074              :     {
    3075       945312 :       range.min = range.max = range.likely = range.unlikely = navail;
    3076       945312 :       return range;
    3077              :     }
    3078              : 
    3079              :   /* The lower bound of the available range is the available size
    3080              :      minus the maximum output size, and the upper bound is the size
    3081              :      minus the minimum.  */
    3082        18973 :   range.max = res.range.min < navail ? navail - res.range.min : 0;
    3083              : 
    3084        18973 :   range.likely = res.range.likely < navail ? navail - res.range.likely : 0;
    3085              : 
    3086        18973 :   if (res.range.max < HOST_WIDE_INT_MAX)
    3087        13705 :     range.min = res.range.max < navail ? navail - res.range.max : 0;
    3088              :   else
    3089         5268 :     range.min = range.likely;
    3090              : 
    3091        37946 :   range.unlikely = (res.range.unlikely < navail
    3092        18973 :                     ? navail - res.range.unlikely : 0);
    3093              : 
    3094        18973 :   return range;
    3095              : }
    3096              : 
    3097              : /* Compute the length of the output resulting from the directive DIR
    3098              :    in a call described by INFO and update the overall result of the call
    3099              :    in *RES.  Return true if the directive has been handled.  */
    3100              : 
    3101              : static bool
    3102       966970 : format_directive (const call_info &info,
    3103              :                   format_result *res, const directive &dir,
    3104              :                   pointer_query &ptr_qry)
    3105              : {
    3106              :   /* Offset of the beginning of the directive from the beginning
    3107              :      of the format string.  */
    3108       966970 :   size_t offset = dir.beg - info.fmtstr;
    3109       966970 :   size_t start = offset;
    3110       966970 :   size_t length = offset + dir.len - !!dir.len;
    3111              : 
    3112              :   /* Create a location for the whole directive from the % to the format
    3113              :      specifier.  */
    3114      1933940 :   substring_loc dirloc (info.fmtloc, TREE_TYPE (info.format),
    3115       966970 :                         offset, start, length);
    3116              : 
    3117              :   /* Also get the location of the argument if possible.
    3118              :      This doesn't work for integer literals or function calls.  */
    3119       966970 :   location_t argloc = UNKNOWN_LOCATION;
    3120       966970 :   if (dir.arg)
    3121       405850 :     argloc = EXPR_LOCATION (dir.arg);
    3122              : 
    3123              :   /* Bail when there is no function to compute the output length,
    3124              :      or when minimum length checking has been disabled.   */
    3125       966970 :   if (!dir.fmtfunc || res->range.min >= HOST_WIDE_INT_MAX)
    3126              :     return false;
    3127              : 
    3128              :   /* Compute the range of lengths of the formatted output.  */
    3129       964435 :   fmtresult fmtres = dir.fmtfunc (dir, dir.arg, ptr_qry);
    3130              : 
    3131              :   /* Record whether the output of all directives is known to be
    3132              :      bounded by some maximum, implying that their arguments are
    3133              :      either known exactly or determined to be in a known range
    3134              :      or, for strings, limited by the upper bounds of the arrays
    3135              :      they refer to.  */
    3136       964435 :   res->knownrange &= fmtres.knownrange;
    3137              : 
    3138       964435 :   if (!fmtres.knownrange)
    3139              :     {
    3140              :       /* Only when the range is known, check it against the host value
    3141              :          of INT_MAX + (the number of bytes of the "%.*Lf" directive with
    3142              :          INT_MAX precision, which is the longest possible output of any
    3143              :          single directive).  That's the largest valid byte count (though
    3144              :          not valid call to a printf-like function because it can never
    3145              :          return such a count).  Otherwise, the range doesn't correspond
    3146              :          to known values of the argument.  */
    3147        48377 :       if (fmtres.range.max > target_dir_max ())
    3148              :         {
    3149              :           /* Normalize the MAX counter to avoid having to deal with it
    3150              :              later.  The counter can be less than HOST_WIDE_INT_M1U
    3151              :              when compiling for an ILP32 target on an LP64 host.  */
    3152        12975 :           fmtres.range.max = HOST_WIDE_INT_M1U;
    3153              :           /* Disable exact and maximum length checking after a failure
    3154              :              to determine the maximum number of characters (for example
    3155              :              for wide characters or wide character strings) but continue
    3156              :              tracking the minimum number of characters.  */
    3157        12975 :           res->range.max = HOST_WIDE_INT_M1U;
    3158              :         }
    3159              : 
    3160        48377 :       if (fmtres.range.min > target_dir_max ())
    3161              :         {
    3162              :           /* Disable exact length checking after a failure to determine
    3163              :              even the minimum number of characters (it shouldn't happen
    3164              :              except in an error) but keep tracking the minimum and maximum
    3165              :              number of characters.  */
    3166              :           return true;
    3167              :         }
    3168              :     }
    3169              : 
    3170              :   /* Buffer for the directive in the host character set (used when
    3171              :      the source character set is different).  */
    3172       964318 :   char hostdir[32];
    3173              : 
    3174       964318 :   int dirlen = dir.len;
    3175              : 
    3176       964318 :   if (fmtres.nullp)
    3177              :     {
    3178           62 :       fmtwarn (dirloc, argloc, NULL, info.warnopt (),
    3179              :                "%<%.*s%> directive argument is null",
    3180           33 :                dirlen, target_to_host (hostdir, sizeof hostdir, dir.beg));
    3181              : 
    3182              :       /* Don't bother processing the rest of the format string.  */
    3183           33 :       res->warned = true;
    3184           33 :       res->range.min = HOST_WIDE_INT_M1U;
    3185           33 :       res->range.max = HOST_WIDE_INT_M1U;
    3186           33 :       return false;
    3187              :     }
    3188              : 
    3189              :   /* Compute the number of available bytes in the destination.  There
    3190              :      must always be at least one byte of space for the terminating
    3191              :      NUL that's appended after the format string has been processed.  */
    3192       964285 :   result_range avail_range = bytes_remaining (info.objsize, *res);
    3193              : 
    3194              :   /* If the argument aliases a part of the destination of the formatted
    3195              :      call at offset FMTRES.DST_OFFSET append the directive and its result
    3196              :      to the set of aliases for later processing.  */
    3197       964285 :   if (fmtres.dst_offset != HOST_WIDE_INT_MIN)
    3198          262 :     res->append_alias (dir, fmtres.dst_offset, fmtres.range);
    3199              : 
    3200       964285 :   bool warned = res->warned;
    3201              : 
    3202       964285 :   if (!warned)
    3203       962903 :     warned = maybe_warn (dirloc, argloc, info, avail_range,
    3204              :                          fmtres.range, dir);
    3205              : 
    3206              :   /* Bump up the total maximum if it isn't too big.  */
    3207       964285 :   if (res->range.max < HOST_WIDE_INT_MAX
    3208       922004 :       && fmtres.range.max < HOST_WIDE_INT_MAX)
    3209       922002 :     res->range.max += fmtres.range.max;
    3210              : 
    3211              :   /* Raise the total unlikely maximum by the larger of the maximum
    3212              :      and the unlikely maximum.  */
    3213       964285 :   unsigned HOST_WIDE_INT save = res->range.unlikely;
    3214       964285 :   if (fmtres.range.max < fmtres.range.unlikely)
    3215         7893 :     res->range.unlikely += fmtres.range.unlikely;
    3216              :   else
    3217       956392 :     res->range.unlikely += fmtres.range.max;
    3218              : 
    3219       964285 :   if (res->range.unlikely < save)
    3220        40208 :     res->range.unlikely = HOST_WIDE_INT_M1U;
    3221              : 
    3222       964285 :   res->range.min += fmtres.range.min;
    3223       964285 :   res->range.likely += fmtres.range.likely;
    3224              : 
    3225              :   /* Has the minimum directive output length exceeded the maximum
    3226              :      of 4095 bytes required to be supported?  */
    3227       964285 :   bool minunder4k = fmtres.range.min < 4096;
    3228       964285 :   bool maxunder4k = fmtres.range.max < 4096;
    3229              :   /* Clear POSUNDER4K in the overall result if the maximum has exceeded
    3230              :      the 4k (this is necessary to avoid the return value optimization
    3231              :      that may not be safe in the maximum case).  */
    3232       964285 :   if (!maxunder4k)
    3233        13702 :     res->posunder4k = false;
    3234              :   /* Also clear POSUNDER4K if the directive may fail.  */
    3235       964285 :   if (fmtres.mayfail)
    3236          331 :     res->posunder4k = false;
    3237              : 
    3238       964285 :   if (!warned
    3239              :       /* Only warn at level 2.  */
    3240       961087 :       && warn_level > 1
    3241              :       /* Only warn for string functions.  */
    3242         1156 :       && info.is_string_func ()
    3243       964671 :       && (!minunder4k
    3244          384 :           || (!maxunder4k && fmtres.range.max < HOST_WIDE_INT_MAX)))
    3245              :     {
    3246              :       /* The directive output may be longer than the maximum required
    3247              :          to be handled by an implementation according to 7.21.6.1, p15
    3248              :          of C11.  Warn on this only at level 2 but remember this and
    3249              :          prevent folding the return value when done.  This allows for
    3250              :          the possibility of the actual libc call failing due to ENOMEM
    3251              :          (like Glibc does with very large precision or width).
    3252              :          Issue the "may exceed" warning only for string functions and
    3253              :          not for fprintf or printf.  */
    3254              : 
    3255            6 :       if (fmtres.range.min == fmtres.range.max)
    3256            2 :         warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (),
    3257              :                           "%<%.*s%> directive output of %wu bytes exceeds "
    3258              :                           "minimum required size of 4095", dirlen,
    3259            2 :                           target_to_host (hostdir, sizeof hostdir, dir.beg),
    3260              :                           fmtres.range.min);
    3261            4 :       else if (!minunder4k)
    3262            0 :         warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (),
    3263              :                           "%<%.*s%> directive output between %wu and %wu "
    3264              :                           "bytes exceeds minimum required size of 4095",
    3265              :                           dirlen,
    3266            0 :                           target_to_host (hostdir, sizeof hostdir, dir.beg),
    3267              :                           fmtres.range.min, fmtres.range.max);
    3268            4 :       else if (!info.retval_used () && info.is_string_func ())
    3269            2 :         warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (),
    3270              :                           "%<%.*s%> directive output between %wu and %wu "
    3271              :                           "bytes may exceed minimum required size of "
    3272              :                           "4095",
    3273              :                           dirlen,
    3274            2 :                           target_to_host (hostdir, sizeof hostdir, dir.beg),
    3275              :                           fmtres.range.min, fmtres.range.max);
    3276              :     }
    3277              : 
    3278              :   /* Has the likely and maximum directive output exceeded INT_MAX?  */
    3279       964285 :   bool likelyximax = *dir.beg && res->range.likely > target_int_max ();
    3280              :   /* Don't consider the maximum to be in excess when it's the result
    3281              :      of a string of unknown length (i.e., whose maximum has been set
    3282              :      to be greater than or equal to HOST_WIDE_INT_MAX.  */
    3283       964285 :   bool maxximax = (*dir.beg
    3284       829517 :                    && res->range.max > target_int_max ()
    3285       995123 :                    && res->range.max < HOST_WIDE_INT_MAX);
    3286              : 
    3287       964285 :   if (!warned
    3288              :       /* Warn for the likely output size at level 1.  */
    3289       961083 :       && (likelyximax
    3290              :           /* But only warn for the maximum at level 2.  */
    3291       960945 :           || (warn_level > 1
    3292         1048 :               && maxximax
    3293           84 :               && fmtres.range.max < HOST_WIDE_INT_MAX)))
    3294              :     {
    3295          222 :       if (fmtres.range.min > target_int_max ())
    3296              :         {
    3297              :           /* The directive output exceeds INT_MAX bytes.  */
    3298           32 :           if (fmtres.range.min == fmtres.range.max)
    3299           40 :             warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (),
    3300              :                               "%<%.*s%> directive output of %wu bytes exceeds "
    3301              :                               "%<INT_MAX%>", dirlen,
    3302              :                               target_to_host (hostdir, sizeof hostdir, dir.beg),
    3303              :                               fmtres.range.min);
    3304              :           else
    3305           24 :             warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (),
    3306              :                               "%<%.*s%> directive output between %wu and "
    3307              :                               "%wu bytes exceeds %<INT_MAX%>", dirlen,
    3308              :                               target_to_host (hostdir, sizeof hostdir, dir.beg),
    3309              :                               fmtres.range.min, fmtres.range.max);
    3310              :         }
    3311          190 :       else if (res->range.min > target_int_max ())
    3312              :         {
    3313              :           /* The directive output is under INT_MAX but causes the result
    3314              :              to exceed INT_MAX bytes.  */
    3315          104 :           if (fmtres.range.min == fmtres.range.max)
    3316          182 :             warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (),
    3317              :                               "%<%.*s%> directive output of %wu bytes causes "
    3318              :                               "result to exceed %<INT_MAX%>", dirlen,
    3319              :                               target_to_host (hostdir, sizeof hostdir, dir.beg),
    3320              :                               fmtres.range.min);
    3321              :           else
    3322           26 :             warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (),
    3323              :                               "%<%.*s%> directive output between %wu and "
    3324              :                               "%wu bytes causes result to exceed %<INT_MAX%>",
    3325              :                               dirlen,
    3326              :                               target_to_host (hostdir, sizeof hostdir, dir.beg),
    3327              :                               fmtres.range.min, fmtres.range.max);
    3328              :         }
    3329           86 :       else if ((!info.retval_used () || !info.bounded)
    3330           86 :                && (info.is_string_func ()))
    3331              :         /* Warn for calls to string functions that either aren't bounded
    3332              :            (sprintf) or whose return value isn't used.  */
    3333            0 :         warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (),
    3334              :                           "%<%.*s%> directive output between %wu and "
    3335              :                           "%wu bytes may cause result to exceed "
    3336              :                           "%<INT_MAX%>", dirlen,
    3337            0 :                           target_to_host (hostdir, sizeof hostdir, dir.beg),
    3338              :                           fmtres.range.min, fmtres.range.max);
    3339              :     }
    3340              : 
    3341       961083 :   if (!warned && fmtres.nonstr)
    3342              :     {
    3343          268 :       warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (),
    3344              :                         "%<%.*s%> directive argument is not a nul-terminated "
    3345              :                         "string",
    3346              :                         dirlen,
    3347          135 :                         target_to_host (hostdir, sizeof hostdir, dir.beg));
    3348          135 :       if (warned && DECL_P (fmtres.nonstr))
    3349           45 :         inform (DECL_SOURCE_LOCATION (fmtres.nonstr),
    3350              :                 "referenced argument declared here");
    3351          135 :       return false;
    3352              :     }
    3353              : 
    3354         3338 :   if (warned && fmtres.range.min < fmtres.range.likely
    3355          572 :       && fmtres.range.likely < fmtres.range.max)
    3356          333 :     inform_n (info.fmtloc, fmtres.range.likely,
    3357              :               "assuming directive output of %wu byte",
    3358              :               "assuming directive output of %wu bytes",
    3359              :               fmtres.range.likely);
    3360              : 
    3361         3338 :   if (warned && fmtres.argmin)
    3362              :     {
    3363          382 :       if (fmtres.argmin == fmtres.argmax)
    3364            2 :         inform (info.fmtloc, "directive argument %qE", fmtres.argmin);
    3365          380 :       else if (fmtres.knownrange)
    3366          174 :         inform (info.fmtloc, "directive argument in the range [%E, %E]",
    3367              :                 fmtres.argmin, fmtres.argmax);
    3368              :       else
    3369          206 :         inform (info.fmtloc,
    3370              :                 "using the range [%E, %E] for directive argument",
    3371              :                 fmtres.argmin, fmtres.argmax);
    3372              :     }
    3373              : 
    3374       964150 :   res->warned |= warned;
    3375              : 
    3376       964150 :   if (!dir.beg[0] && res->warned)
    3377              :     {
    3378         1954 :       location_t callloc = gimple_location (info.callstmt);
    3379              : 
    3380         1954 :       unsigned HOST_WIDE_INT min = res->range.min;
    3381         1954 :       unsigned HOST_WIDE_INT max = res->range.max;
    3382              : 
    3383         1954 :       if (info.objsize < HOST_WIDE_INT_MAX)
    3384              :         {
    3385              :           /* If a warning has been issued for buffer overflow or truncation
    3386              :              help the user figure out how big a buffer they need.  */
    3387              : 
    3388         1816 :           if (min == max)
    3389          672 :             inform_n (callloc, min,
    3390              :                       "%qE output %wu byte into a destination of size %wu",
    3391              :                       "%qE output %wu bytes into a destination of size %wu",
    3392          672 :                       info.func, min, info.objsize);
    3393         1144 :           else if (max < HOST_WIDE_INT_MAX)
    3394         1099 :             inform (callloc,
    3395              :                     "%qE output between %wu and %wu bytes into "
    3396              :                     "a destination of size %wu",
    3397         1099 :                     info.func, min, max, info.objsize);
    3398           45 :           else if (min < res->range.likely && res->range.likely < max)
    3399           25 :             inform (callloc,
    3400              :                     "%qE output %wu or more bytes (assuming %wu) into "
    3401              :                     "a destination of size %wu",
    3402           25 :                     info.func, min, res->range.likely, info.objsize);
    3403              :           else
    3404           20 :             inform (callloc,
    3405              :                     "%qE output %wu or more bytes into a destination of size "
    3406              :                     "%wu",
    3407           20 :                     info.func, min, info.objsize);
    3408              :         }
    3409          138 :       else if (!info.is_string_func ())
    3410              :         {
    3411              :           /* If the warning is for a file function like fprintf
    3412              :              of printf with no destination size just print the computed
    3413              :              result.  */
    3414          129 :           if (min == max)
    3415           77 :             inform_n (callloc, min,
    3416              :                       "%qE output %wu byte", "%qE output %wu bytes",
    3417           77 :                       info.func, min);
    3418           52 :           else if (max < HOST_WIDE_INT_MAX)
    3419           12 :             inform (callloc,
    3420              :                     "%qE output between %wu and %wu bytes",
    3421           12 :                     info.func, min, max);
    3422           40 :           else if (min < res->range.likely && res->range.likely < max)
    3423            0 :             inform (callloc,
    3424              :                     "%qE output %wu or more bytes (assuming %wu)",
    3425            0 :                     info.func, min, res->range.likely);
    3426              :           else
    3427           40 :             inform (callloc,
    3428              :                     "%qE output %wu or more bytes",
    3429           40 :                     info.func, min);
    3430              :         }
    3431              :     }
    3432              : 
    3433       964150 :   if (dump_file && *dir.beg)
    3434              :     {
    3435            0 :       fprintf (dump_file,
    3436              :                "    Result: "
    3437              :                HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC ", "
    3438              :                HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC " ("
    3439              :                HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC ", "
    3440              :                HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC ")\n",
    3441              :                fmtres.range.min, fmtres.range.likely,
    3442              :                fmtres.range.max, fmtres.range.unlikely,
    3443              :                res->range.min, res->range.likely,
    3444              :                res->range.max, res->range.unlikely);
    3445              :     }
    3446              : 
    3447              :   return true;
    3448              : }
    3449              : 
    3450              : /* Parse a format directive in function call described by INFO starting
    3451              :    at STR and populate DIR structure.  Bump up *ARGNO by the number of
    3452              :    arguments extracted for the directive.  Return the length of
    3453              :    the directive.  */
    3454              : 
    3455              : static size_t
    3456       966970 : parse_directive (call_info &info,
    3457              :                  directive &dir, format_result *res,
    3458              :                  const char *str, unsigned *argno,
    3459              :                  range_query *query)
    3460              : {
    3461       966970 :   const char *pcnt = strchr (str, target_percent);
    3462       966970 :   dir.beg = str;
    3463              : 
    3464       966970 :   if (size_t len = pcnt ? pcnt - str : *str ? strlen (str) : 1)
    3465              :     {
    3466              :       /* This directive is either a plain string or the terminating nul
    3467              :          (which isn't really a directive but it simplifies things to
    3468              :          handle it as if it were).  */
    3469       557300 :       dir.len = len;
    3470       557300 :       dir.fmtfunc = format_plain;
    3471              : 
    3472       557300 :       if (dump_file)
    3473              :         {
    3474            0 :           fprintf (dump_file, "  Directive %u at offset "
    3475              :                    HOST_WIDE_INT_PRINT_UNSIGNED ": \"%.*s\", "
    3476              :                    "length = " HOST_WIDE_INT_PRINT_UNSIGNED "\n",
    3477              :                    dir.dirno,
    3478            0 :                    (unsigned HOST_WIDE_INT)(size_t)(dir.beg - info.fmtstr),
    3479              :                    (int)dir.len, dir.beg, (unsigned HOST_WIDE_INT) dir.len);
    3480              :         }
    3481              : 
    3482       557300 :       return len - !*str;
    3483              :     }
    3484              : 
    3485              :   /* Set the directive argument's number to correspond to its position
    3486              :      in the formatted function call's argument list.  */
    3487       409670 :   dir.argno = *argno;
    3488              : 
    3489       409670 :   const char *pf = pcnt + 1;
    3490              : 
    3491              :     /* POSIX numbered argument index or zero when none.  */
    3492       409670 :   HOST_WIDE_INT dollar = 0;
    3493              : 
    3494              :   /* With and precision.  -1 when not specified, HOST_WIDE_INT_MIN
    3495              :      when given by a va_list argument, and a non-negative value
    3496              :      when specified in the format string itself.  */
    3497       409670 :   HOST_WIDE_INT width = -1;
    3498       409670 :   HOST_WIDE_INT precision = -1;
    3499              : 
    3500              :   /* Pointers to the beginning of the width and precision decimal
    3501              :      string (if any) within the directive.  */
    3502       409670 :   const char *pwidth = 0;
    3503       409670 :   const char *pprec = 0;
    3504              : 
    3505              :   /* When the value of the decimal string that specifies width or
    3506              :      precision is out of range, points to the digit that causes
    3507              :      the value to exceed the limit.  */
    3508       409670 :   const char *werange = NULL;
    3509       409670 :   const char *perange = NULL;
    3510              : 
    3511              :   /* Width specified via the asterisk.  Need not be INTEGER_CST.
    3512              :      For vararg functions set to void_node.  */
    3513       409670 :   tree star_width = NULL_TREE;
    3514              : 
    3515              :   /* Width specified via the asterisk.  Need not be INTEGER_CST.
    3516              :      For vararg functions set to void_node.  */
    3517       409670 :   tree star_precision = NULL_TREE;
    3518              : 
    3519       409670 :   if (ISDIGIT (target_to_host (*pf)))
    3520              :     {
    3521              :       /* This could be either a POSIX positional argument, the '0'
    3522              :          flag, or a width, depending on what follows.  Store it as
    3523              :          width and sort it out later after the next character has
    3524              :          been seen.  */
    3525         1238 :       pwidth = pf;
    3526         1238 :       width = target_strtowi (&pf, &werange);
    3527              :     }
    3528       408432 :   else if (target_to_host (*pf) == '*')
    3529              :     {
    3530              :       /* Similarly to the block above, this could be either a POSIX
    3531              :          positional argument or a width, depending on what follows.  */
    3532          768 :       if (*argno < gimple_call_num_args (info.callstmt))
    3533          756 :         star_width = gimple_call_arg (info.callstmt, (*argno)++);
    3534              :       else
    3535           12 :         star_width = void_node;
    3536          768 :       ++pf;
    3537              :     }
    3538              : 
    3539       409670 :   if (target_to_host (*pf) == '$')
    3540              :     {
    3541              :       /* Handle the POSIX dollar sign which references the 1-based
    3542              :          positional argument number.  */
    3543          110 :       if (width != -1)
    3544          110 :         dollar = width + info.argidx;
    3545            0 :       else if (star_width
    3546            0 :                && TREE_CODE (star_width) == INTEGER_CST
    3547            0 :                && (TYPE_PRECISION (TREE_TYPE (star_width))
    3548            0 :                    <= TYPE_PRECISION (integer_type_node)))
    3549            0 :         dollar = width + tree_to_shwi (star_width);
    3550              : 
    3551              :       /* Bail when the numbered argument is out of range (it will
    3552              :          have already been diagnosed by -Wformat).  */
    3553          110 :       if (dollar == 0
    3554          106 :           || dollar == (int)info.argidx
    3555          214 :           || dollar > gimple_call_num_args (info.callstmt))
    3556              :         return false;
    3557              : 
    3558           96 :       --dollar;
    3559              : 
    3560           96 :       star_width = NULL_TREE;
    3561           96 :       width = -1;
    3562           96 :       ++pf;
    3563              :     }
    3564              : 
    3565       409656 :   if (dollar || !star_width)
    3566              :     {
    3567       408888 :       if (width != -1)
    3568              :         {
    3569         1128 :           if (width == 0)
    3570              :             {
    3571              :               /* The '0' that has been interpreted as a width above is
    3572              :                  actually a flag.  Reset HAVE_WIDTH, set the '0' flag,
    3573              :                  and continue processing other flags.  */
    3574          142 :               width = -1;
    3575          142 :               dir.set_flag ('0');
    3576              :             }
    3577          986 :           else if (!dollar)
    3578              :             {
    3579              :               /* (Non-zero) width has been seen.  The next character
    3580              :                  is either a period or a digit.  */
    3581          986 :               goto start_precision;
    3582              :             }
    3583              :         }
    3584              :       /* When either '$' has been seen, or width has not been seen,
    3585              :          the next field is the optional flags followed by an optional
    3586              :          width.  */
    3587       411192 :       for ( ; ; ) {
    3588       409547 :         switch (target_to_host (*pf))
    3589              :           {
    3590         1645 :           case ' ':
    3591         1645 :           case '0':
    3592         1645 :           case '+':
    3593         1645 :           case '-':
    3594         1645 :           case '#':
    3595         1645 :             dir.set_flag (target_to_host (*pf++));
    3596         1645 :             break;
    3597              : 
    3598       407902 :           default:
    3599       407902 :             goto start_width;
    3600              :           }
    3601              :       }
    3602              : 
    3603       407902 :     start_width:
    3604       407902 :       if (ISDIGIT (target_to_host (*pf)))
    3605              :         {
    3606          319 :           werange = 0;
    3607          319 :           pwidth = pf;
    3608          319 :           width = target_strtowi (&pf, &werange);
    3609              :         }
    3610       407583 :       else if (target_to_host (*pf) == '*')
    3611              :         {
    3612           56 :           if (*argno < gimple_call_num_args (info.callstmt))
    3613           56 :             star_width = gimple_call_arg (info.callstmt, (*argno)++);
    3614              :           else
    3615              :             {
    3616              :               /* This is (likely) a va_list.  It could also be an invalid
    3617              :                  call with insufficient arguments.  */
    3618            0 :               star_width = void_node;
    3619              :             }
    3620           56 :           ++pf;
    3621              :         }
    3622       407527 :       else if (target_to_host (*pf) == '\'')
    3623              :         {
    3624              :           /* The POSIX apostrophe indicating a numeric grouping
    3625              :              in the current locale.  Even though it's possible to
    3626              :              estimate the upper bound on the size of the output
    3627              :              based on the number of digits it probably isn't worth
    3628              :              continuing.  */
    3629              :           return 0;
    3630              :         }
    3631              :     }
    3632              : 
    3633          768 :  start_precision:
    3634       409622 :   if (target_to_host (*pf) == '.')
    3635              :     {
    3636         1875 :       ++pf;
    3637              : 
    3638         1875 :       if (ISDIGIT (target_to_host (*pf)))
    3639              :         {
    3640          888 :           pprec = pf;
    3641          888 :           precision = target_strtowi (&pf, &perange);
    3642              :         }
    3643          987 :       else if (target_to_host (*pf) == '*')
    3644              :         {
    3645          911 :           if (*argno < gimple_call_num_args (info.callstmt))
    3646          888 :             star_precision = gimple_call_arg (info.callstmt, (*argno)++);
    3647              :           else
    3648              :             {
    3649              :               /* This is (likely) a va_list.  It could also be an invalid
    3650              :                  call with insufficient arguments.  */
    3651           23 :               star_precision = void_node;
    3652              :             }
    3653          911 :           ++pf;
    3654              :         }
    3655              :       else
    3656              :         {
    3657              :           /* The decimal precision or the asterisk are optional.
    3658              :              When neither is specified it's taken to be zero.  */
    3659              :           precision = 0;
    3660              :         }
    3661              :     }
    3662              : 
    3663       409622 :   switch (target_to_host (*pf))
    3664              :     {
    3665         1005 :     case 'h':
    3666         1005 :       if (target_to_host (pf[1]) == 'h')
    3667              :         {
    3668          647 :           ++pf;
    3669          647 :           dir.modifier = FMT_LEN_hh;
    3670              :         }
    3671              :       else
    3672          358 :         dir.modifier = FMT_LEN_h;
    3673         1005 :       ++pf;
    3674         1005 :       break;
    3675              : 
    3676          108 :     case 'j':
    3677          108 :       dir.modifier = FMT_LEN_j;
    3678          108 :       ++pf;
    3679          108 :       break;
    3680              : 
    3681          516 :     case 'L':
    3682          516 :       dir.modifier = FMT_LEN_L;
    3683          516 :       ++pf;
    3684          516 :       break;
    3685              : 
    3686        15870 :     case 'l':
    3687        15870 :       if (target_to_host (pf[1]) == 'l')
    3688              :         {
    3689          694 :           ++pf;
    3690          694 :           dir.modifier = FMT_LEN_ll;
    3691              :         }
    3692              :       else
    3693        15176 :         dir.modifier = FMT_LEN_l;
    3694        15870 :       ++pf;
    3695        15870 :       break;
    3696              : 
    3697           49 :     case 't':
    3698           49 :       dir.modifier = FMT_LEN_t;
    3699           49 :       ++pf;
    3700           49 :       break;
    3701              : 
    3702         1863 :     case 'z':
    3703         1863 :       dir.modifier = FMT_LEN_z;
    3704         1863 :       ++pf;
    3705         1863 :       break;
    3706              :     }
    3707              : 
    3708       409622 :   switch (target_to_host (*pf))
    3709              :     {
    3710              :       /* Handle a sole '%' character the same as "%%" but since it's
    3711              :          undefined prevent the result from being folded.  */
    3712            0 :     case '\0':
    3713            0 :       --pf;
    3714            0 :       res->range.min = res->range.max = HOST_WIDE_INT_M1U;
    3715              :       /* FALLTHRU */
    3716           88 :     case '%':
    3717           88 :       dir.fmtfunc = format_percent;
    3718           88 :       break;
    3719              : 
    3720         5372 :     case 'a':
    3721         5372 :     case 'A':
    3722         5372 :     case 'e':
    3723         5372 :     case 'E':
    3724         5372 :     case 'f':
    3725         5372 :     case 'F':
    3726         5372 :     case 'g':
    3727         5372 :     case 'G':
    3728         5372 :       res->floating = true;
    3729         5372 :       dir.fmtfunc = format_floating;
    3730         5372 :       break;
    3731              : 
    3732       132143 :     case 'd':
    3733       132143 :     case 'i':
    3734       132143 :     case 'o':
    3735       132143 :     case 'u':
    3736       132143 :     case 'x':
    3737       132143 :     case 'X':
    3738       132143 :       dir.fmtfunc = format_integer;
    3739       132143 :       break;
    3740              : 
    3741           80 :     case 'b':
    3742           80 :     case 'B':
    3743           80 :       dir.fmtfunc = format_integer;
    3744           80 :       break;
    3745              : 
    3746              :     case 'p':
    3747              :       /* The %p output is implementation-defined.  It's possible
    3748              :          to determine this format but due to extensions (especially
    3749              :          those of the Linux kernel -- see bug 78512) the first %p
    3750              :          in the format string disables any further processing.  */
    3751              :       return false;
    3752              : 
    3753           77 :     case 'n':
    3754              :       /* %n has side-effects even when nothing is actually printed to
    3755              :          any buffer.  */
    3756           77 :       info.nowrite = false;
    3757           77 :       dir.fmtfunc = format_none;
    3758           77 :       break;
    3759              : 
    3760         1045 :     case 'C':
    3761         1045 :     case 'c':
    3762              :       /* POSIX wide character and C/POSIX narrow character.  */
    3763         1045 :       dir.fmtfunc = format_character;
    3764         1045 :       break;
    3765              : 
    3766       268332 :     case 'S':
    3767       268332 :     case 's':
    3768              :       /* POSIX wide string and C/POSIX narrow character string.  */
    3769       268332 :       dir.fmtfunc = format_string;
    3770       268332 :       break;
    3771              : 
    3772              :     default:
    3773              :       /* Unknown conversion specification.  */
    3774              :       return 0;
    3775              :     }
    3776              : 
    3777       407137 :   dir.specifier = target_to_host (*pf++);
    3778              : 
    3779              :   /* Store the length of the format directive.  */
    3780       407137 :   dir.len = pf - pcnt;
    3781              : 
    3782              :   /* Buffer for the directive in the host character set (used when
    3783              :      the source character set is different).  */
    3784       407137 :   char hostdir[32];
    3785              : 
    3786       407137 :   if (star_width)
    3787              :     {
    3788          802 :       if (INTEGRAL_TYPE_P (TREE_TYPE (star_width)))
    3789          783 :         dir.set_width (star_width, query);
    3790              :       else
    3791              :         {
    3792              :           /* Width specified by a va_list takes on the range [0, -INT_MIN]
    3793              :              (width is the absolute value of that specified).  */
    3794           19 :           dir.width[0] = 0;
    3795           19 :           dir.width[1] = target_int_max () + 1;
    3796              :         }
    3797              :     }
    3798              :   else
    3799              :     {
    3800       406335 :       if (width == HOST_WIDE_INT_MAX && werange)
    3801              :         {
    3802            1 :           size_t begin = dir.beg - info.fmtstr + (pwidth - pcnt);
    3803            1 :           size_t caret = begin + (werange - pcnt);
    3804            1 :           size_t end = pf - info.fmtstr - 1;
    3805              : 
    3806              :           /* Create a location for the width part of the directive,
    3807              :              pointing the caret at the first out-of-range digit.  */
    3808            1 :           substring_loc dirloc (info.fmtloc, TREE_TYPE (info.format),
    3809            1 :                                 caret, begin, end);
    3810              : 
    3811            2 :           fmtwarn (dirloc, UNKNOWN_LOCATION, NULL, info.warnopt (),
    3812            1 :                    "%<%.*s%> directive width out of range", (int) dir.len,
    3813              :                    target_to_host (hostdir, sizeof hostdir, dir.beg));
    3814              :         }
    3815              : 
    3816       406335 :       dir.set_width (width);
    3817              :     }
    3818              : 
    3819       407137 :   if (star_precision)
    3820              :     {
    3821          900 :       if (INTEGRAL_TYPE_P (TREE_TYPE (star_precision)))
    3822          872 :         dir.set_precision (star_precision, query);
    3823              :       else
    3824              :         {
    3825              :           /* Precision specified by a va_list takes on the range [-1, INT_MAX]
    3826              :              (unlike width, negative precision is ignored).  */
    3827           28 :           dir.prec[0] = -1;
    3828           28 :           dir.prec[1] = target_int_max ();
    3829              :         }
    3830              :     }
    3831              :   else
    3832              :     {
    3833       406237 :       if (precision == HOST_WIDE_INT_MAX && perange)
    3834              :         {
    3835            1 :           size_t begin = dir.beg - info.fmtstr + (pprec - pcnt) - 1;
    3836            1 :           size_t caret = dir.beg - info.fmtstr + (perange - pcnt) - 1;
    3837            1 :           size_t end = pf - info.fmtstr - 2;
    3838              : 
    3839              :           /* Create a location for the precision part of the directive,
    3840              :              including the leading period, pointing the caret at the first
    3841              :              out-of-range digit .  */
    3842            1 :           substring_loc dirloc (info.fmtloc, TREE_TYPE (info.format),
    3843            1 :                                 caret, begin, end);
    3844              : 
    3845            2 :           fmtwarn (dirloc, UNKNOWN_LOCATION, NULL, info.warnopt (),
    3846            1 :                    "%<%.*s%> directive precision out of range", (int) dir.len,
    3847              :                    target_to_host (hostdir, sizeof hostdir, dir.beg));
    3848              :         }
    3849              : 
    3850       406237 :       dir.set_precision (precision);
    3851              :     }
    3852              : 
    3853              :   /* Extract the argument if the directive takes one and if it's
    3854              :      available (e.g., the function doesn't take a va_list).  Treat
    3855              :      missing arguments the same as va_list, even though they will
    3856              :      have likely already been diagnosed by -Wformat.  */
    3857       407137 :   if (dir.specifier != '%'
    3858       407137 :       && *argno < gimple_call_num_args (info.callstmt))
    3859       405850 :     dir.arg = gimple_call_arg (info.callstmt, dollar ? dollar : (*argno)++);
    3860              : 
    3861       407137 :   if (dump_file)
    3862              :     {
    3863            0 :       fprintf (dump_file,
    3864              :                "  Directive %u at offset " HOST_WIDE_INT_PRINT_UNSIGNED
    3865              :                ": \"%.*s\"",
    3866              :                dir.dirno,
    3867            0 :                (unsigned HOST_WIDE_INT)(size_t)(dir.beg - info.fmtstr),
    3868            0 :                (int)dir.len, dir.beg);
    3869            0 :       if (star_width)
    3870              :         {
    3871            0 :           if (dir.width[0] == dir.width[1])
    3872            0 :             fprintf (dump_file, ", width = " HOST_WIDE_INT_PRINT_DEC,
    3873              :                      dir.width[0]);
    3874              :           else
    3875            0 :             fprintf (dump_file,
    3876              :                      ", width in range [" HOST_WIDE_INT_PRINT_DEC
    3877              :                      ", " HOST_WIDE_INT_PRINT_DEC "]",
    3878              :                      dir.width[0], dir.width[1]);
    3879              :         }
    3880              : 
    3881            0 :       if (star_precision)
    3882              :         {
    3883            0 :           if (dir.prec[0] == dir.prec[1])
    3884            0 :             fprintf (dump_file, ", precision = " HOST_WIDE_INT_PRINT_DEC,
    3885              :                      dir.prec[0]);
    3886              :           else
    3887            0 :             fprintf (dump_file,
    3888              :                      ", precision in range [" HOST_WIDE_INT_PRINT_DEC
    3889              :                      HOST_WIDE_INT_PRINT_DEC "]",
    3890              :                      dir.prec[0], dir.prec[1]);
    3891              :         }
    3892            0 :       fputc ('\n', dump_file);
    3893              :     }
    3894              : 
    3895       407137 :   return dir.len;
    3896              : }
    3897              : 
    3898              : /* Diagnose overlap between destination and %s directive arguments.  */
    3899              : 
    3900              : static void
    3901       134768 : maybe_warn_overlap (call_info &info, format_result *res)
    3902              : {
    3903              :   /* Two vectors of 1-based indices corresponding to either certainly
    3904              :      or possibly aliasing arguments.  */
    3905       673840 :   auto_vec<int, 16> aliasarg[2];
    3906              : 
    3907              :   /* Go through the array of potentially aliasing directives and collect
    3908              :      argument numbers of those that do or may overlap the destination
    3909              :      object given the full result.  */
    3910       135030 :   for (unsigned i = 0; i != res->alias_count; ++i)
    3911              :     {
    3912          262 :       const format_result::alias_info &alias = res->aliases[i];
    3913              : 
    3914          262 :       enum { possible = -1, none = 0, certain = 1 } overlap = none;
    3915              : 
    3916              :       /* If the precision is zero there is no overlap.  (This only
    3917              :          considers %s directives and ignores %n.)  */
    3918          262 :       if (alias.dir.prec[0] == 0 && alias.dir.prec[1] == 0)
    3919            6 :         continue;
    3920              : 
    3921          256 :       if (alias.offset == HOST_WIDE_INT_MAX
    3922          200 :           || info.dst_offset == HOST_WIDE_INT_MAX)
    3923              :         overlap = possible;
    3924          182 :       else if (alias.offset == info.dst_offset)
    3925           79 :         overlap = alias.dir.prec[0] == 0 ? possible : certain;
    3926              :       else
    3927              :         {
    3928              :           /* Determine overlap from the range of output and offsets
    3929              :              into the same destination as the source, and rule out
    3930              :              impossible overlap.  */
    3931          103 :           unsigned HOST_WIDE_INT albeg = alias.offset;
    3932          103 :           unsigned HOST_WIDE_INT dstbeg = info.dst_offset;
    3933              : 
    3934          103 :           unsigned HOST_WIDE_INT alend = albeg + alias.range.min;
    3935          103 :           unsigned HOST_WIDE_INT dstend = dstbeg + res->range.min - 1;
    3936              : 
    3937          103 :           if ((albeg <= dstbeg && alend > dstbeg)
    3938           99 :               || (albeg >= dstbeg && albeg < dstend))
    3939              :             overlap = certain;
    3940              :           else
    3941              :             {
    3942           95 :               alend = albeg + alias.range.max;
    3943           95 :               if (alend < albeg)
    3944           13 :                 alend = HOST_WIDE_INT_M1U;
    3945              : 
    3946           95 :               dstend = dstbeg + res->range.max - 1;
    3947           95 :               if (dstend < dstbeg)
    3948            4 :                 dstend = HOST_WIDE_INT_M1U;
    3949              : 
    3950           95 :               if ((albeg >= dstbeg && albeg <= dstend)
    3951           56 :                   || (alend >= dstbeg && alend <= dstend))
    3952              :                 overlap = possible;
    3953              :             }
    3954              :         }
    3955              : 
    3956           20 :       if (overlap == none)
    3957           20 :         continue;
    3958              : 
    3959              :       /* Append the 1-based argument number.  */
    3960          236 :       aliasarg[overlap != certain].safe_push (alias.dir.argno + 1);
    3961              : 
    3962              :       /* Disable any kind of optimization.  */
    3963          236 :       res->range.unlikely = HOST_WIDE_INT_M1U;
    3964              :     }
    3965              : 
    3966       134768 :   tree arg0 = gimple_call_arg (info.callstmt, 0);
    3967       134768 :   location_t loc = gimple_location (info.callstmt);
    3968              : 
    3969       134768 :   bool aliaswarn = false;
    3970              : 
    3971       134768 :   unsigned ncertain = aliasarg[0].length ();
    3972       134768 :   unsigned npossible = aliasarg[1].length ();
    3973       134768 :   if (ncertain && npossible)
    3974              :     {
    3975              :       /* If there are multiple arguments that overlap, some certainly
    3976              :          and some possibly, handle both sets in a single diagnostic.  */
    3977            1 :       aliaswarn
    3978            3 :         = warning_at (loc, OPT_Wrestrict,
    3979              :                       "%qE arguments %Z and maybe %Z overlap destination "
    3980              :                       "object %qE",
    3981              :                       info.func, aliasarg[0].address (), ncertain,
    3982              :                       aliasarg[1].address (), npossible,
    3983              :                       info.dst_origin);
    3984              :     }
    3985       134767 :   else if (ncertain)
    3986              :     {
    3987              :       /* There is only one set of two or more arguments and they all
    3988              :          certainly overlap the destination.  */
    3989           84 :       aliaswarn
    3990          168 :         = warning_n (loc, OPT_Wrestrict, ncertain,
    3991              :                      "%qE argument %Z overlaps destination object %qE",
    3992              :                      "%qE arguments %Z overlap destination object %qE",
    3993              :                      info.func, aliasarg[0].address (), ncertain,
    3994              :                      info.dst_origin);
    3995              :     }
    3996       134683 :   else if (npossible)
    3997              :     {
    3998              :       /* There is only one set of two or more arguments and they all
    3999              :          may overlap (but need not).  */
    4000          148 :       aliaswarn
    4001          296 :         = warning_n (loc, OPT_Wrestrict, npossible,
    4002              :                      "%qE argument %Z may overlap destination object %qE",
    4003              :                      "%qE arguments %Z may overlap destination object %qE",
    4004              :                      info.func, aliasarg[1].address (), npossible,
    4005              :                      info.dst_origin);
    4006              :     }
    4007              : 
    4008          233 :   if (aliaswarn)
    4009              :     {
    4010          233 :       res->warned = true;
    4011              : 
    4012          233 :       if (info.dst_origin != arg0)
    4013              :         {
    4014              :           /* If its location is different from the first argument of the call
    4015              :              point either at the destination object itself or at the expression
    4016              :              that was used to determine the overlap.  */
    4017          221 :           loc = (DECL_P (info.dst_origin)
    4018          233 :                  ? DECL_SOURCE_LOCATION (info.dst_origin)
    4019           12 :                  : EXPR_LOCATION (info.dst_origin));
    4020          221 :           if (loc != UNKNOWN_LOCATION)
    4021          221 :             inform (loc,
    4022              :                     "destination object referenced by %<restrict%>-qualified "
    4023              :                     "argument 1 was declared here");
    4024              :         }
    4025              :     }
    4026       404304 : }
    4027              : 
    4028              : /* Compute the length of the output resulting from the call to a formatted
    4029              :    output function described by INFO and store the result of the call in
    4030              :    *RES.  Issue warnings for detected past the end writes.  Return true
    4031              :    if the complete format string has been processed and *RES can be relied
    4032              :    on, false otherwise (e.g., when a unknown or unhandled directive was seen
    4033              :    that caused the processing to be terminated early).  */
    4034              : 
    4035              : static bool
    4036       137471 : compute_format_length (call_info &info, format_result *res,
    4037              :                        pointer_query &ptr_qry)
    4038              : {
    4039       137471 :   if (dump_file)
    4040              :     {
    4041            0 :       location_t callloc = gimple_location (info.callstmt);
    4042            0 :       fprintf (dump_file, "%s:%i: ",
    4043            0 :                LOCATION_FILE (callloc), LOCATION_LINE (callloc));
    4044            0 :       print_generic_expr (dump_file, info.func, dump_flags);
    4045              : 
    4046            0 :       fprintf (dump_file,
    4047              :                ": objsize = " HOST_WIDE_INT_PRINT_UNSIGNED
    4048              :                ", fmtstr = \"%s\"\n",
    4049              :                info.objsize, info.fmtstr);
    4050              :     }
    4051              : 
    4052              :   /* Reset the minimum and maximum byte counters.  */
    4053       137471 :   res->range.min = res->range.max = 0;
    4054              : 
    4055              :   /* No directive has been seen yet so the length of output is bounded
    4056              :      by the known range [0, 0] (with no conversion resulting in a failure
    4057              :      or producing more than 4K bytes) until determined otherwise.  */
    4058       137471 :   res->knownrange = true;
    4059       137471 :   res->floating = false;
    4060       137471 :   res->warned = false;
    4061              : 
    4062              :   /* 1-based directive counter.  */
    4063       137471 :   unsigned dirno = 1;
    4064              : 
    4065              :   /* The variadic argument counter.  */
    4066       137471 :   unsigned argno = info.argidx;
    4067              : 
    4068       137471 :   bool success = true;
    4069              : 
    4070       137471 :   for (const char *pf = info.fmtstr; ; ++dirno)
    4071              :     {
    4072       966970 :       directive dir (&info, dirno);
    4073              : 
    4074       966970 :       size_t n = parse_directive (info, dir, res, pf, &argno, ptr_qry.rvals);
    4075              : 
    4076              :       /* Return failure if the format function fails.  */
    4077       966970 :       if (!format_directive (info, res, dir, ptr_qry))
    4078         2703 :         return false;
    4079              : 
    4080              :       /* Return success when the directive is zero bytes long and it's
    4081              :          the last thing in the format string (i.e., it's the terminating
    4082              :          nul, which isn't really a directive but handling it as one makes
    4083              :          things simpler).  */
    4084       964267 :       if (!n)
    4085              :         {
    4086       134768 :           success = *pf == '\0';
    4087       134768 :           break;
    4088              :         }
    4089              : 
    4090       829499 :       pf += n;
    4091       829499 :     }
    4092              : 
    4093       134768 :   maybe_warn_overlap (info, res);
    4094              : 
    4095              :   /* The complete format string was processed (with or without warnings).  */
    4096       134768 :   return success;
    4097              : }
    4098              : 
    4099              : /* Return the size of the object referenced by the expression DEST in
    4100              :    statement STMT, if available, or the maximum possible size otherwise.  */
    4101              : 
    4102              : static unsigned HOST_WIDE_INT
    4103       138768 : get_destination_size (tree dest, gimple *stmt, pointer_query &ptr_qry)
    4104              : {
    4105              :   /* When there is no destination return the maximum.  */
    4106       138768 :   if (!dest)
    4107              :     return HOST_WIDE_INT_MAX;
    4108              : 
    4109              :   /* Use compute_objsize to determine the size of the destination object.  */
    4110         8538 :   access_ref aref;
    4111         8538 :   if (!ptr_qry.get_ref (dest, stmt, &aref))
    4112              :     return HOST_WIDE_INT_MAX;
    4113              : 
    4114         8538 :   offset_int remsize = aref.size_remaining ();
    4115         8538 :   if (!wi::fits_uhwi_p (remsize))
    4116              :     return HOST_WIDE_INT_MAX;
    4117              : 
    4118         8538 :   return remsize.to_uhwi ();
    4119              : }
    4120              : 
    4121              : /* Return true if the call described by INFO with result RES safe to
    4122              :    optimize (i.e., no undefined behavior), and set RETVAL to the range
    4123              :    of its return values.  */
    4124              : 
    4125              : static bool
    4126       253974 : is_call_safe (const call_info &info,
    4127              :               const format_result &res, bool under4k,
    4128              :               unsigned HOST_WIDE_INT retval[2])
    4129              : {
    4130       253974 :   if (under4k && !res.posunder4k)
    4131              :     return false;
    4132              : 
    4133              :   /* The minimum return value.  */
    4134       129554 :   retval[0] = res.range.min;
    4135              : 
    4136              :   /* The maximum return value is in most cases bounded by RES.RANGE.MAX
    4137              :      but in cases involving multibyte characters could be as large as
    4138              :      RES.RANGE.UNLIKELY.  */
    4139       129554 :   retval[1]
    4140       129554 :     = res.range.unlikely < res.range.max ? res.range.max : res.range.unlikely;
    4141              : 
    4142              :   /* Adjust the number of bytes which includes the terminating nul
    4143              :      to reflect the return value of the function which does not.
    4144              :      Because the valid range of the function is [INT_MIN, INT_MAX],
    4145              :      a valid range before the adjustment below is [0, INT_MAX + 1]
    4146              :      (the functions only return negative values on error or undefined
    4147              :      behavior).  */
    4148       129554 :   if (retval[0] <= target_int_max () + 1)
    4149       129424 :     --retval[0];
    4150       129554 :   if (retval[1] <= target_int_max () + 1)
    4151       115367 :     --retval[1];
    4152              : 
    4153              :   /* Avoid the return value optimization when the behavior of the call
    4154              :      is undefined either because any directive may have produced 4K or
    4155              :      more of output, or the return value exceeds INT_MAX, or because
    4156              :      the output overflows the destination object (but leave it enabled
    4157              :      when the function is bounded because then the behavior is well-
    4158              :      defined).  */
    4159       129554 :   if (retval[0] == retval[1]
    4160        93935 :       && (info.bounded || retval[0] < info.objsize)
    4161       223003 :       && retval[0] <= target_int_max ())
    4162              :     return true;
    4163              : 
    4164        34368 :   if ((info.bounded || retval[1] < info.objsize)
    4165        55525 :       && (retval[0] < target_int_max ()
    4166        21058 :           && retval[1] < target_int_max ()))
    4167              :     return true;
    4168              : 
    4169        16212 :   if (!under4k && (info.bounded || retval[0] < info.objsize))
    4170              :     return true;
    4171              : 
    4172              :   return false;
    4173              : }
    4174              : 
    4175              : /* Given a suitable result RES of a call to a formatted output function
    4176              :    described by INFO, substitute the result for the return value of
    4177              :    the call.  The result is suitable if the number of bytes it represents
    4178              :    is known and exact.  A result that isn't suitable for substitution may
    4179              :    have its range set to the range of return values, if that is known.
    4180              :    Return true if the call is removed and gsi_next should not be performed
    4181              :    in the caller.  */
    4182              : 
    4183              : static bool
    4184       126983 : try_substitute_return_value (gimple_stmt_iterator *gsi,
    4185              :                              const call_info &info,
    4186              :                              const format_result &res)
    4187              : {
    4188       126983 :   tree lhs = gimple_get_lhs (info.callstmt);
    4189              : 
    4190              :   /* Set to true when the entire call has been removed.  */
    4191       126983 :   bool removed = false;
    4192              : 
    4193              :   /* The minimum and maximum return value.  */
    4194       126983 :   unsigned HOST_WIDE_INT retval[2] = {0};
    4195       126983 :   bool safe = is_call_safe (info, res, true, retval);
    4196              : 
    4197       126983 :   if (safe
    4198         2294 :       && retval[0] == retval[1]
    4199              :       /* Not prepared to handle possibly throwing calls here; they shouldn't
    4200              :          appear in non-artificial testcases, except when the __*_chk routines
    4201              :          are badly declared.  */
    4202       128075 :       && !stmt_ends_bb_p (info.callstmt))
    4203              :     {
    4204         1062 :       tree cst = build_int_cst (lhs ? TREE_TYPE (lhs) : integer_type_node,
    4205         1062 :                                 retval[0]);
    4206              : 
    4207         1062 :       if (lhs == NULL_TREE && info.nowrite)
    4208              :         {
    4209              :           /* Remove the call to the bounded function with a zero size
    4210              :              (e.g., snprintf(0, 0, "%i", 123)) if there is no lhs.  */
    4211           13 :           unlink_stmt_vdef (info.callstmt);
    4212           13 :           gsi_remove (gsi, true);
    4213           13 :           removed = true;
    4214              :         }
    4215         1049 :       else if (info.nowrite)
    4216              :         {
    4217              :           /* Replace the call to the bounded function with a zero size
    4218              :              (e.g., snprintf(0, 0, "%i", 123) with the constant result
    4219              :              of the function.  */
    4220          167 :           gimplify_and_update_call_from_tree (gsi, cst);
    4221          167 :           gimple *callstmt = gsi_stmt (*gsi);
    4222          167 :           update_stmt (callstmt);
    4223              :         }
    4224          882 :       else if (lhs)
    4225              :         {
    4226              :           /* Replace the left-hand side of the call with the constant
    4227              :              result of the formatted function.  */
    4228          354 :           gimple_call_set_lhs (info.callstmt, NULL_TREE);
    4229          354 :           gimple *g = gimple_build_assign (lhs, cst);
    4230          354 :           gsi_insert_after (gsi, g, GSI_NEW_STMT);
    4231          354 :           update_stmt (info.callstmt);
    4232              :         }
    4233              : 
    4234         1062 :       if (dump_file)
    4235              :         {
    4236            0 :           if (removed)
    4237            0 :             fprintf (dump_file, "  Removing call statement.");
    4238              :           else
    4239              :             {
    4240            0 :               fprintf (dump_file, "  Substituting ");
    4241            0 :               print_generic_expr (dump_file, cst, dump_flags);
    4242            0 :               fprintf (dump_file, " for %s.\n",
    4243            0 :                        info.nowrite ? "statement" : "return value");
    4244              :             }
    4245              :         }
    4246              :     }
    4247       125921 :   else if (lhs && types_compatible_p (TREE_TYPE (lhs), integer_type_node))
    4248              :     {
    4249         2439 :       bool setrange = false;
    4250              : 
    4251         2439 :       if (safe
    4252          501 :           && (info.bounded || retval[1] < info.objsize)
    4253         2940 :           && (retval[0] < target_int_max ()
    4254          501 :               && retval[1] < target_int_max ()))
    4255              :         {
    4256              :           /* If the result is in a valid range bounded by the size of
    4257              :              the destination set it so that it can be used for subsequent
    4258              :              optimizations.  */
    4259          501 :           int prec = TYPE_PRECISION (integer_type_node);
    4260              : 
    4261          501 :           wide_int min = wi::shwi (retval[0], prec);
    4262          501 :           wide_int max = wi::shwi (retval[1], prec);
    4263          501 :           int_range_max r (TREE_TYPE (lhs), min, max);
    4264          501 :           set_range_info (lhs, r);
    4265              : 
    4266          501 :           setrange = true;
    4267          501 :         }
    4268              : 
    4269         2439 :       if (dump_file)
    4270              :         {
    4271            0 :           const char *inbounds
    4272            0 :             = (retval[0] < info.objsize
    4273            0 :                ? (retval[1] < info.objsize
    4274            0 :                   ? "in" : "potentially out-of")
    4275              :                : "out-of");
    4276              : 
    4277            0 :           const char *what = setrange ? "Setting" : "Discarding";
    4278            0 :           if (retval[0] != retval[1])
    4279            0 :             fprintf (dump_file,
    4280              :                      "  %s %s-bounds return value range ["
    4281              :                      HOST_WIDE_INT_PRINT_UNSIGNED ", "
    4282              :                      HOST_WIDE_INT_PRINT_UNSIGNED "].\n",
    4283              :                      what, inbounds, retval[0], retval[1]);
    4284              :           else
    4285            0 :             fprintf (dump_file, "  %s %s-bounds return value "
    4286              :                      HOST_WIDE_INT_PRINT_UNSIGNED ".\n",
    4287              :                      what, inbounds, retval[0]);
    4288              :         }
    4289              :     }
    4290              : 
    4291       126983 :   if (dump_file)
    4292            0 :     fputc ('\n', dump_file);
    4293              : 
    4294       126983 :   return removed;
    4295              : }
    4296              : 
    4297              : /* Try to simplify a s{,n}printf call described by INFO with result
    4298              :    RES by replacing it with a simpler and presumably more efficient
    4299              :    call (such as strcpy).  */
    4300              : 
    4301              : static bool
    4302       126991 : try_simplify_call (gimple_stmt_iterator *gsi,
    4303              :                    const call_info &info,
    4304              :                    const format_result &res)
    4305              : {
    4306       126991 :   unsigned HOST_WIDE_INT dummy[2];
    4307       126991 :   if (!is_call_safe (info, res, info.retval_used (), dummy))
    4308              :     return false;
    4309              : 
    4310       124358 :   switch (info.fncode)
    4311              :     {
    4312         1605 :     case BUILT_IN_SNPRINTF:
    4313         1605 :       return gimple_fold_builtin_snprintf (gsi);
    4314              : 
    4315         2278 :     case BUILT_IN_SPRINTF:
    4316         2278 :       return gimple_fold_builtin_sprintf (gsi);
    4317              : 
    4318              :     default:
    4319              :       ;
    4320              :     }
    4321              : 
    4322              :   return false;
    4323              : }
    4324              : 
    4325              : /* Return the zero-based index of the format string argument of a printf
    4326              :    like function and set *IDX_ARGS to the first format argument.  When
    4327              :    no such index exists return UINT_MAX.  */
    4328              : 
    4329              : static unsigned
    4330      3761353 : get_user_idx_format (tree fndecl, unsigned *idx_args)
    4331              : {
    4332      3761353 :   tree attrs = lookup_attribute ("format", DECL_ATTRIBUTES (fndecl));
    4333      3761353 :   if (!attrs)
    4334      3761353 :     attrs = lookup_attribute ("format", TYPE_ATTRIBUTES (TREE_TYPE (fndecl)));
    4335              : 
    4336      3761353 :   if (!attrs)
    4337              :     return UINT_MAX;
    4338              : 
    4339        20631 :   attrs = TREE_VALUE (attrs);
    4340              : 
    4341        20631 :   tree archetype = TREE_VALUE (attrs);
    4342        20631 :   if (strcmp ("printf", IDENTIFIER_POINTER (archetype)))
    4343              :     return UINT_MAX;
    4344              : 
    4345        16753 :   attrs = TREE_CHAIN (attrs);
    4346        16753 :   tree fmtarg = TREE_VALUE (attrs);
    4347              : 
    4348        16753 :   attrs = TREE_CHAIN (attrs);
    4349        16753 :   tree elliparg = TREE_VALUE (attrs);
    4350              : 
    4351              :   /* Attribute argument indices are 1-based but we use zero-based.  */
    4352        16753 :   *idx_args = tree_to_uhwi (elliparg) - 1;
    4353        16753 :   return tree_to_uhwi (fmtarg) - 1;
    4354              : }
    4355              : 
    4356              : }   /* Unnamed namespace.  */
    4357              : 
    4358              : /* Determine if a GIMPLE call at *GSI is to one of the sprintf-like built-in
    4359              :    functions and if so, handle it.  Return true if the call is removed and
    4360              :    gsi_next should not be performed in the caller.  */
    4361              : 
    4362              : bool
    4363      4891677 : handle_printf_call (gimple_stmt_iterator *gsi, pointer_query &ptr_qry)
    4364              : {
    4365      4891677 :   init_target_to_host_charmap ();
    4366              : 
    4367      4891677 :   call_info info = call_info ();
    4368              : 
    4369      4891677 :   info.callstmt = gsi_stmt (*gsi);
    4370      4891677 :   info.func = gimple_call_fndecl (info.callstmt);
    4371      4891677 :   if (!info.func)
    4372              :     return false;
    4373              : 
    4374              :   /* Format string argument number (valid for all functions).  */
    4375      4709390 :   unsigned idx_format = UINT_MAX;
    4376      4709390 :   if (gimple_call_builtin_p (info.callstmt, BUILT_IN_NORMAL))
    4377       948037 :     info.fncode = DECL_FUNCTION_CODE (info.func);
    4378              :   else
    4379              :     {
    4380      3761353 :       unsigned idx_args;
    4381      3761353 :       idx_format = get_user_idx_format (info.func, &idx_args);
    4382      3761353 :       if (idx_format == UINT_MAX
    4383        16753 :           || idx_format >= gimple_call_num_args (info.callstmt)
    4384        16753 :           || idx_args > gimple_call_num_args (info.callstmt)
    4385      3778078 :           || !POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (info.callstmt,
    4386              :                                                           idx_format))))
    4387      3744628 :         return false;
    4388        16725 :       info.fncode = BUILT_IN_NONE;
    4389        16725 :       info.argidx = idx_args;
    4390              :     }
    4391              : 
    4392              :   /* The size of the destination as in snprintf(dest, size, ...).  */
    4393       964762 :   unsigned HOST_WIDE_INT dstsize = HOST_WIDE_INT_M1U;
    4394              : 
    4395              :   /* The size of the destination determined by __builtin_object_size.  */
    4396       964762 :   unsigned HOST_WIDE_INT objsize = HOST_WIDE_INT_M1U;
    4397              : 
    4398              :   /* Zero-based buffer size argument number (snprintf and vsnprintf).  */
    4399       964762 :   unsigned idx_dstsize = UINT_MAX;
    4400              : 
    4401              :   /* Object size argument number (snprintf_chk and vsnprintf_chk).  */
    4402       964762 :   unsigned idx_objsize = UINT_MAX;
    4403              : 
    4404              :   /* Destinaton argument number (valid for sprintf functions only).  */
    4405       964762 :   unsigned idx_dstptr = 0;
    4406              : 
    4407       964762 :   switch (info.fncode)
    4408              :     {
    4409              :     case BUILT_IN_NONE:
    4410              :       // User-defined function with attribute format (printf).
    4411              :       idx_dstptr = -1;
    4412              :       break;
    4413              : 
    4414        86054 :     case BUILT_IN_FPRINTF:
    4415              :       // Signature:
    4416              :       //   __builtin_fprintf (FILE*, format, ...)
    4417        86054 :       idx_format = 1;
    4418        86054 :       info.argidx = 2;
    4419        86054 :       idx_dstptr = -1;
    4420        86054 :       break;
    4421              : 
    4422          147 :     case BUILT_IN_FPRINTF_CHK:
    4423              :       // Signature:
    4424              :       //   __builtin_fprintf_chk (FILE*, ost, format, ...)
    4425          147 :       idx_format = 2;
    4426          147 :       info.argidx = 3;
    4427          147 :       idx_dstptr = -1;
    4428          147 :       break;
    4429              : 
    4430           64 :     case BUILT_IN_FPRINTF_UNLOCKED:
    4431              :       // Signature:
    4432              :       //   __builtin_fprintf_unnlocked (FILE*, format, ...)
    4433           64 :       idx_format = 1;
    4434           64 :       info.argidx = 2;
    4435           64 :       idx_dstptr = -1;
    4436           64 :       break;
    4437              : 
    4438        26307 :     case BUILT_IN_PRINTF:
    4439              :       // Signature:
    4440              :       //   __builtin_printf (format, ...)
    4441        26307 :       idx_format = 0;
    4442        26307 :       info.argidx = 1;
    4443        26307 :       idx_dstptr = -1;
    4444        26307 :       break;
    4445              : 
    4446          151 :     case BUILT_IN_PRINTF_CHK:
    4447              :       // Signature:
    4448              :       //   __builtin_printf_chk (ost, format, ...)
    4449          151 :       idx_format = 1;
    4450          151 :       info.argidx = 2;
    4451          151 :       idx_dstptr = -1;
    4452          151 :       break;
    4453              : 
    4454           63 :     case BUILT_IN_PRINTF_UNLOCKED:
    4455              :       // Signature:
    4456              :       //   __builtin_printf (format, ...)
    4457           63 :       idx_format = 0;
    4458           63 :       info.argidx = 1;
    4459           63 :       idx_dstptr = -1;
    4460           63 :       break;
    4461              : 
    4462         4172 :     case BUILT_IN_SPRINTF:
    4463              :       // Signature:
    4464              :       //   __builtin_sprintf (dst, format, ...)
    4465         4172 :       idx_format = 1;
    4466         4172 :       info.argidx = 2;
    4467         4172 :       break;
    4468              : 
    4469         1117 :     case BUILT_IN_SPRINTF_CHK:
    4470              :       // Signature:
    4471              :       //   __builtin___sprintf_chk (dst, ost, objsize, format, ...)
    4472         1117 :       idx_objsize = 2;
    4473         1117 :       idx_format = 3;
    4474         1117 :       info.argidx = 4;
    4475         1117 :       break;
    4476              : 
    4477         2197 :     case BUILT_IN_SNPRINTF:
    4478              :       // Signature:
    4479              :       //   __builtin_snprintf (dst, size, format, ...)
    4480         2197 :       idx_dstsize = 1;
    4481         2197 :       idx_format = 2;
    4482         2197 :       info.argidx = 3;
    4483         2197 :       info.bounded = true;
    4484         2197 :       break;
    4485              : 
    4486          139 :     case BUILT_IN_SNPRINTF_CHK:
    4487              :       // Signature:
    4488              :       //   __builtin___snprintf_chk (dst, size, ost, objsize, format, ...)
    4489          139 :       idx_dstsize = 1;
    4490          139 :       idx_objsize = 3;
    4491          139 :       idx_format = 4;
    4492          139 :       info.argidx = 5;
    4493          139 :       info.bounded = true;
    4494          139 :       break;
    4495              : 
    4496          375 :     case BUILT_IN_VFPRINTF:
    4497              :       // Signature:
    4498              :       //   __builtin_vprintf (FILE*, format, va_list)
    4499          375 :       idx_format = 1;
    4500          375 :       info.argidx = -1;
    4501          375 :       idx_dstptr = -1;
    4502          375 :       break;
    4503              : 
    4504          139 :     case BUILT_IN_VFPRINTF_CHK:
    4505              :       // Signature:
    4506              :       //   __builtin___vfprintf_chk (FILE*, ost, format, va_list)
    4507          139 :       idx_format = 2;
    4508          139 :       info.argidx = -1;
    4509          139 :       idx_dstptr = -1;
    4510          139 :       break;
    4511              : 
    4512           58 :     case BUILT_IN_VPRINTF:
    4513              :       // Signature:
    4514              :       //   __builtin_vprintf (format, va_list)
    4515           58 :       idx_format = 0;
    4516           58 :       info.argidx = -1;
    4517           58 :       idx_dstptr = -1;
    4518           58 :       break;
    4519              : 
    4520          147 :     case BUILT_IN_VPRINTF_CHK:
    4521              :       // Signature:
    4522              :       //   __builtin___vprintf_chk (ost, format, va_list)
    4523          147 :       idx_format = 1;
    4524          147 :       info.argidx = -1;
    4525          147 :       idx_dstptr = -1;
    4526          147 :       break;
    4527              : 
    4528         1631 :     case BUILT_IN_VSNPRINTF:
    4529              :       // Signature:
    4530              :       //   __builtin_vsprintf (dst, size, format, va)
    4531         1631 :       idx_dstsize = 1;
    4532         1631 :       idx_format = 2;
    4533         1631 :       info.argidx = -1;
    4534         1631 :       info.bounded = true;
    4535         1631 :       break;
    4536              : 
    4537          131 :     case BUILT_IN_VSNPRINTF_CHK:
    4538              :       // Signature:
    4539              :       //   __builtin___vsnprintf_chk (dst, size, ost, objsize, format, va)
    4540          131 :       idx_dstsize = 1;
    4541          131 :       idx_objsize = 3;
    4542          131 :       idx_format = 4;
    4543          131 :       info.argidx = -1;
    4544          131 :       info.bounded = true;
    4545          131 :       break;
    4546              : 
    4547         3071 :     case BUILT_IN_VSPRINTF:
    4548              :       // Signature:
    4549              :       //   __builtin_vsprintf (dst, format, va)
    4550         3071 :       idx_format = 1;
    4551         3071 :       info.argidx = -1;
    4552         3071 :       break;
    4553              : 
    4554          178 :     case BUILT_IN_VSPRINTF_CHK:
    4555              :       // Signature:
    4556              :       //   __builtin___vsprintf_chk (dst, ost, objsize, format, va)
    4557          178 :       idx_format = 3;
    4558          178 :       idx_objsize = 2;
    4559          178 :       info.argidx = -1;
    4560          178 :       break;
    4561              : 
    4562              :     default:
    4563              :       return false;
    4564              :     }
    4565              : 
    4566              :   /* Set the global warning level for this function.  */
    4567       142866 :   warn_level = info.bounded ? warn_format_trunc : warn_format_overflow;
    4568              : 
    4569              :   /* For all string functions the first argument is a pointer to
    4570              :      the destination.  */
    4571       142866 :   tree dstptr = (idx_dstptr < gimple_call_num_args (info.callstmt)
    4572       142866 :                  ? gimple_call_arg (info.callstmt, 0) : NULL_TREE);
    4573              : 
    4574       142866 :   info.format = gimple_call_arg (info.callstmt, idx_format);
    4575              : 
    4576              :   /* True when the destination size is constant as opposed to the lower
    4577              :      or upper bound of a range.  */
    4578       142866 :   bool dstsize_cst_p = true;
    4579       142866 :   bool posunder4k = true;
    4580              : 
    4581       142866 :   if (idx_dstsize == UINT_MAX)
    4582              :     {
    4583              :       /* For non-bounded functions like sprintf, determine the size
    4584              :          of the destination from the object or pointer passed to it
    4585              :          as the first argument.  */
    4586       138768 :       dstsize = get_destination_size (dstptr, info.callstmt, ptr_qry);
    4587              :     }
    4588         4098 :   else if (tree size = gimple_call_arg (info.callstmt, idx_dstsize))
    4589              :     {
    4590              :       /* For bounded functions try to get the size argument.  */
    4591              : 
    4592         4098 :       if (TREE_CODE (size) == INTEGER_CST)
    4593              :         {
    4594         3471 :           dstsize = tree_to_uhwi (size);
    4595              :           /* No object can be larger than SIZE_MAX bytes (half the address
    4596              :              space) on the target.
    4597              :              The functions are defined only for output of at most INT_MAX
    4598              :              bytes.  Specifying a bound in excess of that limit effectively
    4599              :              defeats the bounds checking (and on some implementations such
    4600              :              as Solaris cause the function to fail with EINVAL).  */
    4601         3471 :           if (dstsize > target_size_max () / 2)
    4602              :             {
    4603              :               /* Avoid warning if -Wstringop-overflow is specified since
    4604              :                  it also warns for the same thing though only for the
    4605              :                  checking built-ins.  */
    4606           10 :               if ((idx_objsize == UINT_MAX
    4607            1 :                    || !warn_stringop_overflow))
    4608            9 :                 warning_at (gimple_location (info.callstmt), info.warnopt (),
    4609              :                             "specified bound %wu exceeds maximum object size "
    4610              :                             "%wu",
    4611              :                             dstsize, target_size_max () / 2);
    4612              :               /* POSIX requires snprintf to fail if DSTSIZE is greater
    4613              :                  than INT_MAX.  Even though not all POSIX implementations
    4614              :                  conform to the requirement, avoid folding in this case.  */
    4615              :               posunder4k = false;
    4616              :             }
    4617         3461 :           else if (dstsize > target_int_max ())
    4618              :             {
    4619           16 :               warning_at (gimple_location (info.callstmt), info.warnopt (),
    4620              :                           "specified bound %wu exceeds %<INT_MAX%>",
    4621              :                           dstsize);
    4622              :               /* POSIX requires snprintf to fail if DSTSIZE is greater
    4623              :                  than INT_MAX.  Avoid folding in that case.  */
    4624           16 :               posunder4k = false;
    4625              :             }
    4626              :         }
    4627          627 :       else if (TREE_CODE (size) == SSA_NAME)
    4628              :         {
    4629              :           /* Try to determine the range of values of the argument
    4630              :              and use the greater of the two at level 1 and the smaller
    4631              :              of them at level 2.  */
    4632          627 :           int_range_max vr;
    4633          627 :           ptr_qry.rvals->range_of_expr (vr, size, info.callstmt);
    4634              : 
    4635          627 :           if (!vr.undefined_p ())
    4636              :             {
    4637          627 :               tree type = TREE_TYPE (size);
    4638          627 :               tree tmin = wide_int_to_tree (type, vr.lower_bound ());
    4639          627 :               tree tmax = wide_int_to_tree (type, vr.upper_bound ());
    4640          627 :               unsigned HOST_WIDE_INT minsize = TREE_INT_CST_LOW (tmin);
    4641          627 :               unsigned HOST_WIDE_INT maxsize = TREE_INT_CST_LOW (tmax);
    4642          627 :               dstsize = warn_level < 2 ? maxsize : minsize;
    4643              : 
    4644          627 :               if (minsize > target_int_max ())
    4645            8 :                 warning_at (gimple_location (info.callstmt), info.warnopt (),
    4646              :                             "specified bound range [%wu, %wu] exceeds "
    4647              :                             "%<INT_MAX%>",
    4648              :                             minsize, maxsize);
    4649              : 
    4650              :               /* POSIX requires snprintf to fail if DSTSIZE is greater
    4651              :                  than INT_MAX.  Avoid folding if that's possible.  */
    4652          627 :               if (maxsize > target_int_max ())
    4653          584 :                 posunder4k = false;
    4654              :             }
    4655              : 
    4656              :           /* The destination size is not constant.  If the function is
    4657              :              bounded (e.g., snprintf) a lower bound of zero doesn't
    4658              :              necessarily imply it can be eliminated.  */
    4659          627 :           dstsize_cst_p = false;
    4660          627 :         }
    4661              :     }
    4662              : 
    4663       142866 :   if (idx_objsize != UINT_MAX)
    4664         1565 :     if (tree size = gimple_call_arg (info.callstmt, idx_objsize))
    4665         1565 :       if (tree_fits_uhwi_p (size))
    4666         1552 :         objsize = tree_to_uhwi (size);
    4667              : 
    4668       142866 :   if (info.bounded && !dstsize)
    4669              :     {
    4670              :       /* As a special case, when the explicitly specified destination
    4671              :          size argument (to a bounded function like snprintf) is zero
    4672              :          it is a request to determine the number of bytes on output
    4673              :          without actually producing any.  Pretend the size is
    4674              :          unlimited in this case.  */
    4675          461 :       info.objsize = HOST_WIDE_INT_MAX;
    4676          461 :       info.nowrite = dstsize_cst_p;
    4677              :     }
    4678              :   else
    4679              :     {
    4680              :       /* For calls to non-bounded functions or to those of bounded
    4681              :          functions with a non-zero size, warn if the destination
    4682              :          pointer is null.  */
    4683       142405 :       if (dstptr && integer_zerop (dstptr))
    4684              :         {
    4685              :           /* This is diagnosed with -Wformat only when the null is a constant
    4686              :              pointer.  The warning here diagnoses instances where the pointer
    4687              :              is not constant.  */
    4688           19 :           location_t loc = gimple_location (info.callstmt);
    4689           48 :           warning_at (EXPR_LOC_OR_LOC (dstptr, loc),
    4690           19 :                       info.warnopt (), "null destination pointer");
    4691           19 :           return false;
    4692              :         }
    4693              : 
    4694              :       /* Set the object size to the smaller of the two arguments
    4695              :          of both have been specified and they're not equal.  */
    4696       142386 :       info.objsize = dstsize < objsize ? dstsize : objsize;
    4697              : 
    4698       142386 :       if (info.bounded
    4699         3628 :           && dstsize < target_size_max () / 2 && objsize < dstsize
    4700              :           /* Avoid warning if -Wstringop-overflow is specified since
    4701              :              it also warns for the same thing though only for the
    4702              :              checking built-ins.  */
    4703       142456 :           && (idx_objsize == UINT_MAX
    4704           70 :               || !warn_stringop_overflow))
    4705              :         {
    4706            3 :           warning_at (gimple_location (info.callstmt), info.warnopt (),
    4707              :                       "specified bound %wu exceeds the size %wu "
    4708              :                       "of the destination object", dstsize, objsize);
    4709              :         }
    4710              :     }
    4711              : 
    4712              :   /* Determine if the format argument may be null and warn if not
    4713              :      and if the argument is null.  */
    4714       142847 :   if (integer_zerop (info.format)
    4715       142847 :       && gimple_call_builtin_p (info.callstmt, BUILT_IN_NORMAL))
    4716              :     {
    4717           63 :       location_t loc = gimple_location (info.callstmt);
    4718          181 :       warning_at (EXPR_LOC_OR_LOC (info.format, loc),
    4719           63 :                   info.warnopt (), "null format string");
    4720           63 :       return false;
    4721              :     }
    4722              : 
    4723       142784 :   info.fmtstr = get_format_string (info.format, &info.fmtloc);
    4724       142784 :   if (!info.fmtstr)
    4725              :     return false;
    4726              : 
    4727       137471 :   if (warn_restrict)
    4728              :     {
    4729              :       /* Compute the origin of the destination pointer and its offset
    4730              :          from the base object/pointer if possible.  */
    4731        34341 :       info.dst_offset = 0;
    4732        34341 :       info.dst_origin = get_origin_and_offset (dstptr, &info.dst_field,
    4733              :                                                &info.dst_offset);
    4734              :     }
    4735              : 
    4736              :   /* The result is the number of bytes output by the formatted function,
    4737              :      including the terminating NUL.  */
    4738       274942 :   format_result res;
    4739              : 
    4740              :   /* I/O functions with no destination argument (i.e., all forms of fprintf
    4741              :      and printf) may fail under any conditions.  Others (i.e., all forms of
    4742              :      sprintf) may only fail under specific conditions determined for each
    4743              :      directive.  Clear POSUNDER4K for the former set of functions and set
    4744              :      it to true for the latter (it can only be cleared later, but it is
    4745              :      never set to true again).  */
    4746       137471 :   res.posunder4k = posunder4k && dstptr;
    4747              : 
    4748       137471 :   bool success = compute_format_length (info, &res, ptr_qry);
    4749       137471 :   if (res.warned)
    4750         4357 :     suppress_warning (info.callstmt, info.warnopt ());
    4751              : 
    4752              :   /* When optimizing and the printf return value optimization is enabled,
    4753              :      attempt to substitute the computed result for the return value of
    4754              :      the call.  Avoid this optimization when -frounding-math is in effect
    4755              :      and the format string contains a floating point directive.  */
    4756       137471 :   bool call_removed = false;
    4757       137471 :   if (success && optimize > 0)
    4758              :     {
    4759              :       /* Save a copy of the iterator pointing at the call.  The iterator
    4760              :          may change to point past the call in try_substitute_return_value
    4761              :          but the original value is needed in try_simplify_call.  */
    4762       127004 :       gimple_stmt_iterator gsi_call = *gsi;
    4763              : 
    4764       127004 :       if (flag_printf_return_value
    4765       126983 :           && (!flag_rounding_math || !res.floating))
    4766       126983 :         call_removed = try_substitute_return_value (gsi, info, res);
    4767              : 
    4768       126983 :       if (!call_removed)
    4769       126991 :         try_simplify_call (&gsi_call, info, res);
    4770              :     }
    4771              : 
    4772       137471 :   return call_removed;
    4773              : }
        

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.