Home | History | Annotate | Line # | Download | only in c-family
      1 /* Check calls to formatted I/O functions (-Wformat).
      2    Copyright (C) 1992-2022 Free Software Foundation, Inc.
      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 #include "config.h"
     21 #include "system.h"
     22 #include "coretypes.h"
     23 #include "tm.h"
     24 #include "c-target.h"
     25 #include "c-common.h"
     26 #include "alloc-pool.h"
     27 #include "stringpool.h"
     28 #include "c-objc.h"
     29 #include "intl.h"
     30 #include "langhooks.h"
     31 #include "c-format.h"
     32 #include "diagnostic.h"
     33 #include "substring-locations.h"
     34 #include "selftest.h"
     35 #include "selftest-diagnostic.h"
     36 #include "builtins.h"
     37 #include "attribs.h"
     38 #include "gcc-rich-location.h"
     39 
     40 /* Handle attributes associated with format checking.  */
     41 
     42 /* This must be in the same order as format_types, except for
     43    format_type_error.  Target-specific format types do not have
     44    matching enum values.  */
     45 enum format_type { printf_format_type, asm_fprintf_format_type,
     46 		   gcc_diag_format_type, gcc_tdiag_format_type,
     47 		   gcc_cdiag_format_type,
     48 		   gcc_cxxdiag_format_type, gcc_gfc_format_type,
     49 		   gcc_dump_printf_format_type,
     50 		   gcc_objc_string_format_type,
     51 		   format_type_error = -1};
     52 
     53 struct function_format_info
     54 {
     55   enum format_type format_type;		/* type of format (printf, scanf, etc.) */
     56   /* IS_RAW is relevant only for GCC diagnostic format functions.
     57      It is set for "raw" formatting functions like pp_printf that
     58      are not intended to produce complete diagnostics according to
     59      GCC guidelines, and clear for others like error and warning
     60      whose format string is checked for proper quoting and spelling.  */
     61   bool is_raw;
     62   unsigned HOST_WIDE_INT format_num;	/* number of format argument */
     63   unsigned HOST_WIDE_INT first_arg_num;	/* number of first arg (zero for varargs) */
     64 };
     65 
     66 /* Initialized in init_dynamic_diag_info.  */
     67 static GTY(()) tree local_tree_type_node;
     68 static GTY(()) tree local_event_ptr_node;
     69 static GTY(()) tree local_gimple_ptr_node;
     70 static GTY(()) tree local_cgraph_node_ptr_node;
     71 static GTY(()) tree locus;
     72 
     73 static bool decode_format_attr (const_tree, tree, tree, function_format_info *,
     74 				bool);
     75 static format_type decode_format_type (const char *, bool * = NULL);
     76 
     77 static bool check_format_string (const_tree argument,
     78 				 unsigned HOST_WIDE_INT format_num,
     79 				 int flags, bool *no_add_attrs,
     80 				 int expected_format_type);
     81 static tree get_constant (const_tree fntype, const_tree atname, tree expr,
     82 			  int argno, unsigned HOST_WIDE_INT *value,
     83 			  int flags, bool validated_p);
     84 static const char *convert_format_name_to_system_name (const char *attr_name);
     85 
     86 static int first_target_format_type;
     87 static const char *format_name (int format_num);
     88 static int format_flags (int format_num);
     89 
     90 /* Emit a warning as per format_warning_va, but construct the substring_loc
     91    for the character at offset (CHAR_IDX - 1) within a string constant
     92    FORMAT_STRING_CST at FMT_STRING_LOC.  */
     93 
     94 ATTRIBUTE_GCC_DIAG (5,6)
     95 static bool
     96 format_warning_at_char (location_t fmt_string_loc, tree format_string_cst,
     97 			int char_idx, int opt, const char *gmsgid, ...)
     98 {
     99   va_list ap;
    100   va_start (ap, gmsgid);
    101   tree string_type = TREE_TYPE (format_string_cst);
    102 
    103   /* The callers are of the form:
    104        format_warning (format_string_loc, format_string_cst,
    105 		       format_chars - orig_format_chars,
    106       where format_chars has already been incremented, so that
    107       CHAR_IDX is one character beyond where the warning should
    108       be emitted.  Fix it.  */
    109   char_idx -= 1;
    110 
    111   substring_loc fmt_loc (fmt_string_loc, string_type, char_idx, char_idx,
    112 			 char_idx);
    113   format_string_diagnostic_t diag (fmt_loc, NULL, UNKNOWN_LOCATION, NULL,
    114 				   NULL);
    115   bool warned = diag.emit_warning_va (opt, gmsgid, &ap);
    116   va_end (ap);
    117 
    118   return warned;
    119 }
    120 
    121 
    122 /* Emit a warning as per format_warning_va, but construct the substring_loc
    123    for the substring at offset (POS1, POS2 - 1) within a string constant
    124    FORMAT_STRING_CST at FMT_STRING_LOC.  */
    125 
    126 ATTRIBUTE_GCC_DIAG (6,7)
    127 static bool
    128 format_warning_substr (location_t fmt_string_loc, tree format_string_cst,
    129 		       int pos1, int pos2, int opt, const char *gmsgid, ...)
    130 {
    131   va_list ap;
    132   va_start (ap, gmsgid);
    133   tree string_type = TREE_TYPE (format_string_cst);
    134 
    135   pos2 -= 1;
    136 
    137   substring_loc fmt_loc (fmt_string_loc, string_type, pos1, pos1, pos2);
    138   format_string_diagnostic_t diag (fmt_loc, NULL, UNKNOWN_LOCATION, NULL,
    139 				   NULL);
    140   bool warned = diag.emit_warning_va (opt, gmsgid, &ap);
    141   va_end (ap);
    142 
    143   return warned;
    144 }
    145 
    146 
    147 /* Check that we have a pointer to a string suitable for use as a format.
    148    The default is to check for a char type.
    149    For objective-c dialects, this is extended to include references to string
    150    objects validated by objc_string_ref_type_p ().
    151    Targets may also provide a string object type that can be used within c and
    152    c++ and shared with their respective objective-c dialects. In this case the
    153    reference to a format string is checked for validity via a hook.
    154 
    155    The function returns true if strref points to any string type valid for the
    156    language dialect and target.  */
    157 
    158 bool
    159 valid_format_string_type_p (tree strref)
    160 {
    161   return (strref != NULL
    162 	  && TREE_CODE (strref) == POINTER_TYPE
    163 	  && (TYPE_MAIN_VARIANT (TREE_TYPE (strref)) == char_type_node
    164 	      || objc_string_ref_type_p (strref)
    165 	      || (*targetcm.string_object_ref_type_p) ((const_tree) strref)));
    166 }
    167 
    168 /* Handle a "format_arg" attribute; arguments as in
    169    struct attribute_spec.handler.  */
    170 tree
    171 handle_format_arg_attribute (tree *node, tree atname,
    172 			     tree args, int flags, bool *no_add_attrs)
    173 {
    174   tree type = *node;
    175   /* Note that TREE_VALUE (args) is changed in place below.  */
    176   tree *format_num_expr = &TREE_VALUE (args);
    177   unsigned HOST_WIDE_INT format_num = 0;
    178 
    179   if (tree val = get_constant (type, atname, *format_num_expr, 0, &format_num,
    180 			       0, false))
    181     *format_num_expr = val;
    182   else
    183     {
    184       *no_add_attrs = true;
    185       return NULL_TREE;
    186     }
    187 
    188   if (prototype_p (type))
    189     {
    190       /* The format arg can be any string reference valid for the language and
    191 	target.  We cannot be more specific in this case.  */
    192       if (!check_format_string (type, format_num, flags, no_add_attrs, -1))
    193 	return NULL_TREE;
    194     }
    195 
    196   if (!valid_format_string_type_p (TREE_TYPE (type)))
    197     {
    198       if (!(flags & (int) ATTR_FLAG_BUILT_IN))
    199 	error ("function does not return string type");
    200       *no_add_attrs = true;
    201       return NULL_TREE;
    202     }
    203 
    204   return NULL_TREE;
    205 }
    206 
    207 /* Verify that the format_num argument is actually a string reference suitable,
    208    for the language dialect and target (in case the format attribute is in
    209    error).  When we know the specific reference type expected, this is also
    210    checked.  */
    211 static bool
    212 check_format_string (const_tree fntype, unsigned HOST_WIDE_INT format_num,
    213 		     int flags, bool *no_add_attrs, int expected_format_type)
    214 {
    215   unsigned HOST_WIDE_INT i;
    216   bool is_objc_sref, is_target_sref, is_char_ref;
    217   tree ref;
    218   int fmt_flags;
    219   function_args_iterator iter;
    220 
    221   i = 1;
    222   FOREACH_FUNCTION_ARGS (fntype, ref, iter)
    223     {
    224       if (i == format_num)
    225 	break;
    226       i++;
    227     }
    228 
    229   if (!ref
    230       || !valid_format_string_type_p (ref))
    231     {
    232       if (!(flags & (int) ATTR_FLAG_BUILT_IN))
    233 	error ("format string argument is not a string type");
    234       *no_add_attrs = true;
    235       return false;
    236     }
    237 
    238   /* We only know that we want a suitable string reference.  */
    239   if (expected_format_type < 0)
    240     return true;
    241 
    242   /* Now check that the arg matches the expected type.  */
    243   is_char_ref =
    244     (TYPE_MAIN_VARIANT (TREE_TYPE (ref)) == char_type_node);
    245 
    246   fmt_flags = format_flags (expected_format_type);
    247   is_objc_sref = is_target_sref = false;
    248   if (!is_char_ref)
    249     is_objc_sref = objc_string_ref_type_p (ref);
    250 
    251   if (!(fmt_flags & FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL))
    252     {
    253       if (is_char_ref)
    254 	return true; /* OK, we expected a char and found one.  */
    255       else
    256 	{
    257 	  /* We expected a char but found an extended string type.  */
    258 	  if (is_objc_sref)
    259 	    error ("found a %qs reference but the format argument should"
    260 		   " be a string", format_name (gcc_objc_string_format_type));
    261 	  else
    262 	    error ("found a %qT but the format argument should be a string",
    263 		   ref);
    264 	  *no_add_attrs = true;
    265 	  return false;
    266 	}
    267     }
    268 
    269   /* We expect a string object type as the format arg.  */
    270   if (is_char_ref)
    271     {
    272       error ("format argument should be a %qs reference but"
    273 	     " a string was found", format_name (expected_format_type));
    274       *no_add_attrs = true;
    275       return false;
    276     }
    277 
    278   /* We will assert that objective-c will support either its own string type
    279      or the target-supplied variant.  */
    280   if (!is_objc_sref)
    281     is_target_sref = (*targetcm.string_object_ref_type_p) ((const_tree) ref);
    282 
    283   if (expected_format_type == (int) gcc_objc_string_format_type
    284       && (is_objc_sref || is_target_sref))
    285     return true;
    286 
    287   /* We will allow a target string ref to match only itself.  */
    288   if (first_target_format_type
    289       && expected_format_type >= first_target_format_type
    290       && is_target_sref)
    291     return true;
    292   else
    293     {
    294       error ("format argument should be a %qs reference",
    295 	      format_name (expected_format_type));
    296       *no_add_attrs = true;
    297       return false;
    298     }
    299 }
    300 
    301 /* Under the control of FLAGS, verify EXPR is a valid constant that
    302    refers to a positional argument ARGNO having a string type (char*
    303    or, for targets like Darwin, a pointer to struct CFString) to
    304    a function type FNTYPE declared with attribute ATNAME.
    305    If valid, store the constant's integer value in *VALUE and return
    306    the value.
    307    If VALIDATED_P is true assert the validation is successful.
    308    Returns the converted constant value on success, null otherwise.  */
    309 
    310 static tree
    311 get_constant (const_tree fntype, const_tree atname, tree expr, int argno,
    312 	      unsigned HOST_WIDE_INT *value, int flags, bool validated_p)
    313 {
    314   /* Require the referenced argument to have a string type.  For targets
    315      like Darwin, also accept pointers to struct CFString.  */
    316   if (tree val = positional_argument (fntype, atname, expr, STRING_CST,
    317 				      argno, flags))
    318     {
    319       *value = TREE_INT_CST_LOW (val);
    320       return val;
    321     }
    322 
    323   gcc_assert (!validated_p);
    324   return NULL_TREE;
    325 }
    326 
    327 /* Decode the arguments to a "format" attribute into a
    328    function_format_info structure.  It is already known that the list
    329    is of the right length.  If VALIDATED_P is true, then these
    330    attributes have already been validated and must not be erroneous;
    331    if false, it will give an error message.  Returns true if the
    332    attributes are successfully decoded, false otherwise.  */
    333 
    334 static bool
    335 decode_format_attr (const_tree fntype, tree atname, tree args,
    336 		    function_format_info *info, bool validated_p)
    337 {
    338   tree format_type_id = TREE_VALUE (args);
    339   /* Note that TREE_VALUE (args) is changed in place below.  Ditto
    340      for the value of the next element on the list.  */
    341   tree *format_num_expr = &TREE_VALUE (TREE_CHAIN (args));
    342   tree *first_arg_num_expr = &TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
    343 
    344   if (TREE_CODE (format_type_id) != IDENTIFIER_NODE)
    345     {
    346       gcc_assert (!validated_p);
    347       error ("unrecognized format specifier");
    348       return false;
    349     }
    350   else
    351     {
    352       const char *p = IDENTIFIER_POINTER (format_type_id);
    353 
    354       info->format_type = decode_format_type (p, &info->is_raw);
    355 
    356       if (!c_dialect_objc ()
    357 	   && info->format_type == gcc_objc_string_format_type)
    358 	{
    359 	  gcc_assert (!validated_p);
    360 	  warning (OPT_Wformat_, "%qE is only allowed in Objective-C dialects",
    361 		   format_type_id);
    362 	  info->format_type = format_type_error;
    363 	  return false;
    364 	}
    365 
    366       if (info->format_type == format_type_error)
    367 	{
    368 	  gcc_assert (!validated_p);
    369 	  warning (OPT_Wformat_, "%qE is an unrecognized format function type",
    370 		   format_type_id);
    371 	  return false;
    372 	}
    373     }
    374 
    375   if (tree val = get_constant (fntype, atname, *format_num_expr,
    376 			       2, &info->format_num, 0, validated_p))
    377     *format_num_expr = val;
    378   else
    379     return false;
    380 
    381   if (tree val = get_constant (fntype, atname, *first_arg_num_expr,
    382 			       3, &info->first_arg_num,
    383 			       (POSARG_ZERO | POSARG_ELLIPSIS), validated_p))
    384     *first_arg_num_expr = val;
    385   else
    386     return false;
    387 
    388   if (info->first_arg_num != 0 && info->first_arg_num <= info->format_num)
    389     {
    390       gcc_assert (!validated_p);
    391       error ("format string argument follows the arguments to be formatted");
    392       return false;
    393     }
    394 
    395   return true;
    396 }
    397 
    398 /* Check a call to a format function against a parameter list.  */
    400 
    401 /* The C standard version C++ is treated as equivalent to
    402    or inheriting from, for the purpose of format features supported.  */
    403 #define CPLUSPLUS_STD_VER	(cxx_dialect < cxx11 ? STD_C94 : STD_C99)
    404 /* The C standard version we are checking formats against when pedantic.  */
    405 #define C_STD_VER		((int) (c_dialect_cxx ()		   \
    406 				 ? CPLUSPLUS_STD_VER			   \
    407 				 : (flag_isoc2x				   \
    408 				    ? STD_C2X				   \
    409 				    : (flag_isoc99			   \
    410 				       ? STD_C99			   \
    411 				       : (flag_isoc94 ? STD_C94 : STD_C89)))))
    412 /* The name to give to the standard version we are warning about when
    413    pedantic.  FEATURE_VER is the version in which the feature warned out
    414    appeared, which is higher than C_STD_VER.  */
    415 #define C_STD_NAME(FEATURE_VER) (c_dialect_cxx ()		\
    416 				 ? (cxx_dialect < cxx11 ? "ISO C++98" \
    417 				    : "ISO C++11")		\
    418 				 : ((FEATURE_VER) == STD_EXT	\
    419 				    ? "ISO C"			\
    420 				    : ((FEATURE_VER) == STD_C2X	\
    421 				       ? "ISO C17"		\
    422 				       : "ISO C90")))
    423 /* Adjust a C standard version, which may be STD_C9L, to account for
    424    -Wno-long-long.  Returns other standard versions unchanged.  */
    425 #define ADJ_STD(VER)		((int) ((VER) == STD_C9L		      \
    426 				       ? (warn_long_long ? STD_C99 : STD_C89) \
    427 				       : (VER)))
    428 
    429 /* Enum describing the kind of specifiers present in the format and
    430    requiring an argument.  */
    431 enum format_specifier_kind {
    432   CF_KIND_FORMAT,
    433   CF_KIND_FIELD_WIDTH,
    434   CF_KIND_FIELD_PRECISION
    435 };
    436 
    437 static const char *kind_descriptions[] = {
    438   N_("format"),
    439   N_("field width specifier"),
    440   N_("field precision specifier")
    441 };
    442 
    443 /* Structure describing details of a type expected in format checking,
    444    and the type to check against it.  */
    445 struct format_wanted_type
    446 {
    447   /* The type wanted.  */
    448   tree wanted_type;
    449   /* The name of this type to use in diagnostics.  */
    450   const char *wanted_type_name;
    451   /* Should be type checked just for scalar width identity.  */
    452   int scalar_identity_flag;
    453   /* The level of indirection through pointers at which this type occurs.  */
    454   int pointer_count;
    455   /* Whether, when pointer_count is 1, to allow any character type when
    456      pedantic, rather than just the character or void type specified.  */
    457   int char_lenient_flag;
    458   /* Whether the argument, dereferenced once, is written into and so the
    459      argument must not be a pointer to a const-qualified type.  */
    460   int writing_in_flag;
    461   /* Whether the argument, dereferenced once, is read from and so
    462      must not be a NULL pointer.  */
    463   int reading_from_flag;
    464   /* The kind of specifier that this type is used for.  */
    465   enum format_specifier_kind kind;
    466   /* The starting character of the specifier.  This never includes the
    467      initial percent sign.  */
    468   const char *format_start;
    469   /* The length of the specifier.  */
    470   int format_length;
    471   /* The actual parameter to check against the wanted type.  */
    472   tree param;
    473   /* The argument number of that parameter.  */
    474   int arg_num;
    475   /* The offset location of this argument with respect to the format
    476      string location.  */
    477   unsigned int offset_loc;
    478   /* The next type to check for this format conversion, or NULL if none.  */
    479   struct format_wanted_type *next;
    480 };
    481 
    482 /* Convenience macro for format_length_info meaning unused.  */
    483 #define NO_FMT NULL, FMT_LEN_none, STD_C89
    484 
    485 static const format_length_info printf_length_specs[] =
    486 {
    487   { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99, 0 },
    488   { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L, 0 },
    489   { "q", FMT_LEN_ll, STD_EXT, NO_FMT, 0 },
    490   { "L", FMT_LEN_L, STD_C89, NO_FMT, 0 },
    491   { "z", FMT_LEN_z, STD_C99, NO_FMT, 0 },
    492   { "Z", FMT_LEN_z, STD_EXT, NO_FMT, 0 },
    493   { "t", FMT_LEN_t, STD_C99, NO_FMT, 0 },
    494   { "j", FMT_LEN_j, STD_C99, NO_FMT, 0 },
    495   { "H", FMT_LEN_H, STD_C2X, NO_FMT, 0 },
    496   { "D", FMT_LEN_D, STD_C2X, "DD", FMT_LEN_DD, STD_C2X, 0 },
    497   { NO_FMT, NO_FMT, 0 }
    498 };
    499 
    500 /* Length specifiers valid for asm_fprintf.  */
    501 static const format_length_info asm_fprintf_length_specs[] =
    502 {
    503   { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89, 0 },
    504   { "w", FMT_LEN_w, STD_C89, NO_FMT, 0 },
    505   { NO_FMT, NO_FMT, 0 }
    506 };
    507 
    508 /* Length specifiers valid for GCC diagnostics.  */
    509 static const format_length_info gcc_diag_length_specs[] =
    510 {
    511   { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89, 0 },
    512   { "w", FMT_LEN_w, STD_C89, NO_FMT, 0 },
    513   { NO_FMT, NO_FMT, 0 }
    514 };
    515 
    516 /* The custom diagnostics all accept the same length specifiers.  */
    517 #define gcc_tdiag_length_specs gcc_diag_length_specs
    518 #define gcc_cdiag_length_specs gcc_diag_length_specs
    519 #define gcc_cxxdiag_length_specs gcc_diag_length_specs
    520 #define gcc_dump_printf_length_specs gcc_diag_length_specs
    521 
    522 /* This differs from printf_length_specs only in that "Z" is not accepted.  */
    523 static const format_length_info scanf_length_specs[] =
    524 {
    525   { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99, 0 },
    526   { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L, 0 },
    527   { "q", FMT_LEN_ll, STD_EXT, NO_FMT, 0 },
    528   { "L", FMT_LEN_L, STD_C89, NO_FMT, 0 },
    529   { "z", FMT_LEN_z, STD_C99, NO_FMT, 0 },
    530   { "t", FMT_LEN_t, STD_C99, NO_FMT, 0 },
    531   { "j", FMT_LEN_j, STD_C99, NO_FMT, 0 },
    532   { "H", FMT_LEN_H, STD_C2X, NO_FMT, 0 },
    533   { "D", FMT_LEN_D, STD_C2X, "DD", FMT_LEN_DD, STD_C2X, 0 },
    534   { NO_FMT, NO_FMT, 0 }
    535 };
    536 
    537 
    538 /* All tables for strfmon use STD_C89 everywhere, since -pedantic warnings
    539    make no sense for a format type not part of any C standard version.  */
    540 static const format_length_info strfmon_length_specs[] =
    541 {
    542   /* A GNU extension.  */
    543   { "L", FMT_LEN_L, STD_C89, NO_FMT, 0 },
    544   { NO_FMT, NO_FMT, 0 }
    545 };
    546 
    547 
    548 /* Length modifiers used by the fortran/error.cc routines.  */
    549 static const format_length_info gcc_gfc_length_specs[] =
    550 {
    551   { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89, 0 },
    552   { "w", FMT_LEN_w, STD_C89, NO_FMT, 0 },
    553   { NO_FMT, NO_FMT, 0 }
    554 };
    555 
    556 
    557 static const format_flag_spec printf_flag_specs[] =
    558 {
    559   { ' ',  0, 0, 0, N_("' ' flag"),        N_("the ' ' printf flag"),              STD_C89 },
    560   { '+',  0, 0, 0, N_("'+' flag"),        N_("the '+' printf flag"),              STD_C89 },
    561   { '#',  0, 0, 0, N_("'#' flag"),        N_("the '#' printf flag"),              STD_C89 },
    562   { '0',  0, 0, 0, N_("'0' flag"),        N_("the '0' printf flag"),              STD_C89 },
    563   { '-',  0, 0, 0, N_("'-' flag"),        N_("the '-' printf flag"),              STD_C89 },
    564   { '\'', 0, 0, 0, N_("''' flag"),        N_("the ''' printf flag"),              STD_EXT },
    565   { 'I',  0, 0, 0, N_("'I' flag"),        N_("the 'I' printf flag"),              STD_EXT },
    566   { 'w',  0, 0, 0, N_("field width"),     N_("field width in printf format"),     STD_C89 },
    567   { 'p',  0, 0, 0, N_("precision"),       N_("precision in printf format"),       STD_C89 },
    568   { 'L',  0, 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
    569   { 0, 0, 0, 0, NULL, NULL, STD_C89 }
    570 };
    571 
    572 
    573 static const format_flag_pair printf_flag_pairs[] =
    574 {
    575   { ' ', '+', 1, 0   },
    576   { '0', '-', 1, 0   },
    577   { '0', 'p', 1, 'i' },
    578   { 0, 0, 0, 0 }
    579 };
    580 
    581 static const format_flag_spec asm_fprintf_flag_specs[] =
    582 {
    583   { ' ',  0, 0, 0, N_("' ' flag"),        N_("the ' ' printf flag"),              STD_C89 },
    584   { '+',  0, 0, 0, N_("'+' flag"),        N_("the '+' printf flag"),              STD_C89 },
    585   { '#',  0, 0, 0, N_("'#' flag"),        N_("the '#' printf flag"),              STD_C89 },
    586   { '0',  0, 0, 0, N_("'0' flag"),        N_("the '0' printf flag"),              STD_C89 },
    587   { '-',  0, 0, 0, N_("'-' flag"),        N_("the '-' printf flag"),              STD_C89 },
    588   { 'w',  0, 0, 0, N_("field width"),     N_("field width in printf format"),     STD_C89 },
    589   { 'p',  0, 0, 0, N_("precision"),       N_("precision in printf format"),       STD_C89 },
    590   { 'L',  0, 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
    591   { 0, 0, 0, 0, NULL, NULL, STD_C89 }
    592 };
    593 
    594 static const format_flag_pair asm_fprintf_flag_pairs[] =
    595 {
    596   { ' ', '+', 1, 0   },
    597   { '0', '-', 1, 0   },
    598   { '0', 'p', 1, 'i' },
    599   { 0, 0, 0, 0 }
    600 };
    601 
    602 static const format_flag_pair gcc_diag_flag_pairs[] =
    603 {
    604   { 0, 0, 0, 0 }
    605 };
    606 
    607 #define gcc_tdiag_flag_pairs gcc_diag_flag_pairs
    608 #define gcc_cdiag_flag_pairs gcc_diag_flag_pairs
    609 #define gcc_cxxdiag_flag_pairs gcc_diag_flag_pairs
    610 #define gcc_gfc_flag_pairs gcc_diag_flag_pairs
    611 #define gcc_dump_printf_flag_pairs gcc_diag_flag_pairs
    612 
    613 static const format_flag_spec gcc_diag_flag_specs[] =
    614 {
    615   { '+',  0, 0, 0, N_("'+' flag"),        N_("the '+' printf flag"),              STD_C89 },
    616   { '#',  0, 0, 0, N_("'#' flag"),        N_("the '#' printf flag"),              STD_C89 },
    617   { 'q',  0, 0, 1, N_("'q' flag"),        N_("the 'q' diagnostic flag"),          STD_C89 },
    618   { 'p',  0, 0, 0, N_("precision"),       N_("precision in printf format"),       STD_C89 },
    619   { 'L',  0, 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
    620   { 0, 0, 0, 0, NULL, NULL, STD_C89 }
    621 };
    622 
    623 #define gcc_tdiag_flag_specs gcc_diag_flag_specs
    624 #define gcc_cdiag_flag_specs gcc_diag_flag_specs
    625 #define gcc_cxxdiag_flag_specs gcc_diag_flag_specs
    626 #define gcc_gfc_flag_specs gcc_diag_flag_specs
    627 #define gcc_dump_printf_flag_specs gcc_diag_flag_specs
    628 
    629 static const format_flag_spec scanf_flag_specs[] =
    630 {
    631   { '*',  0, 0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89 },
    632   { 'a',  0, 0, 0, N_("'a' flag"),               N_("the 'a' scanf flag"),                       STD_EXT },
    633   { 'm',  0, 0, 0, N_("'m' flag"),               N_("the 'm' scanf flag"),                       STD_EXT },
    634   { 'w',  0, 0, 0, N_("field width"),            N_("field width in scanf format"),              STD_C89 },
    635   { 'L',  0, 0, 0, N_("length modifier"),        N_("length modifier in scanf format"),          STD_C89 },
    636   { '\'', 0, 0, 0, N_("''' flag"),               N_("the ''' scanf flag"),                       STD_EXT },
    637   { 'I',  0, 0, 0, N_("'I' flag"),               N_("the 'I' scanf flag"),                       STD_EXT },
    638   { 0, 0, 0, 0, NULL, NULL, STD_C89 }
    639 };
    640 
    641 
    642 static const format_flag_pair scanf_flag_pairs[] =
    643 {
    644   { '*', 'L', 0, 0 },
    645   { 'a', 'm', 0, 0 },
    646   { 0, 0, 0, 0 }
    647 };
    648 
    649 
    650 static const format_flag_spec strftime_flag_specs[] =
    651 {
    652   { '_', 0,   0, 0, N_("'_' flag"),     N_("the '_' strftime flag"),          STD_EXT },
    653   { '-', 0,   0, 0, N_("'-' flag"),     N_("the '-' strftime flag"),          STD_EXT },
    654   { '0', 0,   0, 0, N_("'0' flag"),     N_("the '0' strftime flag"),          STD_EXT },
    655   { '^', 0,   0, 0, N_("'^' flag"),     N_("the '^' strftime flag"),          STD_EXT },
    656   { '#', 0,   0, 0, N_("'#' flag"),     N_("the '#' strftime flag"),          STD_EXT },
    657   { 'w', 0,   0, 0, N_("field width"),  N_("field width in strftime format"), STD_EXT },
    658   { 'E', 0,   0, 0, N_("'E' modifier"), N_("the 'E' strftime modifier"),      STD_C99 },
    659   { 'O', 0,   0, 0, N_("'O' modifier"), N_("the 'O' strftime modifier"),      STD_C99 },
    660   { 'O', 'o', 0, 0, NULL,               N_("the 'O' modifier"),               STD_EXT },
    661   { 'O', 'p', 0, 0, NULL,               N_("the 'O' modifier"),               STD_C2X },
    662   { 0, 0, 0, 0, NULL, NULL, STD_C89 }
    663 };
    664 
    665 
    666 static const format_flag_pair strftime_flag_pairs[] =
    667 {
    668   { 'E', 'O', 0, 0 },
    669   { '_', '-', 0, 0 },
    670   { '_', '0', 0, 0 },
    671   { '-', '0', 0, 0 },
    672   { '^', '#', 0, 0 },
    673   { 0, 0, 0, 0 }
    674 };
    675 
    676 
    677 static const format_flag_spec strfmon_flag_specs[] =
    678 {
    679   { '=',  0, 1, 0, N_("fill character"),  N_("fill character in strfmon format"),  STD_C89 },
    680   { '^',  0, 0, 0, N_("'^' flag"),        N_("the '^' strfmon flag"),              STD_C89 },
    681   { '+',  0, 0, 0, N_("'+' flag"),        N_("the '+' strfmon flag"),              STD_C89 },
    682   { '(',  0, 0, 0, N_("'(' flag"),        N_("the '(' strfmon flag"),              STD_C89 },
    683   { '!',  0, 0, 0, N_("'!' flag"),        N_("the '!' strfmon flag"),              STD_C89 },
    684   { '-',  0, 0, 0, N_("'-' flag"),        N_("the '-' strfmon flag"),              STD_C89 },
    685   { 'w',  0, 0, 0, N_("field width"),     N_("field width in strfmon format"),     STD_C89 },
    686   { '#',  0, 0, 0, N_("left precision"),  N_("left precision in strfmon format"),  STD_C89 },
    687   { 'p',  0, 0, 0, N_("right precision"), N_("right precision in strfmon format"), STD_C89 },
    688   { 'L',  0, 0, 0, N_("length modifier"), N_("length modifier in strfmon format"), STD_C89 },
    689   { 0, 0, 0, 0, NULL, NULL, STD_C89 }
    690 };
    691 
    692 static const format_flag_pair strfmon_flag_pairs[] =
    693 {
    694   { '+', '(', 0, 0 },
    695   { 0, 0, 0, 0 }
    696 };
    697 
    698 
    699 static const format_char_info print_char_table[] =
    700 {
    701   /* C89 conversion specifiers.  */
    702   { "di",  0, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  TEX_LL,  T99_SST, T99_PD,  T99_IM,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +'I",  "i",  NULL },
    703   { "oxX", 0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM, BADLEN,  BADLEN,  BADLEN }, "-wp0#",     "i",  NULL },
    704   { "u",   0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM, BADLEN,  BADLEN,  BADLEN }, "-wp0'I",    "i",  NULL },
    705   { "fgG", 0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64, T2X_D128 }, "-wp0 +#'I", "",   NULL },
    706   { "eE",  0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64, T2X_D128 }, "-wp0 +#I",  "",   NULL },
    707   { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T94_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-w",        "",   NULL },
    708   { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-wp",       "cR", NULL },
    709   { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-w",        "c",  NULL },
    710   { "n",   1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  T99_IM,  BADLEN,  BADLEN,  BADLEN }, "",          "W",  NULL },
    711   /* C99 conversion specifiers.  */
    712   { "F",   0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64, T2X_D128 }, "-wp0 +#'I", "",   NULL },
    713   { "aA",  0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64,  T2X_D128 }, "-wp0 +#",   "",   NULL },
    714   /* C2X conversion specifiers.  */
    715   { "b",   0, STD_C2X, { T2X_UI,  T2X_UC,  T2X_US,  T2X_UL,  T2X_ULL, TEX_ULL, T2X_ST,  T2X_UPD, T2X_UIM, BADLEN,  BADLEN,  BADLEN }, "-wp0#",     "i",  NULL },
    716   /* X/Open conversion specifiers.  */
    717   { "C",   0, STD_EXT, { TEX_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-w",        "",   NULL },
    718   { "S",   1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-wp",       "R",  NULL },
    719   /* GNU conversion specifiers.  */
    720   { "m",   0, STD_EXT, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "-wp",       "",   NULL },
    721   { "B",   0, STD_EXT, { T2X_UI,  T2X_UC,  T2X_US,  T2X_UL,  T2X_ULL, TEX_ULL, T2X_ST,  T2X_UPD, T2X_UIM, BADLEN,  BADLEN,  BADLEN }, "-wp0#",     "i",  NULL },
    722   { NULL,  0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
    723 };
    724 
    725 static const format_char_info asm_fprintf_char_table[] =
    726 {
    727   /* C89 conversion specifiers.  */
    728   { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +",  "i", NULL },
    729   { "oxX", 0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0#",   "i", NULL },
    730   { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0",    "i", NULL },
    731   { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w",       "", NULL },
    732   { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",    "cR", NULL },
    733 
    734   /* asm_fprintf conversion specifiers.  */
    735   { "O",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
    736   { "R",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
    737   { "I",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
    738   { "L",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
    739   { "U",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
    740   { "r",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "",  "", NULL },
    741   { "z",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
    742   { "@",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
    743   { NULL,  0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
    744 };
    745 
    746 /* GCC-specific format_char_info arrays.  */
    747 
    748 /* The conversion specifiers implemented within pp_format, and thus supported
    749    by all pretty_printer instances within GCC.  */
    750 
    751 #define PP_FORMAT_CHAR_TABLE \
    752   { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
    753   { "ox",  0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
    754   { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
    755   { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL }, \
    756   { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "pq", "cR", NULL }, \
    757   { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "c",  NULL }, \
    758   { "r",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "",    "//cR",   NULL }, \
    759   { "@",   1, STD_C89, { T_EVENT_PTR,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "", "\"",   NULL }, \
    760   { "<",   0, STD_C89, NOARGUMENTS, "",      "<",   NULL }, \
    761   { ">",   0, STD_C89, NOARGUMENTS, "",      ">",   NULL }, \
    762   { "'" ,  0, STD_C89, NOARGUMENTS, "",      "",    NULL }, \
    763   { "{",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "",   "cR", NULL }, \
    764   { "}",   0, STD_C89, NOARGUMENTS, "",      "",    NULL }, \
    765   { "R",   0, STD_C89, NOARGUMENTS, "",     "\\",   NULL }, \
    766   { "m",   0, STD_C89, NOARGUMENTS, "q",     "",   NULL }, \
    767   { "Z",   1, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "",    "", &gcc_diag_char_table[0] }
    768 
    769 static const format_char_info gcc_diag_char_table[] =
    770 {
    771   /* The conversion specifiers implemented within pp_format.  */
    772   PP_FORMAT_CHAR_TABLE,
    773 
    774   { NULL,  0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
    775 };
    776 
    777 static const format_char_info gcc_tdiag_char_table[] =
    778 {
    779   /* The conversion specifiers implemented within pp_format.  */
    780   PP_FORMAT_CHAR_TABLE,
    781 
    782   /* Custom conversion specifiers implemented by default_tree_printer.  */
    783 
    784   /* These will require a "tree" at runtime.  */
    785   { "DFTV", 1, STD_C89, { T89_T,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+", "'",   NULL },
    786   { "E", 1, STD_C89, { T89_T,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+", "",   NULL },
    787 
    788   { NULL,  0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
    789 };
    790 
    791 static const format_char_info gcc_cdiag_char_table[] =
    792 {
    793   /* The conversion specifiers implemented within pp_format.  */
    794   PP_FORMAT_CHAR_TABLE,
    795 
    796   /* Custom conversion specifiers implemented by c_tree_printer.  */
    797 
    798   /* These will require a "tree" at runtime.  */
    799   { "DFTV", 1, STD_C89, { T89_T,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+", "'",   NULL },
    800   { "E",   1, STD_C89, { T89_T,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+", "",   NULL },
    801 
    802   { "v",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q#",  "",   NULL },
    803 
    804   { NULL,  0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
    805 };
    806 
    807 static const format_char_info gcc_cxxdiag_char_table[] =
    808 {
    809   /* The conversion specifiers implemented within pp_format.  */
    810   PP_FORMAT_CHAR_TABLE,
    811 
    812   /* Custom conversion specifiers implemented by cp_printer.  */
    813 
    814   /* These will require a "tree" at runtime.  */
    815   { "ADFHISTVX",1,STD_C89,{ T89_T,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+#",   "'",   NULL },
    816   { "E", 1,STD_C89,{ T89_T,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+#",   "",   NULL },
    817 
    818   /* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.)  */
    819   { "CLOPQ",0,STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
    820 
    821   { NULL,  0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
    822 };
    823 
    824 static const format_char_info gcc_gfc_char_table[] =
    825 {
    826   /* C89 conversion specifiers.  */
    827   { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
    828   { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN, BADLEN  }, "q", "", NULL },
    829   { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
    830   { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN, BADLEN, BADLEN, BADLEN }, "q", "cR", NULL },
    831 
    832   /* gfc conversion specifiers.  */
    833 
    834   { "C",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
    835 
    836   /* This will require a "locus" at runtime.  */
    837   { "L",   0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "", "R", NULL },
    838 
    839   /* These will require nothing.  */
    840   { "<>",0, STD_C89, NOARGUMENTS, "",      "",   NULL },
    841   { NULL,  0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
    842 };
    843 
    844 static const format_char_info gcc_dump_printf_char_table[] =
    845 {
    846   /* The conversion specifiers implemented within pp_format.  */
    847   PP_FORMAT_CHAR_TABLE,
    848 
    849   /* Custom conversion specifiers implemented by dump_pretty_printer.  */
    850 
    851   /* E and G require a "gimple *" argument at runtime.  */
    852   { "EG",   1, STD_C89, { T89_G,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "", "\"",   NULL },
    853 
    854   /* C requires a "cgraph_node *" argument at runtime.  */
    855   { "C",   1, STD_C89, { T_CGRAPH_NODE,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "", "\"",   NULL },
    856 
    857   /* T requires a "tree" at runtime.  */
    858   { "T",   1, STD_C89, { T89_T,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "", "\"",   NULL },
    859 
    860   /* %f requires a "double"; it doesn't support modifiers.  */
    861   { "f",   0, STD_C89, { T89_D,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "", "\"",   NULL },
    862 
    863   { NULL,  0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
    864 };
    865 
    866 static const format_char_info scan_char_table[] =
    867 {
    868   /* C89 conversion specifiers.  */
    869   { "di",    1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  TEX_LL,  T99_SST, T99_PD,  T99_IM,  BADLEN,  BADLEN,  BADLEN }, "*w'I", "W",   NULL },
    870   { "u",     1, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM, BADLEN,  BADLEN,  BADLEN }, "*w'I", "W",   NULL },
    871   { "oxX",   1, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM, BADLEN,  BADLEN,  BADLEN }, "*w",   "W",   NULL },
    872   { "efgEG", 1, STD_C89, { T89_F,   BADLEN,  BADLEN,  T89_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64, T2X_D128 }, "*w'",  "W",   NULL },
    873   { "c",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*mw",   "cW",  NULL },
    874   { "s",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*amw",  "cW",  NULL },
    875   { "[",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*amw",  "cW[", NULL },
    876   { "p",     2, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*w",   "W",   NULL },
    877   { "n",     1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  T99_IM,  BADLEN,  BADLEN,  BADLEN }, "",     "W",   NULL },
    878   /* C99 conversion specifiers.  */
    879   { "F",   1, STD_C99, { T99_F,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32, T2X_D64, T2X_D128 }, "*w'",  "W",   NULL },
    880   { "aA",   1, STD_C99, { T99_F,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN,  T2X_D32,  T2X_D64,  T2X_D128 }, "*w'",  "W",   NULL },
    881   /* C2X conversion specifiers.  */
    882   { "b",     1, STD_C2X, { T2X_UI,  T2X_UC,  T2X_US,  T2X_UL,  T2X_ULL, TEX_ULL, T2X_ST,  T2X_UPD, T2X_UIM, BADLEN,  BADLEN,  BADLEN }, "*w",   "W",   NULL },
    883   /* X/Open conversion specifiers.  */
    884   { "C",     1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*mw",   "W",   NULL },
    885   { "S",     1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN }, "*amw",  "W",   NULL },
    886   { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
    887 };
    888 
    889 static const format_char_info time_char_table[] =
    890 {
    891   /* C89 conversion specifiers.  */
    892   { "AZa",		0, STD_C89, NOLENGTHS, "^#",     "",   NULL },
    893   { "Bb",		0, STD_C89, NOLENGTHS, "O^#",    "p",  NULL },
    894   { "cx",		0, STD_C89, NOLENGTHS, "E",      "3",  NULL },
    895   { "HIMSUWdmw",	0, STD_C89, NOLENGTHS, "-_0Ow",  "",   NULL },
    896   { "j",		0, STD_C89, NOLENGTHS, "-_0Ow",  "o",  NULL },
    897   { "p",		0, STD_C89, NOLENGTHS, "#",      "",   NULL },
    898   { "X",		0, STD_C89, NOLENGTHS, "E",      "",   NULL },
    899   { "y",		0, STD_C89, NOLENGTHS, "EO-_0w", "4",  NULL },
    900   { "Y",		0, STD_C89, NOLENGTHS, "-_0EOw", "o",  NULL },
    901   { "%",		0, STD_C89, NOLENGTHS, "",       "",   NULL },
    902   /* C99 conversion specifiers.  */
    903   { "C",		0, STD_C99, NOLENGTHS, "-_0EOw", "o",  NULL },
    904   { "D",		0, STD_C99, NOLENGTHS, "",       "2",  NULL },
    905   { "eVu",		0, STD_C99, NOLENGTHS, "-_0Ow",  "",   NULL },
    906   { "FRTnrt",		0, STD_C99, NOLENGTHS, "",       "",   NULL },
    907   { "g",		0, STD_C99, NOLENGTHS, "O-_0w",  "2o", NULL },
    908   { "G",		0, STD_C99, NOLENGTHS, "-_0Ow",  "o",  NULL },
    909   { "h",		0, STD_C99, NOLENGTHS, "^#",     "",   NULL },
    910   { "z",		0, STD_C99, NOLENGTHS, "O",      "o",  NULL },
    911   /* GNU conversion specifiers.  */
    912   { "kls",		0, STD_EXT, NOLENGTHS, "-_0Ow",  "",   NULL },
    913   { "P",		0, STD_EXT, NOLENGTHS, "",       "",   NULL },
    914   { NULL,		0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
    915 };
    916 
    917 static const format_char_info monetary_char_table[] =
    918 {
    919   { "in", 0, STD_C89, { T89_D, BADLEN, BADLEN, BADLEN, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "=^+(!-w#p", "", NULL },
    920   { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
    921 };
    922 
    923 /* This must be in the same order as enum format_type.  */
    924 static const format_kind_info format_types_orig[] =
    925 {
    926   { "gnu_printf",   printf_length_specs,  print_char_table, " +#0-'I", NULL,
    927     printf_flag_specs, printf_flag_pairs,
    928     FMT_FLAG_ARG_CONVERT|FMT_FLAG_DOLLAR_MULTIPLE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_EMPTY_PREC_OK,
    929     'w', 0, 'p', 0, 'L', 0,
    930     &integer_type_node, &integer_type_node, format_type_error
    931   },
    932   { "asm_fprintf",   asm_fprintf_length_specs,  asm_fprintf_char_table, " +#0-", NULL,
    933     asm_fprintf_flag_specs, asm_fprintf_flag_pairs,
    934     FMT_FLAG_ARG_CONVERT|FMT_FLAG_EMPTY_PREC_OK,
    935     'w', 0, 'p', 0, 'L', 0,
    936     NULL, NULL, format_type_error
    937   },
    938   { "gcc_diag",   gcc_diag_length_specs,  gcc_diag_char_table, "q+#", NULL,
    939     gcc_diag_flag_specs, gcc_diag_flag_pairs,
    940     FMT_FLAG_ARG_CONVERT|FMT_FLAG_M_OK,
    941     0, 0, 'p', 0, 'L', 0,
    942     NULL, &integer_type_node, format_type_error
    943   },
    944   { "gcc_tdiag",   gcc_tdiag_length_specs,  gcc_tdiag_char_table, "q+#", NULL,
    945     gcc_tdiag_flag_specs, gcc_tdiag_flag_pairs,
    946     FMT_FLAG_ARG_CONVERT|FMT_FLAG_M_OK,
    947     0, 0, 'p', 0, 'L', 0,
    948     NULL, &integer_type_node, format_type_error
    949   },
    950   { "gcc_cdiag",   gcc_cdiag_length_specs,  gcc_cdiag_char_table, "q+#", NULL,
    951     gcc_cdiag_flag_specs, gcc_cdiag_flag_pairs,
    952     FMT_FLAG_ARG_CONVERT|FMT_FLAG_M_OK,
    953     0, 0, 'p', 0, 'L', 0,
    954     NULL, &integer_type_node, format_type_error
    955   },
    956   { "gcc_cxxdiag",   gcc_cxxdiag_length_specs,  gcc_cxxdiag_char_table, "q+#", NULL,
    957     gcc_cxxdiag_flag_specs, gcc_cxxdiag_flag_pairs,
    958     FMT_FLAG_ARG_CONVERT|FMT_FLAG_M_OK,
    959     0, 0, 'p', 0, 'L', 0,
    960     NULL, &integer_type_node, format_type_error
    961   },
    962   { "gcc_gfc", gcc_gfc_length_specs, gcc_gfc_char_table, "q+#", NULL,
    963     gcc_gfc_flag_specs, gcc_gfc_flag_pairs,
    964     FMT_FLAG_ARG_CONVERT|FMT_FLAG_M_OK,
    965     0, 0, 0, 0, 0, 0,
    966     NULL, NULL, format_type_error
    967   },
    968   { "gcc_dump_printf",   gcc_dump_printf_length_specs,
    969     gcc_dump_printf_char_table, "q+#", NULL,
    970     gcc_dump_printf_flag_specs, gcc_dump_printf_flag_pairs,
    971     FMT_FLAG_ARG_CONVERT,
    972     0, 0, 'p', 0, 'L', 0,
    973     NULL, &integer_type_node
    974   },
    975   { "NSString",   NULL,  NULL, NULL, NULL,
    976     NULL, NULL,
    977     FMT_FLAG_ARG_CONVERT|FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL, 0, 0, 0, 0, 0, 0,
    978     NULL, NULL, format_type_error
    979   },
    980   { "gnu_scanf",    scanf_length_specs,   scan_char_table,  "*'I", NULL,
    981     scanf_flag_specs, scanf_flag_pairs,
    982     FMT_FLAG_ARG_CONVERT|FMT_FLAG_SCANF_A_KLUDGE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_ZERO_WIDTH_BAD|FMT_FLAG_DOLLAR_GAP_POINTER_OK,
    983     'w', 0, 0, '*', 'L', 'm',
    984     NULL, NULL, format_type_error
    985   },
    986   { "gnu_strftime", NULL,                 time_char_table,  "_-0^#", "EO",
    987     strftime_flag_specs, strftime_flag_pairs,
    988     FMT_FLAG_FANCY_PERCENT_OK|FMT_FLAG_M_OK, 'w', 0, 0, 0, 0, 0,
    989     NULL, NULL, format_type_error
    990   },
    991   { "gnu_strfmon",  strfmon_length_specs, monetary_char_table, "=^+(!-", NULL,
    992     strfmon_flag_specs, strfmon_flag_pairs,
    993     FMT_FLAG_ARG_CONVERT, 'w', '#', 'p', 0, 'L', 0,
    994     NULL, NULL, format_type_error
    995   },
    996   { "gnu_syslog",   printf_length_specs,  print_char_table, " +#0-'I", NULL,
    997     printf_flag_specs, printf_flag_pairs,
    998     FMT_FLAG_ARG_CONVERT|FMT_FLAG_DOLLAR_MULTIPLE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_EMPTY_PREC_OK|FMT_FLAG_M_OK,
    999     'w', 0, 'p', 0, 'L', 0,
   1000     &integer_type_node, &integer_type_node, printf_format_type
   1001   },
   1002 };
   1003 
   1004 /* This layer of indirection allows GCC to reassign format_types with
   1005    new data if necessary, while still allowing the original data to be
   1006    const.  */
   1007 static const format_kind_info *format_types = format_types_orig;
   1008 /* We can modify this one.  We also add target-specific format types
   1009    to the end of the array.  */
   1010 static format_kind_info *dynamic_format_types;
   1011 
   1012 static int n_format_types = ARRAY_SIZE (format_types_orig);
   1013 
   1014 /* Structure detailing the results of checking a format function call
   1015    where the format expression may be a conditional expression with
   1016    many leaves resulting from nested conditional expressions.  */
   1017 struct format_check_results
   1018 {
   1019   /* Number of leaves of the format argument that could not be checked
   1020      as they were not string literals.  */
   1021   int number_non_literal;
   1022   /* Number of leaves of the format argument that were null pointers or
   1023      string literals, but had extra format arguments.  */
   1024   int number_extra_args;
   1025   location_t extra_arg_loc;
   1026   /* Number of leaves of the format argument that were null pointers or
   1027      string literals, but had extra format arguments and used $ operand
   1028      numbers.  */
   1029   int number_dollar_extra_args;
   1030   /* Number of leaves of the format argument that were wide string
   1031      literals.  */
   1032   int number_wide;
   1033   /* Number of leaves of the format argument that are not array of "char".  */
   1034   int number_non_char;
   1035   /* Number of leaves of the format argument that were empty strings.  */
   1036   int number_empty;
   1037   /* Number of leaves of the format argument that were unterminated
   1038      strings.  */
   1039   int number_unterminated;
   1040   /* Number of leaves of the format argument that were not counted above.  */
   1041   int number_other;
   1042   /* Location of the format string.  */
   1043   location_t format_string_loc;
   1044 };
   1045 
   1046 struct format_check_context
   1047 {
   1048   format_check_results *res;
   1049   function_format_info *info;
   1050   tree params;
   1051   vec<location_t> *arglocs;
   1052 };
   1053 
   1054 /* Return the format name (as specified in the original table) for the format
   1055    type indicated by format_num.  */
   1056 static const char *
   1057 format_name (int format_num)
   1058 {
   1059   if (format_num >= 0 && format_num < n_format_types)
   1060     return format_types[format_num].name;
   1061   gcc_unreachable ();
   1062 }
   1063 
   1064 /* Return the format flags (as specified in the original table) for the format
   1065    type indicated by format_num.  */
   1066 static int
   1067 format_flags (int format_num)
   1068 {
   1069   if (format_num >= 0 && format_num < n_format_types)
   1070     return format_types[format_num].flags;
   1071   gcc_unreachable ();
   1072 }
   1073 
   1074 static void check_format_info (function_format_info *, tree,
   1075 			       vec<location_t> *);
   1076 static void check_format_arg (void *, tree, unsigned HOST_WIDE_INT);
   1077 static void check_format_info_main (format_check_results *,
   1078 				    function_format_info *, const char *,
   1079 				    location_t, tree,
   1080 				    int, tree,
   1081 				    unsigned HOST_WIDE_INT,
   1082 				    object_allocator<format_wanted_type> &,
   1083 				    vec<location_t> *);
   1084 
   1085 static void init_dollar_format_checking (int, tree);
   1086 static int maybe_read_dollar_number (const char **, int,
   1087 				     tree, tree *, const format_kind_info *);
   1088 static bool avoid_dollar_number (const char *);
   1089 static void finish_dollar_format_checking (format_check_results *, int);
   1090 
   1091 static const format_flag_spec *get_flag_spec (const format_flag_spec *,
   1092 					      int, const char *);
   1093 
   1094 static void check_format_types (const substring_loc &fmt_loc,
   1095 				format_wanted_type *,
   1096 				const format_kind_info *fki,
   1097 				int offset_to_type_start,
   1098 				char conversion_char,
   1099 				vec<location_t> *arglocs);
   1100 static void format_type_warning (const substring_loc &fmt_loc,
   1101 				 location_t param_loc,
   1102 				 format_wanted_type *, tree,
   1103 				 tree,
   1104 				 const format_kind_info *fki,
   1105 				 int offset_to_type_start,
   1106 				 char conversion_char);
   1107 
   1108 /* Decode a format type from a string, returning the type, or
   1109    format_type_error if not valid, in which case the caller should
   1110    print an error message.  On success, when IS_RAW is non-null, set
   1111    *IS_RAW when the format type corresponds to a GCC "raw" diagnostic
   1112    formatting function and clear it otherwise.  */
   1113 static format_type
   1114 decode_format_type (const char *s, bool *is_raw /* = NULL */)
   1115 {
   1116   bool is_raw_buf;
   1117 
   1118   if (!is_raw)
   1119     is_raw = &is_raw_buf;
   1120 
   1121   *is_raw = false;
   1122 
   1123   s = convert_format_name_to_system_name (s);
   1124 
   1125   size_t slen = strlen (s);
   1126   for (int i = 0; i < n_format_types; i++)
   1127     {
   1128       /* Check for a match with no underscores.  */
   1129       if (!strcmp (s, format_types[i].name))
   1130 	return static_cast<format_type> (i);
   1131 
   1132       /* Check for leading and trailing underscores.  */
   1133       size_t alen = strlen (format_types[i].name);
   1134       if (slen == alen + 4 && s[0] == '_' && s[1] == '_'
   1135 	  && s[slen - 1] == '_' && s[slen - 2] == '_'
   1136 	  && !strncmp (s + 2, format_types[i].name, alen))
   1137 	return static_cast<format_type>(i);
   1138 
   1139       /* Check for the "_raw" suffix and no leading underscores.  */
   1140       if (slen == alen + 4
   1141 	  && !strncmp (s, format_types[i].name, alen)
   1142 	  && !strcmp (s + alen, "_raw"))
   1143 	{
   1144 	  *is_raw = true;
   1145 	  return static_cast<format_type>(i);
   1146 	}
   1147 
   1148       /* Check for the "_raw__" suffix and leading underscores.  */
   1149       if (slen == alen + 8 && s[0] == '_' && s[1] == '_'
   1150 	  && !strncmp (s + 2, format_types[i].name, alen)
   1151 	  && !strcmp (s + 2 + alen, "_raw__"))
   1152 	{
   1153 	  *is_raw = true;
   1154 	  return static_cast<format_type>(i);
   1155 	}
   1156     }
   1157 
   1158   return format_type_error;
   1159 }
   1160 
   1161 
   1162 /* Check the argument list of a call to printf, scanf, etc.
   1164    ATTRS are the attributes on the function type.  There are NARGS argument
   1165    values in the array ARGARRAY.
   1166    Also, if -Wsuggest-attribute=format,
   1167    warn for calls to vprintf or vscanf in functions with no such format
   1168    attribute themselves.  */
   1169 
   1170 void
   1171 check_function_format (const_tree fntype, tree attrs, int nargs,
   1172 		       tree *argarray, vec<location_t> *arglocs)
   1173 {
   1174   tree a;
   1175 
   1176   tree atname = get_identifier ("format");
   1177 
   1178   /* See if this function has any format attributes.  */
   1179   for (a = attrs; a; a = TREE_CHAIN (a))
   1180     {
   1181       if (is_attribute_p ("format", get_attribute_name (a)))
   1182 	{
   1183 	  /* Yup; check it.  */
   1184 	  function_format_info info;
   1185 	  decode_format_attr (fntype, atname, TREE_VALUE (a), &info,
   1186 			      /*validated=*/true);
   1187 	  if (warn_format)
   1188 	    {
   1189 	      /* FIXME: Rewrite all the internal functions in this file
   1190 		 to use the ARGARRAY directly instead of constructing this
   1191 		 temporary list.  */
   1192 	      tree params = NULL_TREE;
   1193 	      int i;
   1194 	      for (i = nargs - 1; i >= 0; i--)
   1195 		params = tree_cons (NULL_TREE, argarray[i], params);
   1196 	      check_format_info (&info, params, arglocs);
   1197 	    }
   1198 	  const format_kind_info *fi = &format_types[info.format_type];
   1199 
   1200 	  /* Attempt to detect whether the current function might benefit
   1201 	     from the format attribute if the called function is decorated
   1202 	     with it.  Avoid using calls with string literal formats for
   1203 	     guidance since those are unlikely to be viable candidates.  */
   1204 	  if (warn_suggest_attribute_format
   1205 	      && current_function_decl != NULL_TREE
   1206 	      && info.first_arg_num == 0
   1207 	      && (fi->flags & (int) FMT_FLAG_ARG_CONVERT)
   1208 	      /* c_strlen will fail for a function parameter but succeed
   1209 		 for a literal or constant array.  */
   1210 	      && !c_strlen (argarray[info.format_num - 1], 1))
   1211 	    {
   1212 	      tree c;
   1213 	      for (c = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
   1214 		   c;
   1215 		   c = TREE_CHAIN (c))
   1216 		{
   1217 		  if (!is_attribute_p ("format", TREE_PURPOSE (c)))
   1218 		     continue;
   1219 		  int format_type = decode_format_type (
   1220 		      IDENTIFIER_POINTER (TREE_VALUE (TREE_VALUE (c))));
   1221 		  if (format_type == format_type_error)
   1222 		     continue;
   1223 		  if (format_type == info.format_type ||
   1224 		      format_type == fi->parent_format_type)
   1225 		    break;
   1226 		}
   1227 	      if (c == NULL_TREE)
   1228 		{
   1229 		  /* Check if the current function has a parameter to which
   1230 		     the format attribute could be attached; if not, it
   1231 		     can't be a candidate for a format attribute, despite
   1232 		     the vprintf-like or vscanf-like call.  */
   1233 		  tree args;
   1234 		  for (args = DECL_ARGUMENTS (current_function_decl);
   1235 		       args != 0;
   1236 		       args = DECL_CHAIN (args))
   1237 		    {
   1238 		      if (TREE_CODE (TREE_TYPE (args)) == POINTER_TYPE
   1239 			  && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (args)))
   1240 			      == char_type_node))
   1241 			break;
   1242 		    }
   1243 		  if (args != 0)
   1244 		    warning (OPT_Wsuggest_attribute_format, "function %qD "
   1245 			     "might be a candidate for %qs format attribute",
   1246 			     current_function_decl,
   1247 			     format_types[info.format_type].name);
   1248 		}
   1249 	    }
   1250 	}
   1251     }
   1252 }
   1253 
   1254 
   1255 /* Variables used by the checking of $ operand number formats.  */
   1256 static char *dollar_arguments_used = NULL;
   1257 static char *dollar_arguments_pointer_p = NULL;
   1258 static int dollar_arguments_alloc = 0;
   1259 static int dollar_arguments_count;
   1260 static int dollar_first_arg_num;
   1261 static int dollar_max_arg_used;
   1262 static int dollar_format_warned;
   1263 
   1264 /* Initialize the checking for a format string that may contain $
   1265    parameter number specifications; we will need to keep track of whether
   1266    each parameter has been used.  FIRST_ARG_NUM is the number of the first
   1267    argument that is a parameter to the format, or 0 for a vprintf-style
   1268    function; PARAMS is the list of arguments starting at this argument.  */
   1269 
   1270 static void
   1271 init_dollar_format_checking (int first_arg_num, tree params)
   1272 {
   1273   tree oparams = params;
   1274 
   1275   dollar_first_arg_num = first_arg_num;
   1276   dollar_arguments_count = 0;
   1277   dollar_max_arg_used = 0;
   1278   dollar_format_warned = 0;
   1279   if (first_arg_num > 0)
   1280     {
   1281       while (params)
   1282 	{
   1283 	  dollar_arguments_count++;
   1284 	  params = TREE_CHAIN (params);
   1285 	}
   1286     }
   1287   if (dollar_arguments_alloc < dollar_arguments_count)
   1288     {
   1289       free (dollar_arguments_used);
   1290       free (dollar_arguments_pointer_p);
   1291       dollar_arguments_alloc = dollar_arguments_count;
   1292       dollar_arguments_used = XNEWVEC (char, dollar_arguments_alloc);
   1293       dollar_arguments_pointer_p = XNEWVEC (char, dollar_arguments_alloc);
   1294     }
   1295   if (dollar_arguments_alloc)
   1296     {
   1297       memset (dollar_arguments_used, 0, dollar_arguments_alloc);
   1298       if (first_arg_num > 0)
   1299 	{
   1300 	  int i = 0;
   1301 	  params = oparams;
   1302 	  while (params)
   1303 	    {
   1304 	      dollar_arguments_pointer_p[i] = (TREE_CODE (TREE_TYPE (TREE_VALUE (params)))
   1305 					       == POINTER_TYPE);
   1306 	      params = TREE_CHAIN (params);
   1307 	      i++;
   1308 	    }
   1309 	}
   1310     }
   1311 }
   1312 
   1313 
   1314 /* Look for a decimal number followed by a $ in *FORMAT.  If DOLLAR_NEEDED
   1315    is set, it is an error if one is not found; otherwise, it is OK.  If
   1316    such a number is found, check whether it is within range and mark that
   1317    numbered operand as being used for later checking.  Returns the operand
   1318    number if found and within range, zero if no such number was found and
   1319    this is OK, or -1 on error.  PARAMS points to the first operand of the
   1320    format; PARAM_PTR is made to point to the parameter referred to.  If
   1321    a $ format is found, *FORMAT is updated to point just after it.  */
   1322 
   1323 static int
   1324 maybe_read_dollar_number (const char **format,
   1325 			  int dollar_needed, tree params, tree *param_ptr,
   1326 			  const format_kind_info *fki)
   1327 {
   1328   int argnum;
   1329   int overflow_flag;
   1330   const char *fcp = *format;
   1331   if (!ISDIGIT (*fcp))
   1332     {
   1333       if (dollar_needed)
   1334 	{
   1335 	  warning (OPT_Wformat_, "missing $ operand number in format");
   1336 	  return -1;
   1337 	}
   1338       else
   1339 	return 0;
   1340     }
   1341   argnum = 0;
   1342   overflow_flag = 0;
   1343   while (ISDIGIT (*fcp))
   1344     {
   1345       HOST_WIDE_INT nargnum
   1346 	= HOST_WIDE_INT_UC (10) * argnum + (*fcp - '0');
   1347       if ((int) nargnum != nargnum)
   1348 	overflow_flag = 1;
   1349       argnum = nargnum;
   1350       fcp++;
   1351     }
   1352   if (*fcp != '$')
   1353     {
   1354       if (dollar_needed)
   1355 	{
   1356 	  warning (OPT_Wformat_, "missing $ operand number in format");
   1357 	  return -1;
   1358 	}
   1359       else
   1360 	return 0;
   1361     }
   1362   *format = fcp + 1;
   1363   if (pedantic && !dollar_format_warned)
   1364     {
   1365       warning (OPT_Wformat_, "%s does not support %%n$ operand number formats",
   1366 	       C_STD_NAME (STD_EXT));
   1367       dollar_format_warned = 1;
   1368     }
   1369   if (overflow_flag || argnum == 0
   1370       || (dollar_first_arg_num && argnum > dollar_arguments_count))
   1371     {
   1372       warning (OPT_Wformat_, "operand number out of range in format");
   1373       return -1;
   1374     }
   1375   if (argnum > dollar_max_arg_used)
   1376     dollar_max_arg_used = argnum;
   1377   /* For vprintf-style functions we may need to allocate more memory to
   1378      track which arguments are used.  */
   1379   while (dollar_arguments_alloc < dollar_max_arg_used)
   1380     {
   1381       int nalloc;
   1382       nalloc = 2 * dollar_arguments_alloc + 16;
   1383       dollar_arguments_used = XRESIZEVEC (char, dollar_arguments_used,
   1384 					  nalloc);
   1385       dollar_arguments_pointer_p = XRESIZEVEC (char, dollar_arguments_pointer_p,
   1386 					       nalloc);
   1387       memset (dollar_arguments_used + dollar_arguments_alloc, 0,
   1388 	      nalloc - dollar_arguments_alloc);
   1389       dollar_arguments_alloc = nalloc;
   1390     }
   1391   if (!(fki->flags & (int) FMT_FLAG_DOLLAR_MULTIPLE)
   1392       && dollar_arguments_used[argnum - 1] == 1)
   1393     {
   1394       dollar_arguments_used[argnum - 1] = 2;
   1395       warning (OPT_Wformat_, "format argument %d used more than once in %s format",
   1396 	       argnum, fki->name);
   1397     }
   1398   else
   1399     dollar_arguments_used[argnum - 1] = 1;
   1400   if (dollar_first_arg_num)
   1401     {
   1402       int i;
   1403       *param_ptr = params;
   1404       for (i = 1; i < argnum && *param_ptr != 0; i++)
   1405 	*param_ptr = TREE_CHAIN (*param_ptr);
   1406 
   1407       /* This case shouldn't be caught here.  */
   1408       gcc_assert (*param_ptr);
   1409     }
   1410   else
   1411     *param_ptr = 0;
   1412   return argnum;
   1413 }
   1414 
   1415 /* Ensure that FORMAT does not start with a decimal number followed by
   1416    a $; give a diagnostic and return true if it does, false otherwise.  */
   1417 
   1418 static bool
   1419 avoid_dollar_number (const char *format)
   1420 {
   1421   if (!ISDIGIT (*format))
   1422     return false;
   1423   while (ISDIGIT (*format))
   1424     format++;
   1425   if (*format == '$')
   1426     {
   1427       warning (OPT_Wformat_,
   1428 	       "%<$%>operand number used after format without operand number");
   1429       return true;
   1430     }
   1431   return false;
   1432 }
   1433 
   1434 
   1435 /* Finish the checking for a format string that used $ operand number formats
   1436    instead of non-$ formats.  We check for unused operands before used ones
   1437    (a serious error, since the implementation of the format function
   1438    can't know what types to pass to va_arg to find the later arguments).
   1439    and for unused operands at the end of the format (if we know how many
   1440    arguments the format had, so not for vprintf).  If there were operand
   1441    numbers out of range on a non-vprintf-style format, we won't have reached
   1442    here.  If POINTER_GAP_OK, unused arguments are OK if all arguments are
   1443    pointers.  */
   1444 
   1445 static void
   1446 finish_dollar_format_checking (format_check_results *res, int pointer_gap_ok)
   1447 {
   1448   int i;
   1449   bool found_pointer_gap = false;
   1450   for (i = 0; i < dollar_max_arg_used; i++)
   1451     {
   1452       if (!dollar_arguments_used[i])
   1453 	{
   1454 	  if (pointer_gap_ok && (dollar_first_arg_num == 0
   1455 				 || dollar_arguments_pointer_p[i]))
   1456 	    found_pointer_gap = true;
   1457 	  else
   1458 	    warning_at (res->format_string_loc, OPT_Wformat_,
   1459 			"format argument %d unused before used argument %d "
   1460 			"in %<$%>-style format",
   1461 			i + 1, dollar_max_arg_used);
   1462 	}
   1463     }
   1464   if (found_pointer_gap
   1465       || (dollar_first_arg_num
   1466 	  && dollar_max_arg_used < dollar_arguments_count))
   1467     {
   1468       res->number_other--;
   1469       res->number_dollar_extra_args++;
   1470     }
   1471 }
   1472 
   1473 
   1474 /* Retrieve the specification for a format flag.  SPEC contains the
   1475    specifications for format flags for the applicable kind of format.
   1476    FLAG is the flag in question.  If PREDICATES is NULL, the basic
   1477    spec for that flag must be retrieved and must exist.  If
   1478    PREDICATES is not NULL, it is a string listing possible predicates
   1479    for the spec entry; if an entry predicated on any of these is
   1480    found, it is returned, otherwise NULL is returned.  */
   1481 
   1482 static const format_flag_spec *
   1483 get_flag_spec (const format_flag_spec *spec, int flag, const char *predicates)
   1484 {
   1485   int i;
   1486   for (i = 0; spec[i].flag_char != 0; i++)
   1487     {
   1488       if (spec[i].flag_char != flag)
   1489 	continue;
   1490       if (predicates != NULL)
   1491 	{
   1492 	  if (spec[i].predicate != 0
   1493 	      && strchr (predicates, spec[i].predicate) != 0)
   1494 	    return &spec[i];
   1495 	}
   1496       else if (spec[i].predicate == 0)
   1497 	return &spec[i];
   1498     }
   1499   gcc_assert (predicates);
   1500   return NULL;
   1501 }
   1502 
   1503 
   1504 /* Check the argument list of a call to printf, scanf, etc.
   1505    INFO points to the function_format_info structure.
   1506    PARAMS is the list of argument values.  */
   1507 
   1508 static void
   1509 check_format_info (function_format_info *info, tree params,
   1510 		   vec<location_t> *arglocs)
   1511 {
   1512   format_check_context format_ctx;
   1513   unsigned HOST_WIDE_INT arg_num;
   1514   tree format_tree;
   1515   format_check_results res;
   1516   /* Skip to format argument.  If the argument isn't available, there's
   1517      no work for us to do; prototype checking will catch the problem.  */
   1518   for (arg_num = 1; ; ++arg_num)
   1519     {
   1520       if (params == 0)
   1521 	return;
   1522       if (arg_num == info->format_num)
   1523 	break;
   1524       params = TREE_CHAIN (params);
   1525     }
   1526   format_tree = TREE_VALUE (params);
   1527   params = TREE_CHAIN (params);
   1528   if (format_tree == 0)
   1529     return;
   1530 
   1531   res.number_non_literal = 0;
   1532   res.number_extra_args = 0;
   1533   res.extra_arg_loc = UNKNOWN_LOCATION;
   1534   res.number_dollar_extra_args = 0;
   1535   res.number_wide = 0;
   1536   res.number_non_char = 0;
   1537   res.number_empty = 0;
   1538   res.number_unterminated = 0;
   1539   res.number_other = 0;
   1540   res.format_string_loc = input_location;
   1541 
   1542   format_ctx.res = &res;
   1543   format_ctx.info = info;
   1544   format_ctx.params = params;
   1545   format_ctx.arglocs = arglocs;
   1546 
   1547   check_function_arguments_recurse (check_format_arg, &format_ctx,
   1548 				    format_tree, arg_num, OPT_Wformat_);
   1549 
   1550   location_t loc = format_ctx.res->format_string_loc;
   1551 
   1552   if (res.number_non_literal > 0)
   1553     {
   1554       /* Functions taking a va_list normally pass a non-literal format
   1555 	 string.  These functions typically are declared with
   1556 	 first_arg_num == 0, so avoid warning in those cases.  */
   1557       if (!(format_types[info->format_type].flags & (int) FMT_FLAG_ARG_CONVERT))
   1558 	{
   1559 	  /* For strftime-like formats, warn for not checking the format
   1560 	     string; but there are no arguments to check.  */
   1561 	  warning_at (loc, OPT_Wformat_nonliteral,
   1562 		      "format not a string literal, format string not checked");
   1563 	}
   1564       else if (info->first_arg_num != 0)
   1565 	{
   1566 	  /* If there are no arguments for the format at all, we may have
   1567 	     printf (foo) which is likely to be a security hole.  */
   1568 	  while (arg_num + 1 < info->first_arg_num)
   1569 	    {
   1570 	      if (params == 0)
   1571 		break;
   1572 	      params = TREE_CHAIN (params);
   1573 	      ++arg_num;
   1574 	    }
   1575 	  if (params == 0 && warn_format_security)
   1576 	    warning_at (loc, OPT_Wformat_security,
   1577 			"format not a string literal and no format arguments");
   1578 	  else if (params == 0 && warn_format_nonliteral)
   1579 	    warning_at (loc, OPT_Wformat_nonliteral,
   1580 			"format not a string literal and no format arguments");
   1581 	  else
   1582 	    warning_at (loc, OPT_Wformat_nonliteral,
   1583 			"format not a string literal, argument types not checked");
   1584 	}
   1585     }
   1586 
   1587   /* If there were extra arguments to the format, normally warn.  However,
   1588      the standard does say extra arguments are ignored, so in the specific
   1589      case where we have multiple leaves (conditional expressions or
   1590      ngettext) allow extra arguments if at least one leaf didn't have extra
   1591      arguments, but was otherwise OK (either non-literal or checked OK).
   1592      If the format is an empty string, this should be counted similarly to the
   1593      case of extra format arguments.  */
   1594   if (res.number_extra_args > 0 && res.number_non_literal == 0
   1595       && res.number_other == 0)
   1596     {
   1597       if (res.extra_arg_loc == UNKNOWN_LOCATION)
   1598 	res.extra_arg_loc = loc;
   1599       warning_at (res.extra_arg_loc, OPT_Wformat_extra_args,
   1600 		  "too many arguments for format");
   1601     }
   1602   if (res.number_dollar_extra_args > 0 && res.number_non_literal == 0
   1603       && res.number_other == 0)
   1604     warning_at (loc, OPT_Wformat_extra_args,
   1605 		"unused arguments in %<$%>-style format");
   1606   if (res.number_empty > 0 && res.number_non_literal == 0
   1607       && res.number_other == 0)
   1608     warning_at (loc, OPT_Wformat_zero_length, "zero-length %s format string",
   1609 	     format_types[info->format_type].name);
   1610 
   1611   if (res.number_wide > 0)
   1612     warning_at (loc, OPT_Wformat_, "format is a wide character string");
   1613 
   1614   if (res.number_non_char > 0)
   1615     warning_at (loc, OPT_Wformat_,
   1616 		"format string is not an array of type %qs", "char");
   1617 
   1618   if (res.number_unterminated > 0)
   1619     warning_at (loc, OPT_Wformat_, "unterminated format string");
   1620 }
   1621 
   1622 /* Callback from check_function_arguments_recurse to check a
   1623    format string.  FORMAT_TREE is the format parameter.  ARG_NUM
   1624    is the number of the format argument.  CTX points to a
   1625    format_check_context.  */
   1626 
   1627 static void
   1628 check_format_arg (void *ctx, tree format_tree,
   1629 		  unsigned HOST_WIDE_INT arg_num)
   1630 {
   1631   format_check_context *format_ctx = (format_check_context *) ctx;
   1632   format_check_results *res = format_ctx->res;
   1633   function_format_info *info = format_ctx->info;
   1634   tree params = format_ctx->params;
   1635   vec<location_t> *arglocs = format_ctx->arglocs;
   1636 
   1637   int format_length;
   1638   HOST_WIDE_INT offset;
   1639   const char *format_chars;
   1640   tree array_size = 0;
   1641   tree array_init;
   1642 
   1643   location_t fmt_param_loc = EXPR_LOC_OR_LOC (format_tree, input_location);
   1644 
   1645   /* Pull out a constant value if the front end didn't, and handle location
   1646      wrappers.  */
   1647   format_tree = fold_for_warn (format_tree);
   1648   STRIP_NOPS (format_tree);
   1649 
   1650   if (integer_zerop (format_tree))
   1651     {
   1652       /* Skip to first argument to check, so we can see if this format
   1653 	 has any arguments (it shouldn't).  */
   1654       while (arg_num + 1 < info->first_arg_num)
   1655 	{
   1656 	  if (params == 0)
   1657 	    return;
   1658 	  params = TREE_CHAIN (params);
   1659 	  ++arg_num;
   1660 	}
   1661 
   1662       if (params == 0)
   1663 	res->number_other++;
   1664       else
   1665 	{
   1666 	  if (res->number_extra_args == 0)
   1667 	    res->extra_arg_loc = EXPR_LOC_OR_LOC (TREE_VALUE (params),
   1668 						  input_location);
   1669 	  res->number_extra_args++;
   1670 	}
   1671       return;
   1672     }
   1673 
   1674   offset = 0;
   1675   if (TREE_CODE (format_tree) == POINTER_PLUS_EXPR)
   1676     {
   1677       tree arg0, arg1;
   1678 
   1679       arg0 = TREE_OPERAND (format_tree, 0);
   1680       arg1 = TREE_OPERAND (format_tree, 1);
   1681       STRIP_NOPS (arg0);
   1682       STRIP_NOPS (arg1);
   1683       if (TREE_CODE (arg1) == INTEGER_CST)
   1684 	format_tree = arg0;
   1685       else
   1686 	{
   1687 	  res->number_non_literal++;
   1688 	  return;
   1689 	}
   1690       /* POINTER_PLUS_EXPR offsets are to be interpreted signed.  */
   1691       if (!cst_and_fits_in_hwi (arg1))
   1692 	{
   1693 	  res->number_non_literal++;
   1694 	  return;
   1695 	}
   1696       offset = int_cst_value (arg1);
   1697     }
   1698   if (TREE_CODE (format_tree) != ADDR_EXPR)
   1699     {
   1700       res->number_non_literal++;
   1701       return;
   1702     }
   1703   res->format_string_loc = EXPR_LOC_OR_LOC (format_tree, input_location);
   1704   format_tree = TREE_OPERAND (format_tree, 0);
   1705   if (format_types[info->format_type].flags
   1706       & (int) FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL)
   1707     {
   1708       bool objc_str = (info->format_type == gcc_objc_string_format_type);
   1709       /* We cannot examine this string here - but we can check that it is
   1710 	 a valid type.  */
   1711       if (TREE_CODE (format_tree) != CONST_DECL
   1712 	  || !((objc_str && objc_string_ref_type_p (TREE_TYPE (format_tree)))
   1713 		|| (*targetcm.string_object_ref_type_p)
   1714 				     ((const_tree) TREE_TYPE (format_tree))))
   1715 	{
   1716 	  res->number_non_literal++;
   1717 	  return;
   1718 	}
   1719       /* Skip to first argument to check.  */
   1720       while (arg_num + 1 < info->first_arg_num)
   1721 	{
   1722 	  if (params == 0)
   1723 	    return;
   1724 	  params = TREE_CHAIN (params);
   1725 	  ++arg_num;
   1726 	}
   1727       /* So, we have a valid literal string object and one or more params.
   1728 	 We need to use an external helper to parse the string into format
   1729 	 info.  For Objective-C variants we provide the resource within the
   1730 	 objc tree, for target variants, via a hook.  */
   1731       if (objc_str)
   1732 	objc_check_format_arg (format_tree, params);
   1733       else if (targetcm.check_string_object_format_arg)
   1734 	(*targetcm.check_string_object_format_arg) (format_tree, params);
   1735       /* Else we can't handle it and retire quietly.  */
   1736       return;
   1737     }
   1738   if (TREE_CODE (format_tree) == ARRAY_REF
   1739       && tree_fits_shwi_p (TREE_OPERAND (format_tree, 1))
   1740       && (offset += tree_to_shwi (TREE_OPERAND (format_tree, 1))) >= 0)
   1741     format_tree = TREE_OPERAND (format_tree, 0);
   1742   if (offset < 0)
   1743     {
   1744       res->number_non_literal++;
   1745       return;
   1746     }
   1747   if (VAR_P (format_tree)
   1748       && TREE_CODE (TREE_TYPE (format_tree)) == ARRAY_TYPE
   1749       && (array_init = decl_constant_value (format_tree)) != format_tree
   1750       && TREE_CODE (array_init) == STRING_CST)
   1751     {
   1752       /* Extract the string constant initializer.  Note that this may include
   1753 	 a trailing NUL character that is not in the array (e.g.
   1754 	 const char a[3] = "foo";).  */
   1755       array_size = DECL_SIZE_UNIT (format_tree);
   1756       format_tree = array_init;
   1757     }
   1758   if (TREE_CODE (format_tree) != STRING_CST)
   1759     {
   1760       res->number_non_literal++;
   1761       return;
   1762     }
   1763   tree underlying_type
   1764     = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (format_tree)));
   1765   if (underlying_type != char_type_node
   1766       && !(flag_char8_t && underlying_type == char8_type_node))
   1767     {
   1768       if (underlying_type == char16_type_node
   1769 	  || underlying_type == char32_type_node
   1770 	  || underlying_type == wchar_type_node)
   1771 	res->number_wide++;
   1772       else
   1773 	res->number_non_char++;
   1774       return;
   1775     }
   1776   format_chars = TREE_STRING_POINTER (format_tree);
   1777   format_length = TREE_STRING_LENGTH (format_tree);
   1778   if (array_size != 0)
   1779     {
   1780       /* Variable length arrays can't be initialized.  */
   1781       gcc_assert (TREE_CODE (array_size) == INTEGER_CST);
   1782 
   1783       if (tree_fits_shwi_p (array_size))
   1784 	{
   1785 	  HOST_WIDE_INT array_size_value = tree_to_shwi (array_size);
   1786 	  if (array_size_value > 0
   1787 	      && array_size_value == (int) array_size_value
   1788 	      && format_length > array_size_value)
   1789 	    format_length = array_size_value;
   1790 	}
   1791     }
   1792   if (offset)
   1793     {
   1794       if (offset >= format_length)
   1795 	{
   1796 	  res->number_non_literal++;
   1797 	  return;
   1798 	}
   1799       format_chars += offset;
   1800       format_length -= offset;
   1801     }
   1802   if (format_length < 1 || format_chars[--format_length] != 0)
   1803     {
   1804       res->number_unterminated++;
   1805       return;
   1806     }
   1807   if (format_length == 0)
   1808     {
   1809       res->number_empty++;
   1810       return;
   1811     }
   1812 
   1813   /* Skip to first argument to check.  */
   1814   while (arg_num + 1 < info->first_arg_num)
   1815     {
   1816       if (params == 0)
   1817 	return;
   1818       params = TREE_CHAIN (params);
   1819       ++arg_num;
   1820     }
   1821   /* Provisionally increment res->number_other; check_format_info_main
   1822      will decrement it if it finds there are extra arguments, but this way
   1823      need not adjust it for every return.  */
   1824   res->number_other++;
   1825   object_allocator <format_wanted_type> fwt_pool ("format_wanted_type pool");
   1826   check_format_info_main (res, info, format_chars, fmt_param_loc, format_tree,
   1827 			  format_length, params, arg_num, fwt_pool, arglocs);
   1828 }
   1829 
   1830 /* Support class for argument_parser and check_format_info_main.
   1831    Tracks any flag characters that have been applied to the
   1832    current argument.  */
   1833 
   1834 class flag_chars_t
   1835 {
   1836  public:
   1837   flag_chars_t ();
   1838   bool has_char_p (char ch) const;
   1839   void add_char (char ch);
   1840   void validate (const format_kind_info *fki,
   1841 		 const format_char_info *fci,
   1842 		 const format_flag_spec *flag_specs,
   1843 		 const char * const format_chars,
   1844 		 tree format_string_cst,
   1845 		 location_t format_string_loc,
   1846 		 const char * const orig_format_chars,
   1847 		 char format_char,
   1848 		 bool quoted);
   1849   int get_alloc_flag (const format_kind_info *fki);
   1850   int assignment_suppression_p (const format_kind_info *fki);
   1851 
   1852  private:
   1853   char m_flag_chars[256];
   1854 };
   1855 
   1856 /* Support struct for argument_parser and check_format_info_main.
   1857    Encapsulates any length modifier applied to the current argument.  */
   1858 
   1859 class length_modifier
   1860 {
   1861 public:
   1862   length_modifier ()
   1863   : chars (NULL), val (FMT_LEN_none), std (STD_C89),
   1864     scalar_identity_flag (0)
   1865   {
   1866   }
   1867 
   1868   length_modifier (const char *chars_,
   1869 		   enum format_lengths val_,
   1870 		   enum format_std_version std_,
   1871 		   int scalar_identity_flag_)
   1872   : chars (chars_), val (val_), std (std_),
   1873     scalar_identity_flag (scalar_identity_flag_)
   1874   {
   1875   }
   1876 
   1877   const char *chars;
   1878   enum format_lengths val;
   1879   enum format_std_version std;
   1880   int scalar_identity_flag;
   1881 };
   1882 
   1883 /* Parsing one argument within a format string.  */
   1884 
   1885 class argument_parser
   1886 {
   1887  public:
   1888   argument_parser (function_format_info *info, const char *&format_chars,
   1889 		   tree format_string_cst,
   1890 		   const char * const orig_format_chars,
   1891 		   location_t format_string_loc, flag_chars_t &flag_chars,
   1892 		   int &has_operand_number, tree first_fillin_param,
   1893 		   object_allocator <format_wanted_type> &fwt_pool_,
   1894 		   vec<location_t> *arglocs);
   1895 
   1896   bool read_any_dollar ();
   1897 
   1898   bool read_format_flags ();
   1899 
   1900   bool
   1901   read_any_format_width (tree &params,
   1902 			 unsigned HOST_WIDE_INT &arg_num);
   1903 
   1904   void
   1905   read_any_format_left_precision ();
   1906 
   1907   bool
   1908   read_any_format_precision (tree &params,
   1909 			     unsigned HOST_WIDE_INT &arg_num);
   1910 
   1911   void handle_alloc_chars ();
   1912 
   1913   length_modifier read_any_length_modifier ();
   1914 
   1915   void read_any_other_modifier ();
   1916 
   1917   const format_char_info *find_format_char_info (char format_char);
   1918 
   1919   void
   1920   validate_flag_pairs (const format_char_info *fci,
   1921 		       char format_char);
   1922 
   1923   void
   1924   give_y2k_warnings (const format_char_info *fci,
   1925 		     char format_char);
   1926 
   1927   void parse_any_scan_set (const format_char_info *fci);
   1928 
   1929   bool handle_conversions (const format_char_info *fci,
   1930 			   const length_modifier &len_modifier,
   1931 			   tree &wanted_type,
   1932 			   const char *&wanted_type_name,
   1933 			   unsigned HOST_WIDE_INT &arg_num,
   1934 			   tree &params,
   1935 			   char format_char);
   1936 
   1937   bool
   1938   check_argument_type (const format_char_info *fci,
   1939 		       const length_modifier &len_modifier,
   1940 		       tree &wanted_type,
   1941 		       const char *&wanted_type_name,
   1942 		       const bool suppressed,
   1943 		       unsigned HOST_WIDE_INT &arg_num,
   1944 		       tree &params,
   1945 		       const int alloc_flag,
   1946 		       const char * const format_start,
   1947 		       const char * const type_start,
   1948 		       location_t fmt_param_loc,
   1949 		       char conversion_char);
   1950 
   1951  private:
   1952   const function_format_info *const info;
   1953   const format_kind_info * const fki;
   1954   const format_flag_spec * const flag_specs;
   1955   const char *start_of_this_format;
   1956   const char *&format_chars;
   1957   const tree format_string_cst;
   1958   const char * const orig_format_chars;
   1959   const location_t format_string_loc;
   1960   object_allocator <format_wanted_type> &fwt_pool;
   1961   flag_chars_t &flag_chars;
   1962   int main_arg_num;
   1963   tree main_arg_params;
   1964   int &has_operand_number;
   1965   const tree first_fillin_param;
   1966   format_wanted_type width_wanted_type;
   1967   format_wanted_type precision_wanted_type;
   1968  public:
   1969   format_wanted_type main_wanted_type;
   1970  private:
   1971   format_wanted_type *first_wanted_type;
   1972   format_wanted_type *last_wanted_type;
   1973   vec<location_t> *arglocs;
   1974 };
   1975 
   1976 /* flag_chars_t's constructor.  */
   1977 
   1978 flag_chars_t::flag_chars_t ()
   1979 {
   1980   m_flag_chars[0] = 0;
   1981 }
   1982 
   1983 /* Has CH been seen as a flag within the current argument?  */
   1984 
   1985 bool
   1986 flag_chars_t::has_char_p (char ch) const
   1987 {
   1988   return strchr (m_flag_chars, ch) != 0;
   1989 }
   1990 
   1991 /* Add CH to the flags seen within the current argument.  */
   1992 
   1993 void
   1994 flag_chars_t::add_char (char ch)
   1995 {
   1996   int i = strlen (m_flag_chars);
   1997   m_flag_chars[i++] = ch;
   1998   m_flag_chars[i] = 0;
   1999 }
   2000 
   2001 /* Validate the individual flags used, removing any that are invalid.  */
   2002 
   2003 void
   2004 flag_chars_t::validate (const format_kind_info *fki,
   2005 			const format_char_info *fci,
   2006 			const format_flag_spec *flag_specs,
   2007 			const char * const format_chars,
   2008 			tree format_string_cst,
   2009 			location_t format_string_loc,
   2010 			const char * const orig_format_chars,
   2011 			char format_char,
   2012 			bool quoted)
   2013 {
   2014   int i;
   2015   int d = 0;
   2016   bool quotflag = false;
   2017 
   2018   for (i = 0; m_flag_chars[i] != 0; i++)
   2019     {
   2020       const format_flag_spec *s = get_flag_spec (flag_specs,
   2021 						 m_flag_chars[i], NULL);
   2022       m_flag_chars[i - d] = m_flag_chars[i];
   2023       if (m_flag_chars[i] == fki->length_code_char)
   2024 	continue;
   2025 
   2026       /* Remember if a quoting flag is seen.  */
   2027       quotflag |= s->quoting;
   2028 
   2029       if (strchr (fci->flag_chars, m_flag_chars[i]) == 0)
   2030 	{
   2031 	  format_warning_at_char (format_string_loc, format_string_cst,
   2032 				  format_chars - orig_format_chars,
   2033 				  OPT_Wformat_,
   2034 				  "%s used with %<%%%c%> %s format",
   2035 				  _(s->name), format_char, fki->name);
   2036 	  d++;
   2037 	  continue;
   2038 	}
   2039       if (pedantic)
   2040 	{
   2041 	  const format_flag_spec *t;
   2042 	  if (ADJ_STD (s->std) > C_STD_VER)
   2043 	    warning_at (format_string_loc, OPT_Wformat_,
   2044 			"%s does not support %s",
   2045 			C_STD_NAME (s->std), _(s->long_name));
   2046 	  t = get_flag_spec (flag_specs, m_flag_chars[i], fci->flags2);
   2047 	  if (t != NULL && ADJ_STD (t->std) > ADJ_STD (s->std))
   2048 	    {
   2049 	      const char *long_name = (t->long_name != NULL
   2050 				       ? t->long_name
   2051 				       : s->long_name);
   2052 	      if (ADJ_STD (t->std) > C_STD_VER)
   2053 		warning_at (format_string_loc, OPT_Wformat_,
   2054 			    "%s does not support %s with"
   2055 			    " the %<%%%c%> %s format",
   2056 			    C_STD_NAME (t->std), _(long_name),
   2057 			    format_char, fki->name);
   2058 	    }
   2059 	}
   2060 
   2061       /* Detect quoting directives used within a quoted sequence, such
   2062 	 as GCC's "%<...%qE".  */
   2063       if (quoted && s->quoting)
   2064 	{
   2065 	  format_warning_at_char (format_string_loc, format_string_cst,
   2066 				  format_chars - orig_format_chars - 1,
   2067 				  OPT_Wformat_,
   2068 				  "%s used within a quoted sequence",
   2069 				  _(s->name));
   2070 	}
   2071     }
   2072   m_flag_chars[i - d] = 0;
   2073 
   2074   if (!quoted
   2075       && !quotflag
   2076       && strchr (fci->flags2, '\''))
   2077     {
   2078       format_warning_at_char (format_string_loc, format_string_cst,
   2079 			      format_chars - orig_format_chars,
   2080 			      OPT_Wformat_,
   2081 			      "%qc conversion used unquoted",
   2082 			      format_char);
   2083     }
   2084 }
   2085 
   2086 /* Determine if an assignment-allocation has been set, requiring
   2087    an extra char ** for writing back a dynamically-allocated char *.
   2088    This is for handling the optional 'm' character in scanf.  */
   2089 
   2090 int
   2091 flag_chars_t::get_alloc_flag (const format_kind_info *fki)
   2092 {
   2093   if ((fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE)
   2094       && has_char_p ('a'))
   2095     return 1;
   2096   if (fki->alloc_char && has_char_p (fki->alloc_char))
   2097     return 1;
   2098   return 0;
   2099 }
   2100 
   2101 /* Determine if an assignment-suppression character was seen.
   2102    ('*' in scanf, for discarding the converted input).  */
   2103 
   2104 int
   2105 flag_chars_t::assignment_suppression_p (const format_kind_info *fki)
   2106 {
   2107   if (fki->suppression_char
   2108       && has_char_p (fki->suppression_char))
   2109     return 1;
   2110   return 0;
   2111 }
   2112 
   2113 /* Constructor for argument_parser.  Initialize for parsing one
   2114    argument within a format string.  */
   2115 
   2116 argument_parser::
   2117 argument_parser (function_format_info *info_, const char *&format_chars_,
   2118 		 tree format_string_cst_,
   2119 		 const char * const orig_format_chars_,
   2120 		 location_t format_string_loc_,
   2121 		 flag_chars_t &flag_chars_,
   2122 		 int &has_operand_number_,
   2123 		 tree first_fillin_param_,
   2124 		 object_allocator <format_wanted_type> &fwt_pool_,
   2125 		 vec<location_t> *arglocs_)
   2126 : info (info_),
   2127   fki (&format_types[info->format_type]),
   2128   flag_specs (fki->flag_specs),
   2129   start_of_this_format (format_chars_),
   2130   format_chars (format_chars_),
   2131   format_string_cst (format_string_cst_),
   2132   orig_format_chars (orig_format_chars_),
   2133   format_string_loc (format_string_loc_),
   2134   fwt_pool (fwt_pool_),
   2135   flag_chars (flag_chars_),
   2136   main_arg_num (0),
   2137   main_arg_params (NULL),
   2138   has_operand_number (has_operand_number_),
   2139   first_fillin_param (first_fillin_param_),
   2140   first_wanted_type (NULL),
   2141   last_wanted_type (NULL),
   2142   arglocs (arglocs_)
   2143 {
   2144 }
   2145 
   2146 /* Handle dollars at the start of format arguments, setting up main_arg_params
   2147    and main_arg_num.
   2148 
   2149    Return true if format parsing is to continue, false otherwise.  */
   2150 
   2151 bool
   2152 argument_parser::read_any_dollar ()
   2153 {
   2154   if ((fki->flags & (int) FMT_FLAG_USE_DOLLAR) && has_operand_number != 0)
   2155     {
   2156       /* Possibly read a $ operand number at the start of the format.
   2157 	 If one was previously used, one is required here.  If one
   2158 	 is not used here, we can't immediately conclude this is a
   2159 	 format without them, since it could be printf %m or scanf %*.  */
   2160       int opnum;
   2161       opnum = maybe_read_dollar_number (&format_chars, 0,
   2162 					first_fillin_param,
   2163 					&main_arg_params, fki);
   2164       if (opnum == -1)
   2165 	return false;
   2166       else if (opnum > 0)
   2167 	{
   2168 	  has_operand_number = 1;
   2169 	  main_arg_num = opnum + info->first_arg_num - 1;
   2170 	}
   2171     }
   2172   else if (fki->flags & FMT_FLAG_USE_DOLLAR)
   2173     {
   2174       if (avoid_dollar_number (format_chars))
   2175 	return false;
   2176     }
   2177   return true;
   2178 }
   2179 
   2180 /* Read any format flags, but do not yet validate them beyond removing
   2181    duplicates, since in general validation depends on the rest of
   2182    the format.
   2183 
   2184    Return true if format parsing is to continue, false otherwise.  */
   2185 
   2186 bool
   2187 argument_parser::read_format_flags ()
   2188 {
   2189   while (*format_chars != 0
   2190 	 && strchr (fki->flag_chars, *format_chars) != 0)
   2191     {
   2192       const format_flag_spec *s = get_flag_spec (flag_specs,
   2193 						 *format_chars, NULL);
   2194       if (flag_chars.has_char_p (*format_chars))
   2195 	{
   2196 	  format_warning_at_char (format_string_loc, format_string_cst,
   2197 				  format_chars + 1 - orig_format_chars,
   2198 				  OPT_Wformat_,
   2199 				  "repeated %s in format", _(s->name));
   2200 	}
   2201       else
   2202 	flag_chars.add_char (*format_chars);
   2203 
   2204       if (s->skip_next_char)
   2205 	{
   2206 	  ++format_chars;
   2207 	  if (*format_chars == 0)
   2208 	    {
   2209 	      warning_at (format_string_loc, OPT_Wformat_,
   2210 			  "missing fill character at end of strfmon format");
   2211 	      return false;
   2212 	    }
   2213 	}
   2214       ++format_chars;
   2215     }
   2216 
   2217   return true;
   2218 }
   2219 
   2220 /* Read any format width, possibly * or *m$.
   2221 
   2222    Return true if format parsing is to continue, false otherwise.  */
   2223 
   2224 bool
   2225 argument_parser::
   2226 read_any_format_width (tree &params,
   2227 		       unsigned HOST_WIDE_INT &arg_num)
   2228 {
   2229   if (!fki->width_char)
   2230     return true;
   2231 
   2232   if (fki->width_type != NULL && *format_chars == '*')
   2233     {
   2234       flag_chars.add_char (fki->width_char);
   2235       /* "...a field width...may be indicated by an asterisk.
   2236 	 In this case, an int argument supplies the field width..."  */
   2237       ++format_chars;
   2238       if (has_operand_number != 0)
   2239 	{
   2240 	  int opnum;
   2241 	  opnum = maybe_read_dollar_number (&format_chars,
   2242 					    has_operand_number == 1,
   2243 					    first_fillin_param,
   2244 					    &params, fki);
   2245 	  if (opnum == -1)
   2246 	    return false;
   2247 	  else if (opnum > 0)
   2248 	    {
   2249 	      has_operand_number = 1;
   2250 	      arg_num = opnum + info->first_arg_num - 1;
   2251 	    }
   2252 	  else
   2253 	    has_operand_number = 0;
   2254 	}
   2255       else
   2256 	{
   2257 	  if (avoid_dollar_number (format_chars))
   2258 	    return false;
   2259 	}
   2260       if (info->first_arg_num != 0)
   2261 	{
   2262 	  tree cur_param;
   2263 	  if (params == 0)
   2264 	    cur_param = NULL;
   2265 	  else
   2266 	    {
   2267 	      cur_param = TREE_VALUE (params);
   2268 	      if (has_operand_number <= 0)
   2269 		{
   2270 		  params = TREE_CHAIN (params);
   2271 		  ++arg_num;
   2272 		}
   2273 	    }
   2274 	  width_wanted_type.wanted_type = *fki->width_type;
   2275 	  width_wanted_type.wanted_type_name = NULL;
   2276 	  width_wanted_type.pointer_count = 0;
   2277 	  width_wanted_type.char_lenient_flag = 0;
   2278 	  width_wanted_type.scalar_identity_flag = 0;
   2279 	  width_wanted_type.writing_in_flag = 0;
   2280 	  width_wanted_type.reading_from_flag = 0;
   2281 	  width_wanted_type.kind = CF_KIND_FIELD_WIDTH;
   2282 	  width_wanted_type.format_start = format_chars - 1;
   2283 	  width_wanted_type.format_length = 1;
   2284 	  width_wanted_type.param = cur_param;
   2285 	  width_wanted_type.arg_num = arg_num;
   2286 	  width_wanted_type.offset_loc =
   2287 	    format_chars - orig_format_chars;
   2288 	  width_wanted_type.next = NULL;
   2289 	  if (last_wanted_type != 0)
   2290 	    last_wanted_type->next = &width_wanted_type;
   2291 	  if (first_wanted_type == 0)
   2292 	    first_wanted_type = &width_wanted_type;
   2293 	  last_wanted_type = &width_wanted_type;
   2294 	}
   2295     }
   2296   else
   2297     {
   2298       /* Possibly read a numeric width.  If the width is zero,
   2299 	 we complain if appropriate.  */
   2300       int non_zero_width_char = FALSE;
   2301       int found_width = FALSE;
   2302       while (ISDIGIT (*format_chars))
   2303 	{
   2304 	  found_width = TRUE;
   2305 	  if (*format_chars != '0')
   2306 	    non_zero_width_char = TRUE;
   2307 	  ++format_chars;
   2308 	}
   2309       if (found_width && !non_zero_width_char &&
   2310 	  (fki->flags & (int) FMT_FLAG_ZERO_WIDTH_BAD))
   2311 	warning_at (format_string_loc, OPT_Wformat_,
   2312 		    "zero width in %s format", fki->name);
   2313       if (found_width)
   2314 	flag_chars.add_char (fki->width_char);
   2315     }
   2316 
   2317   return true;
   2318 }
   2319 
   2320 /* Read any format left precision (must be a number, not *).  */
   2321 void
   2322 argument_parser::read_any_format_left_precision ()
   2323 {
   2324   if (fki->left_precision_char == 0)
   2325     return;
   2326   if (*format_chars != '#')
   2327     return;
   2328 
   2329   ++format_chars;
   2330   flag_chars.add_char (fki->left_precision_char);
   2331   if (!ISDIGIT (*format_chars))
   2332     format_warning_at_char (format_string_loc, format_string_cst,
   2333 			    format_chars - orig_format_chars,
   2334 			    OPT_Wformat_,
   2335 			    "empty left precision in %s format", fki->name);
   2336   while (ISDIGIT (*format_chars))
   2337     ++format_chars;
   2338 }
   2339 
   2340 /* Read any format precision, possibly * or *m$.
   2341 
   2342    Return true if format parsing is to continue, false otherwise.  */
   2343 
   2344 bool
   2345 argument_parser::
   2346 read_any_format_precision (tree &params,
   2347 			   unsigned HOST_WIDE_INT &arg_num)
   2348 {
   2349   if (fki->precision_char == 0)
   2350     return true;
   2351   if (*format_chars != '.')
   2352     return true;
   2353 
   2354   ++format_chars;
   2355   flag_chars.add_char (fki->precision_char);
   2356   if (fki->precision_type != NULL && *format_chars == '*')
   2357     {
   2358       /* "...a...precision...may be indicated by an asterisk.
   2359 	 In this case, an int argument supplies the...precision."  */
   2360       ++format_chars;
   2361       if (has_operand_number != 0)
   2362 	{
   2363 	  int opnum;
   2364 	  opnum = maybe_read_dollar_number (&format_chars,
   2365 					    has_operand_number == 1,
   2366 					    first_fillin_param,
   2367 					    &params, fki);
   2368 	  if (opnum == -1)
   2369 	    return false;
   2370 	  else if (opnum > 0)
   2371 	    {
   2372 	      has_operand_number = 1;
   2373 	      arg_num = opnum + info->first_arg_num - 1;
   2374 	    }
   2375 	  else
   2376 	    has_operand_number = 0;
   2377 	}
   2378       else
   2379 	{
   2380 	  if (avoid_dollar_number (format_chars))
   2381 	    return false;
   2382 	}
   2383       if (info->first_arg_num != 0)
   2384 	{
   2385 	  tree cur_param;
   2386 	  if (params == 0)
   2387 	    cur_param = NULL;
   2388 	  else
   2389 	    {
   2390 	      cur_param = TREE_VALUE (params);
   2391 	      if (has_operand_number <= 0)
   2392 		{
   2393 		  params = TREE_CHAIN (params);
   2394 		  ++arg_num;
   2395 		}
   2396 	    }
   2397 	  precision_wanted_type.wanted_type = *fki->precision_type;
   2398 	  precision_wanted_type.wanted_type_name = NULL;
   2399 	  precision_wanted_type.pointer_count = 0;
   2400 	  precision_wanted_type.char_lenient_flag = 0;
   2401 	  precision_wanted_type.scalar_identity_flag = 0;
   2402 	  precision_wanted_type.writing_in_flag = 0;
   2403 	  precision_wanted_type.reading_from_flag = 0;
   2404 	  precision_wanted_type.kind = CF_KIND_FIELD_PRECISION;
   2405 	  precision_wanted_type.param = cur_param;
   2406 	  precision_wanted_type.format_start = format_chars - 2;
   2407 	  precision_wanted_type.format_length = 2;
   2408 	  precision_wanted_type.arg_num = arg_num;
   2409 	  precision_wanted_type.offset_loc =
   2410 	    format_chars - orig_format_chars;
   2411 	  precision_wanted_type.next = NULL;
   2412 	  if (last_wanted_type != 0)
   2413 	    last_wanted_type->next = &precision_wanted_type;
   2414 	  if (first_wanted_type == 0)
   2415 	    first_wanted_type = &precision_wanted_type;
   2416 	  last_wanted_type = &precision_wanted_type;
   2417 	}
   2418     }
   2419   else
   2420     {
   2421       if (!(fki->flags & (int) FMT_FLAG_EMPTY_PREC_OK)
   2422 	  && !ISDIGIT (*format_chars))
   2423 	format_warning_at_char (format_string_loc, format_string_cst,
   2424 				format_chars - orig_format_chars,
   2425 				OPT_Wformat_,
   2426 				"empty precision in %s format", fki->name);
   2427       while (ISDIGIT (*format_chars))
   2428 	++format_chars;
   2429     }
   2430 
   2431   return true;
   2432 }
   2433 
   2434 /* Parse any assignment-allocation flags, which request an extra
   2435    char ** for writing back a dynamically-allocated char *.
   2436    This is for handling the optional 'm' character in scanf,
   2437    and, before C99, 'a' (for compatibility with a non-standard
   2438    GNU libc extension).  */
   2439 
   2440 void
   2441 argument_parser::handle_alloc_chars ()
   2442 {
   2443   if (fki->alloc_char && fki->alloc_char == *format_chars)
   2444     {
   2445       flag_chars.add_char (fki->alloc_char);
   2446       format_chars++;
   2447     }
   2448 
   2449   /* Handle the scanf allocation kludge.  */
   2450   if (fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE)
   2451     {
   2452       if (*format_chars == 'a' && !flag_isoc99)
   2453 	{
   2454 	  if (format_chars[1] == 's' || format_chars[1] == 'S'
   2455 	      || format_chars[1] == '[')
   2456 	    {
   2457 	      /* 'a' is used as a flag.  */
   2458 	      flag_chars.add_char ('a');
   2459 	      format_chars++;
   2460 	    }
   2461 	}
   2462     }
   2463 }
   2464 
   2465 /* Look for length modifiers within the current format argument,
   2466    returning a length_modifier instance describing it (or the
   2467    default if one is not found).
   2468 
   2469    Issue warnings about non-standard modifiers.  */
   2470 
   2471 length_modifier
   2472 argument_parser::read_any_length_modifier ()
   2473 {
   2474   length_modifier result;
   2475 
   2476   const format_length_info *fli = fki->length_char_specs;
   2477   if (!fli)
   2478     return result;
   2479 
   2480   while (fli->name != 0
   2481 	 && strncmp (fli->name, format_chars, strlen (fli->name)))
   2482     fli++;
   2483   if (fli->name != 0)
   2484     {
   2485       format_chars += strlen (fli->name);
   2486       if (fli->double_name != 0 && fli->name[0] == *format_chars)
   2487 	{
   2488 	  format_chars++;
   2489 	  result = length_modifier (fli->double_name, fli->double_index,
   2490 				    fli->double_std, 0);
   2491 	}
   2492       else
   2493 	{
   2494 	  result = length_modifier (fli->name, fli->index, fli->std,
   2495 				    fli->scalar_identity_flag);
   2496 	}
   2497       flag_chars.add_char (fki->length_code_char);
   2498     }
   2499   if (pedantic)
   2500     {
   2501       /* Warn if the length modifier is non-standard.  */
   2502       if (ADJ_STD (result.std) > C_STD_VER)
   2503 	warning_at (format_string_loc, OPT_Wformat_,
   2504 		    "%s does not support the %qs %s length modifier",
   2505 		    C_STD_NAME (result.std), result.chars,
   2506 		    fki->name);
   2507     }
   2508 
   2509   return result;
   2510 }
   2511 
   2512 /* Read any other modifier (strftime E/O).  */
   2513 
   2514 void
   2515 argument_parser::read_any_other_modifier ()
   2516 {
   2517   if (fki->modifier_chars == NULL)
   2518     return;
   2519 
   2520   while (*format_chars != 0
   2521 	 && strchr (fki->modifier_chars, *format_chars) != 0)
   2522     {
   2523       if (flag_chars.has_char_p (*format_chars))
   2524 	{
   2525 	  const format_flag_spec *s = get_flag_spec (flag_specs,
   2526 						     *format_chars, NULL);
   2527 	  format_warning_at_char (format_string_loc, format_string_cst,
   2528 				  format_chars - orig_format_chars,
   2529 				  OPT_Wformat_,
   2530 				  "repeated %s in format", _(s->name));
   2531 	}
   2532       else
   2533 	flag_chars.add_char (*format_chars);
   2534       ++format_chars;
   2535     }
   2536 }
   2537 
   2538 /* Return the format_char_info corresponding to FORMAT_CHAR,
   2539    potentially issuing a warning if the format char is
   2540    not supported in the C standard version we are checking
   2541    against.
   2542 
   2543    Issue a warning and return NULL if it is not found.
   2544 
   2545    Issue warnings about non-standard modifiers.  */
   2546 
   2547 const format_char_info *
   2548 argument_parser::find_format_char_info (char format_char)
   2549 {
   2550   const format_char_info *fci = fki->conversion_specs;
   2551 
   2552   while (fci->format_chars != 0
   2553 	 && strchr (fci->format_chars, format_char) == 0)
   2554     ++fci;
   2555   if (fci->format_chars == 0)
   2556     {
   2557       format_warning_at_char (format_string_loc, format_string_cst,
   2558 			      format_chars - orig_format_chars,
   2559 			      OPT_Wformat_,
   2560 			      "unknown conversion type character"
   2561 			      " %qc in format",
   2562 			      format_char);
   2563       return NULL;
   2564     }
   2565 
   2566   if (pedantic)
   2567     {
   2568       if (ADJ_STD (fci->std) > C_STD_VER)
   2569 	format_warning_at_char (format_string_loc, format_string_cst,
   2570 				format_chars - orig_format_chars,
   2571 				OPT_Wformat_,
   2572 				"%s does not support the %<%%%c%> %s format",
   2573 				C_STD_NAME (fci->std), format_char, fki->name);
   2574     }
   2575 
   2576   return fci;
   2577 }
   2578 
   2579 /* Validate the pairs of flags used.
   2580    Issue warnings about incompatible combinations of flags.  */
   2581 
   2582 void
   2583 argument_parser::validate_flag_pairs (const format_char_info *fci,
   2584 				      char format_char)
   2585 {
   2586   const format_flag_pair * const bad_flag_pairs = fki->bad_flag_pairs;
   2587 
   2588   for (int i = 0; bad_flag_pairs[i].flag_char1 != 0; i++)
   2589     {
   2590       const format_flag_spec *s, *t;
   2591       if (!flag_chars.has_char_p (bad_flag_pairs[i].flag_char1))
   2592 	continue;
   2593       if (!flag_chars.has_char_p (bad_flag_pairs[i].flag_char2))
   2594 	continue;
   2595       if (bad_flag_pairs[i].predicate != 0
   2596 	  && strchr (fci->flags2, bad_flag_pairs[i].predicate) == 0)
   2597 	continue;
   2598       s = get_flag_spec (flag_specs, bad_flag_pairs[i].flag_char1, NULL);
   2599       t = get_flag_spec (flag_specs, bad_flag_pairs[i].flag_char2, NULL);
   2600       if (bad_flag_pairs[i].ignored)
   2601 	{
   2602 	  if (bad_flag_pairs[i].predicate != 0)
   2603 	    warning_at (format_string_loc, OPT_Wformat_,
   2604 			"%s ignored with %s and %<%%%c%> %s format",
   2605 			_(s->name), _(t->name), format_char,
   2606 			fki->name);
   2607 	  else
   2608 	    warning_at (format_string_loc, OPT_Wformat_,
   2609 			"%s ignored with %s in %s format",
   2610 			_(s->name), _(t->name), fki->name);
   2611 	}
   2612       else
   2613 	{
   2614 	  if (bad_flag_pairs[i].predicate != 0)
   2615 	    warning_at (format_string_loc, OPT_Wformat_,
   2616 			"use of %s and %s together with %<%%%c%> %s format",
   2617 			_(s->name), _(t->name), format_char,
   2618 			fki->name);
   2619 	  else
   2620 	    warning_at (format_string_loc, OPT_Wformat_,
   2621 			"use of %s and %s together in %s format",
   2622 			_(s->name), _(t->name), fki->name);
   2623 	}
   2624     }
   2625 }
   2626 
   2627 /* Give Y2K warnings.  */
   2628 
   2629 void
   2630 argument_parser::give_y2k_warnings (const format_char_info *fci,
   2631 				    char format_char)
   2632 {
   2633   if (!warn_format_y2k)
   2634     return;
   2635 
   2636   int y2k_level = 0;
   2637   if (strchr (fci->flags2, '4') != 0)
   2638     if (flag_chars.has_char_p ('E'))
   2639       y2k_level = 3;
   2640     else
   2641       y2k_level = 2;
   2642   else if (strchr (fci->flags2, '3') != 0)
   2643     y2k_level = 3;
   2644   else if (strchr (fci->flags2, '2') != 0)
   2645     y2k_level = 2;
   2646   if (y2k_level == 3)
   2647     warning_at (format_string_loc, OPT_Wformat_y2k,
   2648 		"%<%%%c%> yields only last 2 digits of "
   2649 		"year in some locales", format_char);
   2650   else if (y2k_level == 2)
   2651     warning_at (format_string_loc, OPT_Wformat_y2k,
   2652 		"%<%%%c%> yields only last 2 digits of year",
   2653 		format_char);
   2654 }
   2655 
   2656 /* Parse any "scan sets" enclosed in square brackets, e.g.
   2657    for scanf-style calls.  */
   2658 
   2659 void
   2660 argument_parser::parse_any_scan_set (const format_char_info *fci)
   2661 {
   2662   if (strchr (fci->flags2, '[') == NULL)
   2663     return;
   2664 
   2665   /* Skip over scan set, in case it happens to have '%' in it.  */
   2666   if (*format_chars == '^')
   2667     ++format_chars;
   2668   /* Find closing bracket; if one is hit immediately, then
   2669      it's part of the scan set rather than a terminator.  */
   2670   if (*format_chars == ']')
   2671     ++format_chars;
   2672   while (*format_chars && *format_chars != ']')
   2673     ++format_chars;
   2674   if (*format_chars != ']')
   2675     /* The end of the format string was reached.  */
   2676     format_warning_at_char (format_string_loc, format_string_cst,
   2677 			    format_chars - orig_format_chars,
   2678 			    OPT_Wformat_,
   2679 			    "no closing %<]%> for %<%%[%> format");
   2680 }
   2681 
   2682 /* Return true if this argument is to be continued to be parsed,
   2683    false to skip to next argument.  */
   2684 
   2685 bool
   2686 argument_parser::handle_conversions (const format_char_info *fci,
   2687 				     const length_modifier &len_modifier,
   2688 				     tree &wanted_type,
   2689 				     const char *&wanted_type_name,
   2690 				     unsigned HOST_WIDE_INT &arg_num,
   2691 				     tree &params,
   2692 				     char format_char)
   2693 {
   2694   enum format_std_version wanted_type_std;
   2695 
   2696   if (!(fki->flags & (int) FMT_FLAG_ARG_CONVERT))
   2697     return true;
   2698 
   2699   wanted_type = (fci->types[len_modifier.val].type
   2700 		 ? *fci->types[len_modifier.val].type : 0);
   2701   wanted_type_name = fci->types[len_modifier.val].name;
   2702   wanted_type_std = fci->types[len_modifier.val].std;
   2703   if (wanted_type == 0)
   2704     {
   2705       format_warning_at_char (format_string_loc, format_string_cst,
   2706 			      format_chars - orig_format_chars,
   2707 			      OPT_Wformat_,
   2708 			      "use of %qs length modifier with %qc type"
   2709 			      " character has either no effect"
   2710 			      " or undefined behavior",
   2711 			      len_modifier.chars, format_char);
   2712       /* Heuristic: skip one argument when an invalid length/type
   2713 	 combination is encountered.  */
   2714       arg_num++;
   2715       if (params != 0)
   2716 	params = TREE_CHAIN (params);
   2717       return false;
   2718     }
   2719   else if (pedantic
   2720 	   /* Warn if non-standard, provided it is more non-standard
   2721 	      than the length and type characters that may already
   2722 	      have been warned for.  */
   2723 	   && ADJ_STD (wanted_type_std) > ADJ_STD (len_modifier.std)
   2724 	   && ADJ_STD (wanted_type_std) > ADJ_STD (fci->std))
   2725     {
   2726       if (ADJ_STD (wanted_type_std) > C_STD_VER)
   2727 	format_warning_at_char (format_string_loc, format_string_cst,
   2728 				format_chars - orig_format_chars,
   2729 				OPT_Wformat_,
   2730 				"%s does not support the %<%%%s%c%> %s format",
   2731 				C_STD_NAME (wanted_type_std),
   2732 				len_modifier.chars,
   2733 				format_char, fki->name);
   2734     }
   2735 
   2736   return true;
   2737 }
   2738 
   2739 /* Check type of argument against desired type.
   2740 
   2741    Return true if format parsing is to continue, false otherwise.  */
   2742 
   2743 bool
   2744 argument_parser::
   2745 check_argument_type (const format_char_info *fci,
   2746 		     const length_modifier &len_modifier,
   2747 		     tree &wanted_type,
   2748 		     const char *&wanted_type_name,
   2749 		     const bool suppressed,
   2750 		     unsigned HOST_WIDE_INT &arg_num,
   2751 		     tree &params,
   2752 		     const int alloc_flag,
   2753 		     const char * const format_start,
   2754 		     const char * const type_start,
   2755 		     location_t fmt_param_loc,
   2756 		     char conversion_char)
   2757 {
   2758   if (info->first_arg_num == 0)
   2759     return true;
   2760 
   2761   if ((fci->pointer_count == 0 && wanted_type == void_type_node)
   2762       || suppressed)
   2763     {
   2764       if (main_arg_num != 0)
   2765 	{
   2766 	  if (suppressed)
   2767 	    warning_at (format_string_loc, OPT_Wformat_,
   2768 			"operand number specified with "
   2769 			"suppressed assignment");
   2770 	  else
   2771 	    warning_at (format_string_loc, OPT_Wformat_,
   2772 			"operand number specified for format "
   2773 			"taking no argument");
   2774 	}
   2775     }
   2776   else
   2777     {
   2778       format_wanted_type *wanted_type_ptr;
   2779 
   2780       if (main_arg_num != 0)
   2781 	{
   2782 	  arg_num = main_arg_num;
   2783 	  params = main_arg_params;
   2784 	}
   2785       else
   2786 	{
   2787 	  ++arg_num;
   2788 	  if (has_operand_number > 0)
   2789 	    {
   2790 	      warning_at (format_string_loc, OPT_Wformat_,
   2791 			  "missing $ operand number in format");
   2792 	      return false;
   2793 	    }
   2794 	  else
   2795 	    has_operand_number = 0;
   2796 	}
   2797 
   2798       wanted_type_ptr = &main_wanted_type;
   2799       while (fci)
   2800 	{
   2801 	  tree cur_param;
   2802 	  if (params == 0)
   2803 	    cur_param = NULL;
   2804 	  else
   2805 	    {
   2806 	      cur_param = TREE_VALUE (params);
   2807 	      params = TREE_CHAIN (params);
   2808 	    }
   2809 
   2810 	  wanted_type_ptr->wanted_type = wanted_type;
   2811 	  wanted_type_ptr->wanted_type_name = wanted_type_name;
   2812 	  wanted_type_ptr->pointer_count = fci->pointer_count + alloc_flag;
   2813 	  wanted_type_ptr->char_lenient_flag = 0;
   2814 	  if (strchr (fci->flags2, 'c') != 0)
   2815 	    wanted_type_ptr->char_lenient_flag = 1;
   2816 	  wanted_type_ptr->scalar_identity_flag = 0;
   2817 	  if (len_modifier.scalar_identity_flag)
   2818 	    wanted_type_ptr->scalar_identity_flag = 1;
   2819 	  wanted_type_ptr->writing_in_flag = 0;
   2820 	  wanted_type_ptr->reading_from_flag = 0;
   2821 	  if (alloc_flag)
   2822 	    wanted_type_ptr->writing_in_flag = 1;
   2823 	  else
   2824 	    {
   2825 	      if (strchr (fci->flags2, 'W') != 0)
   2826 		wanted_type_ptr->writing_in_flag = 1;
   2827 	      if (strchr (fci->flags2, 'R') != 0)
   2828 		wanted_type_ptr->reading_from_flag = 1;
   2829 	    }
   2830 	  wanted_type_ptr->kind = CF_KIND_FORMAT;
   2831 	  wanted_type_ptr->param = cur_param;
   2832 	  wanted_type_ptr->arg_num = arg_num;
   2833 	  wanted_type_ptr->format_start = format_start;
   2834 	  wanted_type_ptr->format_length = format_chars - format_start;
   2835 	  wanted_type_ptr->offset_loc = format_chars - orig_format_chars;
   2836 	  wanted_type_ptr->next = NULL;
   2837 	  if (last_wanted_type != 0)
   2838 	    last_wanted_type->next = wanted_type_ptr;
   2839 	  if (first_wanted_type == 0)
   2840 	    first_wanted_type = wanted_type_ptr;
   2841 	  last_wanted_type = wanted_type_ptr;
   2842 
   2843 	  fci = fci->chain;
   2844 	  if (fci)
   2845 	    {
   2846 	      wanted_type_ptr = fwt_pool.allocate ();
   2847 	      arg_num++;
   2848 	      wanted_type = *fci->types[len_modifier.val].type;
   2849 	      wanted_type_name = fci->types[len_modifier.val].name;
   2850 	    }
   2851 	}
   2852     }
   2853 
   2854   if (first_wanted_type != 0)
   2855     {
   2856       ptrdiff_t offset_to_format_start = (start_of_this_format - 1) - orig_format_chars;
   2857       ptrdiff_t offset_to_format_end = (format_chars - 1) - orig_format_chars;
   2858       /* By default, use the end of the range for the caret location.  */
   2859       substring_loc fmt_loc (fmt_param_loc, TREE_TYPE (format_string_cst),
   2860 			     offset_to_format_end,
   2861 			     offset_to_format_start, offset_to_format_end);
   2862       ptrdiff_t offset_to_type_start = type_start - orig_format_chars;
   2863       check_format_types (fmt_loc, first_wanted_type, fki,
   2864 			  offset_to_type_start,
   2865 			  conversion_char, arglocs);
   2866     }
   2867 
   2868   return true;
   2869 }
   2870 
   2871 /* Describes "paired tokens" within the format string that are
   2872    expected to be balanced.  */
   2873 
   2874 class baltoks_t
   2875 {
   2876 public:
   2877   baltoks_t (): singlequote (), doublequote () { }
   2878 
   2879   typedef auto_vec<const char *> balanced_tokens_t;
   2880   /* Vectors of pointers to opening brackets ('['), curly brackets ('{'),
   2881      quoting directives (like GCC "%<"), parentheses, and angle brackets
   2882      ('<').  Used to detect unbalanced tokens.  */
   2883   balanced_tokens_t brackets;
   2884   balanced_tokens_t curly;
   2885   balanced_tokens_t quotdirs;
   2886   balanced_tokens_t parens;
   2887   balanced_tokens_t pointy;
   2888   /* Pointer to the last opening quote.  */
   2889   const char *singlequote;
   2890   const char *doublequote;
   2891 };
   2892 
   2893 /* Describes a keyword, operator, or other name.  */
   2894 
   2895 struct token_t
   2896 {
   2897   const char *name;   /* Keyword/operator name.  */
   2898   unsigned char len;  /* Its length.  */
   2899   const char *alt;    /* Alternate spelling.  */
   2900 };
   2901 
   2902 /* Helper for initializing global token_t arrays below.  */
   2903 #define NAME(name) { name, sizeof name - 1, NULL }
   2904 
   2905 /* C/C++ operators that are expected to be quoted within the format
   2906    string.  */
   2907 
   2908 static const token_t c_opers[] =
   2909   {
   2910    NAME ("!="), NAME ("%="),  NAME ("&&"),  NAME ("&="), NAME ("*="),
   2911    NAME ("++"), NAME ("+="),  NAME ("--"),  NAME ("-="), NAME ("->"),
   2912    NAME ("/="), NAME ("<<"),  NAME ("<<="), NAME ("<="), NAME ("=="),
   2913    NAME (">="), NAME (">>="), NAME (">>"),  NAME ("?:"),  NAME ("^="),
   2914    NAME ("|="), NAME ("||")
   2915   };
   2916 
   2917 static const token_t cxx_opers[] =
   2918   {
   2919    NAME ("->*"), NAME (".*"),  NAME ("::"),  NAME ("<=>")
   2920   };
   2921 
   2922 /* Common C/C++ keywords that are expected to be quoted within the format
   2923    string.  Keywords like auto, inline, or volatile are exccluded because
   2924    they are sometimes used in common terms like /auto variables/, /inline
   2925    function/, or /volatile access/ where they should not be quoted.  */
   2926 
   2927 static const token_t c_keywords[] =
   2928   {
   2929 #undef NAME
   2930 #define NAME(name, alt)  { name, sizeof name - 1, alt }
   2931 
   2932    NAME ("alignas", NULL),
   2933    NAME ("alignof", NULL),
   2934    NAME ("asm", NULL),
   2935    NAME ("bool", NULL),
   2936    NAME ("char", NULL),
   2937    NAME ("const %", NULL),
   2938    NAME ("const-qualified", "%<const%>-qualified"),
   2939    NAME ("float", NULL),
   2940    NAME ("ifunc", NULL),
   2941    NAME ("int", NULL),
   2942    NAME ("long double", NULL),
   2943    NAME ("long int", NULL),
   2944    NAME ("long long", NULL),
   2945    NAME ("malloc", NULL),
   2946    NAME ("noclone", NULL),
   2947    NAME ("noinline", NULL),
   2948    NAME ("nonnull", NULL),
   2949    NAME ("noreturn", NULL),
   2950    NAME ("offsetof", NULL),
   2951    NAME ("readonly", "read-only"),
   2952    NAME ("readwrite", "read-write"),
   2953    NAME ("restrict %", NULL),
   2954    NAME ("restrict-qualified", "%<restrict%>-qualified"),
   2955    NAME ("short int", NULL),
   2956    NAME ("signed char", NULL),
   2957    NAME ("signed int", NULL),
   2958    NAME ("signed long", NULL),
   2959    NAME ("signed short", NULL),
   2960    NAME ("sizeof", NULL),
   2961    NAME ("typeof", NULL),
   2962    NAME ("unsigned char", NULL),
   2963    NAME ("unsigned int", NULL),
   2964    NAME ("unsigned long", NULL),
   2965    NAME ("unsigned short", NULL),
   2966    NAME ("volatile %", NULL),
   2967    NAME ("volatile-qualified", "%<volatile%>-qualified"),
   2968    NAME ("weakref", NULL),
   2969   };
   2970 
   2971 static const token_t cxx_keywords[] =
   2972   {
   2973    /* C++ only keywords and operators.  */
   2974    NAME ("catch", NULL),
   2975    NAME ("constexpr if", NULL),
   2976    NAME ("constexpr", NULL),
   2977    NAME ("constinit", NULL),
   2978    NAME ("consteval", NULL),
   2979    NAME ("decltype", NULL),
   2980    NAME ("nullptr", NULL),
   2981    NAME ("operator delete", NULL),
   2982    NAME ("operator new", NULL),
   2983    NAME ("typeid", NULL),
   2984    NAME ("typeinfo", NULL)
   2985   };
   2986 
   2987 /* Blacklisted words such as misspellings that should be avoided in favor
   2988    of the specified alternatives.  */
   2989 static const struct
   2990 {
   2991   const char *name;   /* Bad word.  */
   2992   unsigned char len;  /* Its length.  */
   2993   const char *alt;    /* Preferred alternative.  */
   2994 } badwords[] =
   2995   {
   2996    NAME ("arg", "argument"),
   2997    NAME ("bitfield", "bit-field"),
   2998    NAME ("builtin function", "built-in function"),
   2999    NAME ("can not", "cannot"),
   3000    NAME ("commandline option", "command-line option"),
   3001    NAME ("commandline", "command line"),
   3002    NAME ("command line option", "command-line option"),
   3003    NAME ("decl", "declaration"),
   3004    NAME ("enumeral", "enumerated"),
   3005    NAME ("floating point", "floating-point"),
   3006    NAME ("nonstatic", "non-static"),
   3007    NAME ("non-zero", "nonzero"),
   3008    NAME ("reg", "register"),
   3009    NAME ("stmt", "statement"),
   3010   };
   3011 
   3012 /* Common contractions that should be avoided in favor of the specified
   3013    alternatives.  */
   3014 
   3015 static const struct
   3016 {
   3017   const char *name;   /* Contraction.  */
   3018   unsigned char len;  /* Its length.  */
   3019   const char *alt;    /* Preferred alternative.  */
   3020 } contrs[] =
   3021   {
   3022    NAME ("can't", "cannot"),
   3023    NAME ("didn't", "did not"),
   3024    /* These are commonly abused.  Avoid diagnosing them for now.
   3025       NAME ("isn't", "is not"),
   3026       NAME ("don't", "is not"),
   3027    */
   3028    NAME ("mustn't", "must not"),
   3029    NAME ("needn't", "need not"),
   3030    NAME ("should't", "should not"),
   3031    NAME ("that's", "that is"),
   3032    NAME ("there's", "there is"),
   3033    NAME ("they're", "they are"),
   3034    NAME ("what's", "what is"),
   3035    NAME ("won't", "will not")
   3036   };
   3037 
   3038 /* Check for unquoted TOKENS.  FORMAT_STRING_LOC is the location of
   3039    the format string, FORMAT_STRING_CST the format string itself (as
   3040    a tree), ORIG_FORMAT_CHARS and FORMAT_CHARS are pointers to
   3041    the beginning of the format string and the character currently
   3042    being processed, and BALTOKS describes paired "tokens" within
   3043    the format string that are expected to be balanced.
   3044    Returns a pointer to the last processed character or null when
   3045    nothing was done.  */
   3046 
   3047 static const char*
   3048 check_tokens (const token_t *tokens, unsigned ntoks,
   3049 	      location_t format_string_loc, tree format_string_cst,
   3050 	      const char *orig_format_chars, const char *format_chars,
   3051 	      baltoks_t &baltoks)
   3052 {
   3053   /* For brevity.  */
   3054   const int opt = OPT_Wformat_diag;
   3055   /* Zero-based starting position of a problem sequence.  */
   3056   int fmtchrpos = format_chars - orig_format_chars;
   3057 
   3058   /* For identifier-like "words," set to the word length.  */
   3059   unsigned wlen = 0;
   3060   /* Set for an operator, clear for an identifier/word.  */
   3061   bool is_oper = false;
   3062   bool underscore = false;
   3063 
   3064   if (format_chars[0] == '_' || ISALPHA (format_chars[0]))
   3065     {
   3066       while (format_chars[wlen] == '_' || ISALNUM (format_chars[wlen]))
   3067 	{
   3068 	  underscore |= format_chars[wlen] == '_';
   3069 	  ++wlen;
   3070 	}
   3071     }
   3072   else
   3073     is_oper = true;
   3074 
   3075   for (unsigned i = 0; i != ntoks; ++i)
   3076     {
   3077       unsigned toklen = tokens[i].len;
   3078 
   3079       if (toklen < wlen
   3080 	  || strncmp (format_chars, tokens[i].name, toklen))
   3081 	continue;
   3082 
   3083       if (toklen == 2
   3084 	  && format_chars - orig_format_chars > 0
   3085 	  && (TOUPPER (format_chars[-1]) == 'C'
   3086 	      || TOUPPER (format_chars[-1]) == 'G'))
   3087 	return format_chars + toklen - 1;   /* Reference to C++ or G++.  */
   3088 
   3089       if (ISPUNCT (format_chars[toklen - 1]))
   3090 	{
   3091 	  if (format_chars[toklen - 1] == format_chars[toklen])
   3092 	    return NULL;   /* Operator followed by another punctuator.  */
   3093 	}
   3094       else if (ISALNUM (format_chars[toklen]))
   3095 	return NULL;   /* Keyword prefix for a longer word.  */
   3096 
   3097       if (toklen == 2
   3098 	  && format_chars[0] == '-'
   3099 	  && format_chars[1] == '-'
   3100 	  && ISALNUM (format_chars[2]))
   3101 	return NULL;   /* Probably option like --help.  */
   3102 
   3103       /* Allow this ugly warning for the time being.  */
   3104       if (toklen == 2
   3105 	  && format_chars - orig_format_chars > 6
   3106 	  && startswith (format_chars - 7, " count >= width of "))
   3107 	return format_chars + 10;
   3108 
   3109       /* The token is a type if it ends in an alphabetic character.  */
   3110       bool is_type = (ISALPHA (tokens[i].name[toklen - 1])
   3111 		      && strchr (tokens[i].name, ' '));
   3112 
   3113       /* Backtrack to the last alphabetic character (for tokens whose
   3114 	 names end in '%').  */
   3115       if (!is_oper)
   3116 	while (!ISALPHA (tokens[i].name[toklen - 1]))
   3117 	  --toklen;
   3118 
   3119       if (format_warning_substr (format_string_loc, format_string_cst,
   3120 				 fmtchrpos, fmtchrpos + toklen, opt,
   3121 				 (is_type
   3122 				  ? G_("unquoted type name %<%.*s%> in format")
   3123 				  : (is_oper
   3124 				     ? G_("unquoted operator %<%.*s%> in format")
   3125 				     : G_("unquoted keyword %<%.*s%> in format"))),
   3126 				 toklen, format_chars)
   3127 	  && tokens[i].alt)
   3128 	inform (format_string_loc, "use %qs instead", tokens[i].alt);
   3129 
   3130       return format_chars + toklen - 1;
   3131     }
   3132 
   3133   /* Diagnose unquoted __attribute__.  Consider any parenthesized
   3134      argument to the attribute to avoid redundant warnings for
   3135      the double parentheses that might follow.  */
   3136   if (startswith (format_chars, "__attribute"))
   3137     {
   3138       unsigned nchars = sizeof "__attribute" - 1;
   3139       while ('_' == format_chars[nchars])
   3140 	++nchars;
   3141 
   3142       for (int i = nchars; format_chars[i]; ++i)
   3143 	if (' ' != format_chars[i])
   3144 	  {
   3145 	    nchars = i;
   3146 	    break;
   3147 	  }
   3148 
   3149       if (format_chars[nchars] == '(')
   3150 	{
   3151 	  baltoks.parens.safe_push (format_chars + nchars);
   3152 
   3153 	  ++nchars;
   3154 	  bool close = false;
   3155 	  if (format_chars[nchars] == '(')
   3156 	    {
   3157 	      baltoks.parens.safe_push (format_chars + nchars);
   3158 	      close = true;
   3159 	      ++nchars;
   3160 	    }
   3161 	  for (int i = nchars; format_chars[i]; ++i)
   3162 	    if (')' == format_chars[i])
   3163 	      {
   3164 		if (baltoks.parens.length () > 0)
   3165 		  baltoks.parens.pop ();
   3166 		nchars = i + 1;
   3167 		break;
   3168 	      }
   3169 
   3170 	  if (close && format_chars[nchars] == ')')
   3171 	    {
   3172 	      if (baltoks.parens.length () > 0)
   3173 		baltoks.parens.pop ();
   3174 	      ++nchars;
   3175 	    }
   3176 	}
   3177 
   3178       format_warning_substr (format_string_loc, format_string_cst,
   3179 			     fmtchrpos, fmtchrpos + nchars, opt,
   3180 			      "unquoted attribute in format");
   3181       return format_chars + nchars - 1;
   3182     }
   3183 
   3184   /* Diagnose unquoted built-ins.  */
   3185   if (format_chars[0] == '_'
   3186       && format_chars[1] == '_'
   3187       && (startswith (format_chars + 2, "atomic")
   3188 	  || startswith (format_chars + 2, "builtin")
   3189 	  || startswith (format_chars + 2, "sync")))
   3190     {
   3191       format_warning_substr (format_string_loc, format_string_cst,
   3192 			     fmtchrpos, fmtchrpos + wlen, opt,
   3193 			     "unquoted name of built-in function %<%.*s%> "
   3194 			     "in format",
   3195 			     wlen, format_chars);
   3196       return format_chars + wlen - 1;
   3197     }
   3198 
   3199   /* Diagnose unquoted substrings of alphanumeric characters containing
   3200      underscores.  They most likely refer to identifiers and should be
   3201      quoted.  */
   3202   if (underscore)
   3203     format_warning_substr (format_string_loc, format_string_cst,
   3204 			   format_chars - orig_format_chars,
   3205 			   format_chars + wlen - orig_format_chars,
   3206 			   opt,
   3207 			   "unquoted identifier or keyword %<%.*s%> in format",
   3208 			   wlen, format_chars);
   3209   else
   3210     {
   3211       /* Diagnose some common misspellings.  */
   3212       for (unsigned i = 0; i != sizeof badwords / sizeof *badwords; ++i)
   3213 	{
   3214 	  unsigned badwlen = strspn (badwords[i].name, " -");
   3215 	  if (wlen >= badwlen
   3216 	      && (wlen <= badwords[i].len
   3217 		  || (wlen == badwords[i].len + 1U
   3218 		      && TOUPPER (format_chars[wlen - 1]) == 'S'))
   3219 	      && !strncasecmp (format_chars, badwords[i].name, badwords[i].len))
   3220 	    {
   3221 	      /* Handle singular as well as plural forms of all bad words
   3222 		 even though the latter don't necessarily make sense for
   3223 		 all of the former (like "can nots").  */
   3224 	      badwlen = badwords[i].len;
   3225 	      const char *plural = "";
   3226 	      if (TOUPPER (format_chars[badwlen]) == 'S')
   3227 		{
   3228 		  ++badwlen;
   3229 		  plural = "s";
   3230 		}
   3231 
   3232 	      /* As an exception, don't warn about "decl-specifier*" since
   3233 		 it's a C++ grammar production.  */
   3234 	      if (badwords[i].name[0] == 'd'
   3235 		  && startswith (format_chars, "decl-specifier"))
   3236 		continue;
   3237 
   3238 	      format_warning_substr (format_string_loc, format_string_cst,
   3239 				     fmtchrpos, fmtchrpos + badwords[i].len,
   3240 				     opt,
   3241 				     "misspelled term %<%.*s%> in format; "
   3242 				     "use %<%s%s%> instead",
   3243 				     badwlen, format_chars,
   3244 				     badwords[i].alt, plural);
   3245 
   3246 	      return format_chars + badwords[i].len - 1;
   3247 	    }
   3248 	}
   3249 
   3250       /* Skip C++/G++.  */
   3251       if (!strncasecmp (format_chars, "c++", 3)
   3252 	  || !strncasecmp (format_chars, "g++", 3))
   3253 	return format_chars + 2;
   3254     }
   3255 
   3256   return wlen ? format_chars + wlen - 1 : NULL;
   3257 }
   3258 
   3259 /* Check plain text in a format string of a GCC diagnostic function
   3260    for common quoting, punctuation, and spelling mistakes, and issue
   3261    -Wformat-diag warnings if they are found.   FORMAT_STRING_LOC is
   3262    the location of the format string, FORMAT_STRING_CST the format
   3263    string itself (as a tree), ORIG_FORMAT_CHARS and FORMAT_CHARS are
   3264    pointers to the beginning of the format string and the character
   3265    currently being processed, and BALTOKS describes paired "tokens"
   3266    within the format string that are expected to be balanced.
   3267    Returns a pointer to the last processed character.  */
   3268 
   3269 static const char*
   3270 check_plain (location_t format_string_loc, tree format_string_cst,
   3271 	     const char *orig_format_chars, const char *format_chars,
   3272 	     baltoks_t &baltoks)
   3273 {
   3274   /* For brevity.  */
   3275   const int opt = OPT_Wformat_diag;
   3276   /* Zero-based starting position of a problem sequence.  */
   3277   int fmtchrpos = format_chars - orig_format_chars;
   3278 
   3279   if (*format_chars == '%')
   3280     {
   3281       /* Diagnose %<%s%> and suggest using %qs instead.  */
   3282       if (startswith (format_chars, "%<%s%>"))
   3283 	format_warning_substr (format_string_loc, format_string_cst,
   3284 			       fmtchrpos, fmtchrpos + 6, opt,
   3285 			       "quoted %qs directive in format; "
   3286 			       "use %qs instead", "%s", "%qs");
   3287       else if (format_chars - orig_format_chars > 2
   3288 	       && !strncasecmp (format_chars - 3, "can%'t", 6))
   3289 	format_warning_substr (format_string_loc,
   3290 			       format_string_cst,
   3291 			       fmtchrpos - 3, fmtchrpos + 3, opt,
   3292 			       "contraction %<%.*s%> in format; "
   3293 			       "use %qs instead",
   3294 			       6, format_chars - 3, "cannot");
   3295 
   3296       return format_chars;
   3297     }
   3298 
   3299   if (baltoks.quotdirs.length ())
   3300     {
   3301       /* Skip over all plain text within a quoting directive until
   3302 	 the next directive.  */
   3303       while (*format_chars && '%' != *format_chars)
   3304 	++format_chars;
   3305 
   3306       return format_chars;
   3307     }
   3308 
   3309   /* The length of the problem sequence.  */
   3310   int nchars = 0;
   3311 
   3312   /* Diagnose any whitespace characters other than <space> but only
   3313      leading, trailing, and two or more consecutive <space>s.  Do
   3314      this before diagnosing control characters because whitespace
   3315      is a subset of controls.  */
   3316   const char *other_than_space = NULL;
   3317   while (ISSPACE (format_chars[nchars]))
   3318     {
   3319       if (format_chars[nchars] != ' ' && !other_than_space)
   3320 	other_than_space = format_chars + nchars;
   3321       ++nchars;
   3322     }
   3323 
   3324   if (nchars)
   3325     {
   3326       /* This is the most common problem: go the extra mile to describe
   3327 	 the problem in as much helpful detail as possible.  */
   3328       if (other_than_space)
   3329 	{
   3330 	  format_warning_substr (format_string_loc, format_string_cst,
   3331 				 fmtchrpos, fmtchrpos + nchars, opt,
   3332 				 "unquoted whitespace character %qc in format",
   3333 				 *other_than_space);
   3334 	  return format_chars + nchars - 1;
   3335 	}
   3336 
   3337       if (fmtchrpos == 0)
   3338 	/* Accept strings of leading spaces with no warning.  */
   3339 	return format_chars + nchars - 1;
   3340 
   3341       if (!format_chars[nchars])
   3342 	{
   3343 	  format_warning_substr (format_string_loc, format_string_cst,
   3344 				 fmtchrpos, fmtchrpos + nchars, opt,
   3345 				 "spurious trailing space in format");
   3346 	  return format_chars + nchars - 1;
   3347 	}
   3348 
   3349       if (nchars > 1)
   3350 	{
   3351 	  if (nchars == 2
   3352 	      && orig_format_chars < format_chars
   3353 	      && format_chars[-1] == '.'
   3354 	      && format_chars[0] == ' '
   3355 	      && format_chars[1] == ' ')
   3356 	    {
   3357 	      /* A period followed by two spaces.  */
   3358 	      if (ISUPPER (*orig_format_chars))
   3359 		{
   3360 		  /* If the part before the period is a capitalized
   3361 		     sentence check to make sure that what follows
   3362 		     is also capitalized.  */
   3363 		  if (ISLOWER (format_chars[2]))
   3364 		    format_warning_substr (format_string_loc, format_string_cst,
   3365 					   fmtchrpos, fmtchrpos + nchars, opt,
   3366 					   "inconsistent capitalization in "
   3367 					   "format");
   3368 		}
   3369 	    }
   3370 	  else
   3371 	    format_warning_substr (format_string_loc, format_string_cst,
   3372 				   fmtchrpos, fmtchrpos + nchars, opt,
   3373 				   "unquoted sequence of %i consecutive "
   3374 				   "space characters in format", nchars);
   3375 	  return format_chars + nchars - 1;
   3376 	}
   3377 
   3378       format_chars += nchars;
   3379       nchars = 0;
   3380     }
   3381 
   3382   fmtchrpos = format_chars - orig_format_chars;
   3383 
   3384   /* Diagnose any unquoted control characters other than the terminating
   3385      NUL.  */
   3386   while (format_chars[nchars] && ISCNTRL (format_chars[nchars]))
   3387     ++nchars;
   3388 
   3389   if (nchars > 1)
   3390     {
   3391       format_warning_substr (format_string_loc, format_string_cst,
   3392 			     fmtchrpos, fmtchrpos + nchars, opt,
   3393 			     "unquoted control characters in format");
   3394       return format_chars + nchars - 1;
   3395     }
   3396   if (nchars)
   3397     {
   3398       format_warning_substr (format_string_loc, format_string_cst,
   3399 			     fmtchrpos, fmtchrpos + nchars, opt,
   3400 			     "unquoted control character %qc in format",
   3401 			     *format_chars);
   3402       return format_chars + nchars - 1;
   3403     }
   3404 
   3405   if (ISPUNCT (format_chars[0]))
   3406     {
   3407       size_t nelts = sizeof c_opers / sizeof *c_opers;
   3408       if (const char *ret = check_tokens (c_opers, nelts,
   3409 					  format_string_loc, format_string_cst,
   3410 					  orig_format_chars, format_chars,
   3411 					  baltoks))
   3412 	return ret;
   3413 
   3414       nelts = c_dialect_cxx () ? sizeof cxx_opers / sizeof *cxx_opers : 0;
   3415       if (const char *ret = check_tokens (cxx_opers, nelts,
   3416 					  format_string_loc, format_string_cst,
   3417 					  orig_format_chars, format_chars,
   3418 					  baltoks))
   3419 	return ret;
   3420     }
   3421 
   3422   if (ISALPHA (format_chars[0]))
   3423     {
   3424       size_t nelts = sizeof c_keywords / sizeof *c_keywords;
   3425       if (const char *ret = check_tokens (c_keywords, nelts,
   3426 					  format_string_loc, format_string_cst,
   3427 					  orig_format_chars, format_chars,
   3428 					  baltoks))
   3429 	return ret;
   3430 
   3431       nelts = c_dialect_cxx () ? sizeof cxx_keywords / sizeof *cxx_keywords : 0;
   3432       if (const char *ret = check_tokens (cxx_keywords, nelts,
   3433 					  format_string_loc, format_string_cst,
   3434 					  orig_format_chars, format_chars,
   3435 					  baltoks))
   3436 	return ret;
   3437     }
   3438 
   3439   nchars = 0;
   3440 
   3441   /* Diagnose unquoted options.  */
   3442   if  ((format_chars == orig_format_chars
   3443 	|| format_chars[-1] == ' ')
   3444        && format_chars[0] == '-'
   3445        && ((format_chars[1] == '-'
   3446 	    && ISALPHA (format_chars[2]))
   3447 	   || ISALPHA (format_chars[1])))
   3448     {
   3449       nchars = 1;
   3450       while (ISALNUM (format_chars[nchars])
   3451 	     || '_' == format_chars[nchars]
   3452 	     || '-' == format_chars[nchars]
   3453 	     || '+' == format_chars[nchars])
   3454 	++nchars;
   3455 
   3456       format_warning_substr (format_string_loc, format_string_cst,
   3457 			     fmtchrpos, fmtchrpos + nchars, opt,
   3458 			     "unquoted option name %<%.*s%> in format",
   3459 			     nchars, format_chars);
   3460       return format_chars + nchars - 1;
   3461     }
   3462 
   3463   /* Diagnose leading, trailing, and two or more consecutive punctuation
   3464      characters.  */
   3465   const char *unbalanced = NULL;
   3466   while ('%' != format_chars[nchars]
   3467 	 && ISPUNCT (format_chars[nchars])
   3468 	 && !unbalanced)
   3469     {
   3470       switch (format_chars[nchars])
   3471 	{
   3472 	case '[':
   3473 	  baltoks.brackets.safe_push (format_chars + nchars);
   3474 	  break;
   3475 	case '{':
   3476 	  baltoks.curly.safe_push (format_chars + nchars);
   3477 	  break;
   3478 	case '(':
   3479 	  baltoks.parens.safe_push (format_chars + nchars);
   3480 	  break;
   3481 	case '<':
   3482 	  baltoks.pointy.safe_push (format_chars + nchars);
   3483 	  break;
   3484 
   3485 	case ']':
   3486 	  if (baltoks.brackets.length () > 0)
   3487 	    baltoks.brackets.pop ();
   3488 	  else
   3489 	    unbalanced = format_chars + nchars;
   3490 	  break;
   3491 	case '}':
   3492 	  if (baltoks.curly.length () > 0)
   3493 	    baltoks.curly.pop ();
   3494 	  else
   3495 	    unbalanced = format_chars + nchars;
   3496 	  break;
   3497 	case ')':
   3498 	  if (baltoks.parens.length () > 0)
   3499 	    baltoks.parens.pop ();
   3500 	  else
   3501 	    unbalanced = format_chars + nchars;
   3502 	  break;
   3503 	case '>':
   3504 	  if (baltoks.pointy.length () > 0)
   3505 	    baltoks.pointy.pop ();
   3506 	  else
   3507 	    unbalanced = format_chars + nchars;
   3508 	  break;
   3509 	}
   3510 
   3511       ++nchars;
   3512     }
   3513 
   3514   if (unbalanced)
   3515     {
   3516       format_warning_substr (format_string_loc, format_string_cst,
   3517 			     fmtchrpos, fmtchrpos + nchars, opt,
   3518 			     "unbalanced punctuation character %qc in format",
   3519 			     *unbalanced);
   3520       return format_chars + nchars - 1;
   3521     }
   3522 
   3523   if (nchars)
   3524     {
   3525       /* Consider any identifier that follows the pound ('#') sign
   3526 	 a preprocessing directive.  */
   3527       if (nchars == 1
   3528 	  && format_chars[0] == '#'
   3529 	  && ISALPHA (format_chars[1]))
   3530 	{
   3531 	  while (ISALNUM (format_chars[nchars])
   3532 		 || format_chars[nchars] == '_')
   3533 	    ++nchars;
   3534 
   3535 	  format_warning_substr (format_string_loc, format_string_cst,
   3536 				 fmtchrpos, fmtchrpos + nchars, opt,
   3537 				 "unquoted preprocessing directive %<%.*s%> "
   3538 				 "in format", nchars, format_chars);
   3539 	  return format_chars + nchars - 1;
   3540 	}
   3541 
   3542       /* Diagnose a bare single quote.  */
   3543       if (nchars == 1
   3544 	  && format_chars[0] == '\''
   3545 	  && format_chars - orig_format_chars
   3546 	  && ISALPHA (format_chars[-1])
   3547 	  && ISALPHA (format_chars[1]))
   3548 	{
   3549 	  /* Diagnose a subset of contractions that are best avoided.  */
   3550 	  for (unsigned i = 0; i != sizeof contrs / sizeof *contrs; ++i)
   3551 	    {
   3552 	      const char *apos = strchr (contrs[i].name, '\'');
   3553 	      gcc_assert (apos != NULL);
   3554 	      int off = apos - contrs[i].name;
   3555 
   3556 	      if (format_chars - orig_format_chars >= off
   3557 		  && !strncmp (format_chars - off,
   3558 			       contrs[i].name, contrs[i].len))
   3559 		{
   3560 		  format_warning_substr (format_string_loc,
   3561 					 format_string_cst,
   3562 					 fmtchrpos, fmtchrpos + nchars, opt,
   3563 					 "contraction %<%.*s%> in format; "
   3564 					 "use %qs instead",
   3565 					 contrs[i].len, contrs[i].name,
   3566 					 contrs[i].alt);
   3567 		  return format_chars + nchars - 1;
   3568 		}
   3569 	    }
   3570 
   3571 	  if (format_warning_substr (format_string_loc, format_string_cst,
   3572 				     fmtchrpos, fmtchrpos + nchars, opt,
   3573 				     "bare apostrophe %<'%> in format"))
   3574 	    inform (format_string_loc,
   3575 		    "if avoiding the apostrophe is not feasible, enclose "
   3576 		    "it in a pair of %qs and %qs directives instead",
   3577 		    "%<", "%>");
   3578 	  return format_chars + nchars - 1;
   3579 	}
   3580 
   3581       /* Diagnose a backtick (grave accent).  */
   3582       if (nchars == 1
   3583 	  && format_chars[0] == '`')
   3584 	{
   3585 	  if (format_warning_substr (format_string_loc, format_string_cst,
   3586 				     fmtchrpos, fmtchrpos + nchars, opt,
   3587 				     "grave accent %<`%> in format"))
   3588 	    inform (format_string_loc,
   3589 		    "use the apostrophe directive %qs instead", "%'");
   3590 	  return format_chars + nchars - 1;
   3591 	}
   3592 
   3593       /* Diagnose a punctuation character after a space.  */
   3594       if (nchars == 1
   3595 	  && format_chars - orig_format_chars
   3596 	  && format_chars[-1] == ' '
   3597 	  && strspn (format_chars, "!?:;.,") == 1)
   3598 	{
   3599 	  format_warning_substr (format_string_loc, format_string_cst,
   3600 				 fmtchrpos - 1, fmtchrpos, opt,
   3601 				 "space followed by punctuation character "
   3602 				 "%<%c%>", format_chars[0]);
   3603 	  return format_chars;
   3604 	}
   3605 
   3606       if (nchars == 1)
   3607 	{
   3608 	  if (startswith (format_chars, "\"%s\""))
   3609 	    {
   3610 	      if (format_warning_substr (format_string_loc, format_string_cst,
   3611 					 fmtchrpos, fmtchrpos + 4, opt,
   3612 					 "quoted %qs directive in format",
   3613 					 "%s"))
   3614 		inform (format_string_loc, "if using %qs is not feasible, "
   3615 			"use %qs instead", "%qs", "\"%-s\"");
   3616 	    }
   3617 
   3618 	  if (format_chars[0] == '"')
   3619 	    {
   3620 	      baltoks.doublequote = baltoks.doublequote ? NULL : format_chars;
   3621 	      return format_chars + nchars - 1;
   3622 	    }
   3623 	  if (format_chars[0] == '\'')
   3624 	    {
   3625 	      baltoks.singlequote = baltoks.singlequote ? NULL : format_chars;
   3626 	      return format_chars + nchars - 1;
   3627 	    }
   3628 	}
   3629 
   3630       if (fmtchrpos == 0)
   3631 	{
   3632 	  if (nchars == 1
   3633 	      && format_chars[0] == '(')
   3634 	    ;   /* Text beginning in an open parenthesis.  */
   3635 	  else if (nchars == 3
   3636 	      && startswith (format_chars, "...")
   3637 	      && format_chars[3])
   3638 	    ;   /* Text beginning in an ellipsis.  */
   3639 	  else
   3640 	    {
   3641 	      format_warning_substr (format_string_loc, format_string_cst,
   3642 				     fmtchrpos, fmtchrpos + nchars, opt,
   3643 				     "spurious leading punctuation sequence "
   3644 				     "%<%.*s%> in format",
   3645 				     nchars, format_chars);
   3646 	      return format_chars + nchars - 1;
   3647 	    }
   3648 	}
   3649       else if (!format_chars[nchars])
   3650 	{
   3651 	  if (nchars == 1
   3652 	      && (format_chars[nchars - 1] == ':'
   3653 		  || format_chars[nchars - 1] == ')'))
   3654 	    ;   /* Text ending in a colon or a closing parenthesis.  */
   3655 	  else if (nchars == 1
   3656 		   && ((ISUPPER (*orig_format_chars)
   3657 			&& format_chars[nchars - 1] == '.')
   3658 		       || strspn (format_chars + nchars - 1, "?])") == 1))
   3659 		  ;   /* Capitalized sentence terminated by a single period,
   3660 			 or text ending in a question mark, closing bracket,
   3661 			 or parenthesis.  */
   3662 	  else if (nchars == 2
   3663 		   && format_chars[0] == '?'
   3664 		   && format_chars[1] == ')')
   3665 	    ;   /* A question mark after a closing parenthetical note.  */
   3666 	  else if (nchars == 2
   3667 		   && format_chars[0] == ')'
   3668 		   && (format_chars[1] == '?'
   3669 		       || format_chars[1] == ';'
   3670 		       || format_chars[1] == ':'
   3671 		       || (ISUPPER (*orig_format_chars)
   3672 			   && format_chars[1] == '.')))
   3673 	    ;   /* Closing parenthetical note followed by a question mark,
   3674 		   semicolon, or colon at the end of the string, or by
   3675 		   a period at the end of a capitalized sentence.  */
   3676 	  else if (nchars == 3
   3677 		   && format_chars - orig_format_chars > 0
   3678 		   && startswith (format_chars, "..."))
   3679 	    ;   /* Text ending in the ellipsis.  */
   3680 	  else
   3681 	    format_warning_substr (format_string_loc, format_string_cst,
   3682 				   fmtchrpos, fmtchrpos + nchars, opt,
   3683 				   "spurious trailing punctuation sequence "
   3684 				   "%<%.*s%> in format",
   3685 				   nchars, format_chars);
   3686 
   3687 	  return format_chars + nchars - 1;
   3688 	}
   3689       else if (nchars == 2
   3690 	       && format_chars[0] == ')'
   3691 	       && (format_chars[1] == ':'
   3692 		   || format_chars[1] == ';'
   3693 		   || format_chars[1] == ',')
   3694 	       && format_chars[2] == ' ')
   3695 	;   /* Closing parenthetical note followed by a colon, semicolon
   3696 	       or a comma followed by a space in the middle of the string.  */
   3697       else if (nchars > 1)
   3698 	format_warning_substr (format_string_loc, format_string_cst,
   3699 			       fmtchrpos, fmtchrpos + nchars, opt,
   3700 			       "unquoted sequence of %i consecutive "
   3701 			       "punctuation characters %q.*s in format",
   3702 			       nchars, nchars, format_chars);
   3703       return format_chars + nchars - 1;
   3704     }
   3705 
   3706   nchars = 0;
   3707 
   3708   /* Finally, diagnose any unquoted non-graph, non-punctuation characters
   3709      other than the terminating NUL.  */
   3710   while (format_chars[nchars]
   3711 	 && '%' != format_chars[nchars]
   3712 	 && !ISPUNCT (format_chars[nchars])
   3713 	 && !ISGRAPH (format_chars[nchars]))
   3714     ++nchars;
   3715 
   3716   if (nchars > 1)
   3717     {
   3718       format_warning_substr (format_string_loc, format_string_cst,
   3719 			     fmtchrpos, fmtchrpos + nchars, opt,
   3720 			     "unquoted non-graph characters in format");
   3721       return format_chars + nchars - 1;
   3722     }
   3723   if (nchars)
   3724     {
   3725       format_warning_substr (format_string_loc, format_string_cst,
   3726 			     fmtchrpos, fmtchrpos + nchars, opt,
   3727 			     "unquoted non-graph character %qc in format",
   3728 			     *format_chars);
   3729       return format_chars + nchars - 1;
   3730     }
   3731 
   3732   return format_chars;
   3733 }
   3734 
   3735 /* Diagnose unbalanced tokens described by BALTOKS in format string
   3736    ORIG_FORMAT_CHARS and the corresponding FORMAT_STRING_CST.  */
   3737 
   3738 static void
   3739 maybe_diag_unbalanced_tokens (location_t format_string_loc,
   3740 			      const char *orig_format_chars,
   3741 			      tree format_string_cst,
   3742 			      baltoks_t &baltoks)
   3743 {
   3744   const char *unbalanced = NULL;
   3745 
   3746   if (baltoks.brackets.length ())
   3747     unbalanced = baltoks.brackets.pop ();
   3748   else if (baltoks.curly.length ())
   3749     unbalanced = baltoks.curly.pop ();
   3750   else if (baltoks.parens.length ())
   3751     unbalanced = baltoks.parens.pop ();
   3752   else if (baltoks.pointy.length ())
   3753     unbalanced = baltoks.pointy.pop ();
   3754 
   3755   if (unbalanced)
   3756     format_warning_at_char (format_string_loc, format_string_cst,
   3757 			    unbalanced - orig_format_chars + 1,
   3758 			    OPT_Wformat_diag,
   3759 			    "unbalanced punctuation character %<%c%> in format",
   3760 			    *unbalanced);
   3761 
   3762   if (baltoks.quotdirs.length ())
   3763     format_warning_at_char (format_string_loc, format_string_cst,
   3764 			    baltoks.quotdirs.pop () - orig_format_chars,
   3765 			    OPT_Wformat_,
   3766 			    "unterminated quoting directive");
   3767 
   3768   const char *quote
   3769     = baltoks.singlequote ? baltoks.singlequote : baltoks.doublequote;
   3770 
   3771   if (quote)
   3772     format_warning_at_char (format_string_loc, format_string_cst,
   3773   			    quote - orig_format_chars + 1,
   3774 			    OPT_Wformat_diag,
   3775   			    "unterminated quote character %<%c%> in format",
   3776   			    *quote);
   3777 }
   3778 
   3779 /* Do the main part of checking a call to a format function.  FORMAT_CHARS
   3780    is the NUL-terminated format string (which at this point may contain
   3781    internal NUL characters); FORMAT_LENGTH is its length (excluding the
   3782    terminating NUL character).  ARG_NUM is one less than the number of
   3783    the first format argument to check; PARAMS points to that format
   3784    argument in the list of arguments.  */
   3785 
   3786 static void
   3787 check_format_info_main (format_check_results *res,
   3788 			function_format_info *info, const char *format_chars,
   3789 			location_t fmt_param_loc, tree format_string_cst,
   3790 			int format_length, tree params,
   3791 			unsigned HOST_WIDE_INT arg_num,
   3792 			object_allocator <format_wanted_type> &fwt_pool,
   3793 			vec<location_t> *arglocs)
   3794 {
   3795   const char * const orig_format_chars = format_chars;
   3796   const tree first_fillin_param = params;
   3797 
   3798   const format_kind_info * const fki = &format_types[info->format_type];
   3799   const format_flag_spec * const flag_specs = fki->flag_specs;
   3800   const location_t format_string_loc = res->format_string_loc;
   3801 
   3802   /* -1 if no conversions taking an operand have been found; 0 if one has
   3803      and it didn't use $; 1 if $ formats are in use.  */
   3804   int has_operand_number = -1;
   3805 
   3806   /* Vectors of pointers to opening quoting directives (like GCC "%<"),
   3807      opening braces, brackets, and parentheses.  Used to detect unbalanced
   3808      tokens.  */
   3809   baltoks_t baltoks;
   3810 
   3811   /* Pointers to the most recent color directives (like GCC's "%r or %R").
   3812      A starting color directive much be terminated before the end of
   3813      the format string.  A terminating directive makes no sense without
   3814      a prior starting directive.  */
   3815   const char *color_begin = NULL;
   3816   const char *color_end = NULL;
   3817 
   3818   init_dollar_format_checking (info->first_arg_num, first_fillin_param);
   3819 
   3820   /* In GCC diagnostic functions check plain directives (substrings within
   3821      the format string that don't start with %) for quoting and punctuations
   3822      problems.  */
   3823   bool ck_plain = (!info->is_raw
   3824 		   && (info->format_type == gcc_diag_format_type
   3825 		       || info->format_type == gcc_tdiag_format_type
   3826 		       || info->format_type == gcc_cdiag_format_type
   3827 		       || info->format_type == gcc_cxxdiag_format_type));
   3828 
   3829   while (*format_chars != 0)
   3830     {
   3831       if (ck_plain)
   3832 	format_chars = check_plain (format_string_loc,
   3833 				    format_string_cst,
   3834 				    orig_format_chars, format_chars,
   3835 				    baltoks);
   3836 
   3837       if (*format_chars == 0 || *format_chars++ != '%')
   3838 	continue;
   3839 
   3840       if (*format_chars == 0)
   3841 	{
   3842 	  format_warning_at_char (format_string_loc, format_string_cst,
   3843 				  format_chars - orig_format_chars,
   3844 				  OPT_Wformat_,
   3845 				  "spurious trailing %<%%%> in format");
   3846 	  continue;
   3847 	}
   3848       if (*format_chars == '%')
   3849 	{
   3850 	  ++format_chars;
   3851 	  continue;
   3852 	}
   3853 
   3854       /* ARGUMENT_PARSER ctor takes FORMAT_CHARS by reference and calls
   3855 	 to ARG_PARSER members may modify the variable.  */
   3856       flag_chars_t flag_chars;
   3857       argument_parser arg_parser (info, format_chars, format_string_cst,
   3858 				  orig_format_chars, format_string_loc,
   3859 				  flag_chars, has_operand_number,
   3860 				  first_fillin_param, fwt_pool, arglocs);
   3861 
   3862       if (!arg_parser.read_any_dollar ())
   3863 	return;
   3864 
   3865       if (!arg_parser.read_format_flags ())
   3866 	return;
   3867 
   3868       /* Read any format width, possibly * or *m$.  */
   3869       if (!arg_parser.read_any_format_width (params, arg_num))
   3870 	return;
   3871 
   3872       /* Read any format left precision (must be a number, not *).  */
   3873       arg_parser.read_any_format_left_precision ();
   3874 
   3875       /* Read any format precision, possibly * or *m$.  */
   3876       if (!arg_parser.read_any_format_precision (params, arg_num))
   3877 	return;
   3878 
   3879       const char *format_start = format_chars;
   3880 
   3881       arg_parser.handle_alloc_chars ();
   3882 
   3883       /* The rest of the conversion specification is the length modifier
   3884 	 (if any), and the conversion specifier, so this is where the
   3885 	 type information starts.  If we need to issue a suggestion
   3886 	 about a type mismatch, then we should preserve everything up
   3887 	 to here. */
   3888       const char *type_start = format_chars;
   3889 
   3890       /* Read any length modifier, if this kind of format has them.  */
   3891       const length_modifier len_modifier
   3892 	= arg_parser.read_any_length_modifier ();
   3893 
   3894       /* Read any modifier (strftime E/O).  */
   3895       arg_parser.read_any_other_modifier ();
   3896 
   3897       char format_char = *format_chars;
   3898       if (format_char == 0
   3899 	  || (!(fki->flags & (int) FMT_FLAG_FANCY_PERCENT_OK)
   3900 	      && format_char == '%'))
   3901 	{
   3902 	  format_warning_at_char (format_string_loc, format_string_cst,
   3903 			     format_chars - orig_format_chars,
   3904 			     OPT_Wformat_,
   3905 			     "conversion lacks type at end of format");
   3906 	  continue;
   3907 	}
   3908 
   3909       if (format_char == 'm' && !(fki->flags & FMT_FLAG_M_OK))
   3910         {
   3911 	  warning (OPT_Wformat_,
   3912 	      "%%m is only allowed in syslog(3) like functions");
   3913 	  continue;
   3914 	}
   3915 
   3916       format_chars++;
   3917 
   3918       const format_char_info * const fci
   3919 	= arg_parser.find_format_char_info (format_char);
   3920       if (!fci)
   3921 	continue;
   3922 
   3923       flag_chars.validate (fki, fci, flag_specs, format_chars,
   3924 			   format_string_cst,
   3925 			   format_string_loc, orig_format_chars, format_char,
   3926 			   baltoks.quotdirs.length () > 0);
   3927 
   3928       const int alloc_flag = flag_chars.get_alloc_flag (fki);
   3929       const bool suppressed = flag_chars.assignment_suppression_p (fki);
   3930 
   3931       /* Diagnose nested or unmatched quoting directives such as GCC's
   3932 	 "%<...%<" and "%>...%>".  */
   3933       bool quot_begin_p = strchr (fci->flags2, '<');
   3934       bool quot_end_p = strchr (fci->flags2, '>');
   3935 
   3936       if (quot_begin_p && !quot_end_p)
   3937 	{
   3938 	  if (baltoks.quotdirs.length ())
   3939 	    format_warning_at_char (format_string_loc, format_string_cst,
   3940 				    format_chars - orig_format_chars,
   3941 				    OPT_Wformat_,
   3942 				    "nested quoting directive");
   3943 	  baltoks.quotdirs.safe_push (format_chars);
   3944 	}
   3945       else if (!quot_begin_p && quot_end_p)
   3946 	{
   3947 	  if (baltoks.quotdirs.length ())
   3948 	    baltoks.quotdirs.pop ();
   3949 	  else
   3950 	    format_warning_at_char (format_string_loc, format_string_cst,
   3951 				    format_chars - orig_format_chars,
   3952 				    OPT_Wformat_,
   3953 				    "unmatched quoting directive");
   3954 	}
   3955 
   3956       bool color_begin_p = strchr (fci->flags2, '/');
   3957       if (color_begin_p)
   3958 	{
   3959 	  color_begin = format_chars;
   3960 	  color_end = NULL;
   3961 	}
   3962       else if (strchr (fci->flags2, '\\'))
   3963 	{
   3964 	  if (color_end)
   3965 	    format_warning_at_char (format_string_loc, format_string_cst,
   3966 				    format_chars - orig_format_chars,
   3967 				    OPT_Wformat_,
   3968 				    "%qc directive redundant after prior "
   3969 				    "occurence of the same", format_char);
   3970 	  else if (!color_begin)
   3971 	    format_warning_at_char (format_string_loc, format_string_cst,
   3972 				    format_chars - orig_format_chars,
   3973 				    OPT_Wformat_,
   3974 				    "unmatched color reset directive");
   3975 	  color_end = format_chars;
   3976 	}
   3977 
   3978       /* Diagnose directives that shouldn't appear in a quoted sequence.
   3979 	 (They are denoted by a double quote in FLAGS2.)  */
   3980       if (baltoks.quotdirs.length ())
   3981 	{
   3982 	  if (strchr (fci->flags2, '"'))
   3983 	    format_warning_at_char (format_string_loc, format_string_cst,
   3984 				    format_chars - orig_format_chars,
   3985 				    OPT_Wformat_,
   3986 				    "%qc conversion used within a quoted "
   3987 				    "sequence",
   3988 				    format_char);
   3989 	}
   3990 
   3991       /* Validate the pairs of flags used.  */
   3992       arg_parser.validate_flag_pairs (fci, format_char);
   3993 
   3994       arg_parser.give_y2k_warnings (fci, format_char);
   3995 
   3996       arg_parser.parse_any_scan_set (fci);
   3997 
   3998       tree wanted_type = NULL;
   3999       const char *wanted_type_name = NULL;
   4000 
   4001       if (!arg_parser.handle_conversions (fci, len_modifier,
   4002 					  wanted_type, wanted_type_name,
   4003 					  arg_num,
   4004 					  params,
   4005 					  format_char))
   4006 	continue;
   4007 
   4008       arg_parser.main_wanted_type.next = NULL;
   4009 
   4010       /* Finally. . .check type of argument against desired type!  */
   4011       if (!arg_parser.check_argument_type (fci, len_modifier,
   4012 					   wanted_type, wanted_type_name,
   4013 					   suppressed,
   4014 					   arg_num, params,
   4015 					   alloc_flag,
   4016 					   format_start, type_start,
   4017 					   fmt_param_loc,
   4018 					   format_char))
   4019 	return;
   4020     }
   4021 
   4022   if (format_chars - orig_format_chars != format_length)
   4023     format_warning_at_char (format_string_loc, format_string_cst,
   4024 			    format_chars + 1 - orig_format_chars,
   4025 			    OPT_Wformat_contains_nul,
   4026 			    "embedded %<\\0%> in format");
   4027   if (info->first_arg_num != 0 && params != 0
   4028       && has_operand_number <= 0)
   4029     {
   4030       res->number_other--;
   4031       res->number_extra_args++;
   4032     }
   4033   if (has_operand_number > 0)
   4034     finish_dollar_format_checking (res, fki->flags & (int) FMT_FLAG_DOLLAR_GAP_POINTER_OK);
   4035 
   4036   maybe_diag_unbalanced_tokens (format_string_loc, orig_format_chars,
   4037 				format_string_cst, baltoks);
   4038 
   4039   if (color_begin && !color_end)
   4040     format_warning_at_char (format_string_loc, format_string_cst,
   4041 			    color_begin - orig_format_chars,
   4042 			    OPT_Wformat_, "unterminated color directive");
   4043 }
   4044 
   4045 /* Check the argument types from a single format conversion (possibly
   4046    including width and precision arguments).
   4047 
   4048    FMT_LOC is the location of the format conversion.
   4049 
   4050    TYPES is a singly-linked list expressing the parts of the format
   4051    conversion that expect argument types, and the arguments they
   4052    correspond to.
   4053 
   4054    OFFSET_TO_TYPE_START is the offset within the execution-charset encoded
   4055    format string to where type information begins for the conversion
   4056    (the length modifier and conversion specifier).
   4057 
   4058    CONVERSION_CHAR is the user-provided conversion specifier.
   4059 
   4060    For example, given:
   4061 
   4062      sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
   4063 
   4064    then FMT_LOC covers this range:
   4065 
   4066      sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
   4067                          ^^^^^^^^^
   4068 
   4069    and TYPES in this case is a three-entry singly-linked list consisting of:
   4070    (1) the check for the field width here:
   4071          sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
   4072                                 ^              ^^^^
   4073        against arg3, and
   4074    (2) the check for the field precision here:
   4075          sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
   4076                                  ^^                  ^^^^
   4077        against arg4, and
   4078    (3) the check for the length modifier and conversion char here:
   4079          sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
   4080                                    ^^^                     ^^^^
   4081        against arg5.
   4082 
   4083    OFFSET_TO_TYPE_START is 13, the offset to the "lld" within the
   4084    STRING_CST:
   4085 
   4086                   0000000000111111111122
   4087                   0123456789012345678901
   4088      sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
   4089                                ^ ^
   4090                                | ` CONVERSION_CHAR: 'd'
   4091                                type starts here.  */
   4092 
   4093 static void
   4094 check_format_types (const substring_loc &fmt_loc,
   4095 		    format_wanted_type *types, const format_kind_info *fki,
   4096 		    int offset_to_type_start,
   4097 		    char conversion_char,
   4098 		    vec<location_t> *arglocs)
   4099 {
   4100   for (; types != 0; types = types->next)
   4101     {
   4102       tree cur_param;
   4103       tree cur_type;
   4104       tree orig_cur_type;
   4105       tree wanted_type;
   4106       int arg_num;
   4107       int i;
   4108       int char_type_flag;
   4109 
   4110       wanted_type = types->wanted_type;
   4111       arg_num = types->arg_num;
   4112 
   4113       /* The following should not occur here.  */
   4114       gcc_assert (wanted_type);
   4115       gcc_assert (wanted_type != void_type_node || types->pointer_count);
   4116 
   4117       if (types->pointer_count == 0)
   4118 	wanted_type = lang_hooks.types.type_promotes_to (wanted_type);
   4119 
   4120       wanted_type = TYPE_MAIN_VARIANT (wanted_type);
   4121 
   4122       cur_param = types->param;
   4123       if (!cur_param)
   4124         {
   4125 	  format_type_warning (fmt_loc, UNKNOWN_LOCATION, types, wanted_type,
   4126 			       NULL, fki, offset_to_type_start,
   4127 			       conversion_char);
   4128           continue;
   4129         }
   4130 
   4131       cur_type = TREE_TYPE (cur_param);
   4132       if (cur_type == error_mark_node)
   4133 	continue;
   4134       orig_cur_type = cur_type;
   4135       char_type_flag = 0;
   4136 
   4137       location_t param_loc = UNKNOWN_LOCATION;
   4138       if (EXPR_HAS_LOCATION (cur_param))
   4139 	param_loc = EXPR_LOCATION (cur_param);
   4140       else if (arglocs)
   4141 	{
   4142 	  /* arg_num is 1-based.  */
   4143 	  gcc_assert (types->arg_num > 0);
   4144 	  param_loc = (*arglocs)[types->arg_num - 1];
   4145 	}
   4146 
   4147       STRIP_NOPS (cur_param);
   4148 
   4149       /* Check the types of any additional pointer arguments
   4150 	 that precede the "real" argument.  */
   4151       for (i = 0; i < types->pointer_count; ++i)
   4152 	{
   4153 	  if (TREE_CODE (cur_type) == POINTER_TYPE)
   4154 	    {
   4155 	      cur_type = TREE_TYPE (cur_type);
   4156 	      if (cur_type == error_mark_node)
   4157 		break;
   4158 
   4159 	      /* Check for writing through a NULL pointer.  */
   4160 	      if (types->writing_in_flag
   4161 		  && i == 0
   4162 		  && cur_param != 0
   4163 		  && integer_zerop (cur_param))
   4164 		warning (OPT_Wformat_, "writing through null pointer "
   4165 			 "(argument %d)", arg_num);
   4166 
   4167 	      /* Check for reading through a NULL pointer.  Ignore
   4168 		 printf-family of functions as they are checked for
   4169 		 null arguments by the middle-end.  */
   4170 	      if (fki->conversion_specs != print_char_table
   4171 		  && types->reading_from_flag
   4172 		  && i == 0
   4173 		  && cur_param != 0
   4174 		  && integer_zerop (cur_param))
   4175 		warning (OPT_Wformat_, "reading through null pointer "
   4176 			 "(argument %d)", arg_num);
   4177 
   4178 	      if (cur_param != 0 && TREE_CODE (cur_param) == ADDR_EXPR)
   4179 		cur_param = TREE_OPERAND (cur_param, 0);
   4180 	      else
   4181 		cur_param = 0;
   4182 
   4183 	      /* See if this is an attempt to write into a const type with
   4184 		 scanf or with printf "%n".  Note: the writing in happens
   4185 		 at the first indirection only, if for example
   4186 		 void * const * is passed to scanf %p; passing
   4187 		 const void ** is simply passing an incompatible type.  */
   4188 	      if (types->writing_in_flag
   4189 		  && i == 0
   4190 		  && (TYPE_READONLY (cur_type)
   4191 		      || (cur_param != 0
   4192 			  && (CONSTANT_CLASS_P (cur_param)
   4193 			      || (DECL_P (cur_param)
   4194 				  && TREE_READONLY (cur_param))))))
   4195 		warning (OPT_Wformat_, "writing into constant object "
   4196 			 "(argument %d)", arg_num);
   4197 
   4198 	      /* If there are extra type qualifiers beyond the first
   4199 		 indirection, then this makes the types technically
   4200 		 incompatible.  */
   4201 	      if (i > 0
   4202 		  && pedantic
   4203 		  && (TYPE_READONLY (cur_type)
   4204 		      || TYPE_VOLATILE (cur_type)
   4205 		      || TYPE_ATOMIC (cur_type)
   4206 		      || TYPE_RESTRICT (cur_type)))
   4207 		warning (OPT_Wformat_, "extra type qualifiers in format "
   4208 			 "argument (argument %d)",
   4209 			 arg_num);
   4210 
   4211 	    }
   4212 	  else
   4213 	    {
   4214 	      format_type_warning (fmt_loc, param_loc,
   4215 				   types, wanted_type, orig_cur_type, fki,
   4216 				   offset_to_type_start, conversion_char);
   4217 	      break;
   4218 	    }
   4219 	}
   4220 
   4221       if (i < types->pointer_count)
   4222 	continue;
   4223 
   4224       cur_type = TYPE_MAIN_VARIANT (cur_type);
   4225 
   4226       /* Check whether the argument type is a character type.  This leniency
   4227 	 only applies to certain formats, flagged with 'c'.  */
   4228       if (types->char_lenient_flag)
   4229 	char_type_flag = (cur_type == char_type_node
   4230 			  || cur_type == signed_char_type_node
   4231 			  || cur_type == unsigned_char_type_node);
   4232 
   4233       /* Check the type of the "real" argument, if there's a type we want.  */
   4234       if (lang_hooks.types_compatible_p (wanted_type, cur_type))
   4235 	continue;
   4236       /* If we want 'void *', allow any pointer type.
   4237 	 (Anything else would already have got a warning.)
   4238 	 With -Wpedantic, only allow pointers to void and to character
   4239 	 types.  */
   4240       if (wanted_type == void_type_node
   4241 	  && (!pedantic || (i == 1 && char_type_flag)))
   4242 	continue;
   4243       /* Don't warn about differences merely in signedness, unless
   4244 	 -Wpedantic.  With -Wpedantic, warn if the type is a pointer
   4245 	 target and not a character type, and for character types at
   4246 	 a second level of indirection.  */
   4247       if (TREE_CODE (wanted_type) == INTEGER_TYPE
   4248 	  && TREE_CODE (cur_type) == INTEGER_TYPE
   4249 	  && ((!pedantic && !warn_format_signedness)
   4250 	      || (i == 0 && !warn_format_signedness)
   4251 	      || (i == 1 && char_type_flag))
   4252 	  && (TYPE_UNSIGNED (wanted_type)
   4253 	      ? wanted_type == c_common_unsigned_type (cur_type)
   4254 	      : wanted_type == c_common_signed_type (cur_type)))
   4255 	continue;
   4256       /* Don't warn about differences merely in signedness if we know
   4257 	 that the current type is integer-promoted and its original type
   4258 	 was unsigned such as that it is in the range of WANTED_TYPE.  */
   4259       if (TREE_CODE (wanted_type) == INTEGER_TYPE
   4260 	  && TREE_CODE (cur_type) == INTEGER_TYPE
   4261 	  && warn_format_signedness
   4262 	  && TYPE_UNSIGNED (wanted_type)
   4263 	  && cur_param != NULL_TREE
   4264 	  && TREE_CODE (cur_param) == NOP_EXPR)
   4265 	{
   4266 	  tree t = TREE_TYPE (TREE_OPERAND (cur_param, 0));
   4267 	  if (TYPE_UNSIGNED (t)
   4268 	      && cur_type == lang_hooks.types.type_promotes_to (t))
   4269 	    continue;
   4270 	}
   4271       /* Likewise, "signed char", "unsigned char" and "char" are
   4272 	 equivalent but the above test won't consider them equivalent.  */
   4273       if (wanted_type == char_type_node
   4274 	  && (!pedantic || i < 2)
   4275 	  && char_type_flag)
   4276 	continue;
   4277       if (types->scalar_identity_flag
   4278 	  && (TREE_CODE (cur_type) == TREE_CODE (wanted_type)
   4279 	      || (INTEGRAL_TYPE_P (cur_type)
   4280 		  && INTEGRAL_TYPE_P (wanted_type)))
   4281 	  && TYPE_PRECISION (cur_type) == TYPE_PRECISION (wanted_type))
   4282 	continue;
   4283       /* Now we have a type mismatch.  */
   4284       format_type_warning (fmt_loc, param_loc, types,
   4285 			   wanted_type, orig_cur_type, fki,
   4286 			   offset_to_type_start, conversion_char);
   4287     }
   4288 }
   4289 
   4290 /* Given type TYPE, attempt to dereference the type N times
   4291    (e.g. from ("int ***", 2) to "int *")
   4292 
   4293    Return the derefenced type, with any qualifiers
   4294    such as "const" stripped from the result, or
   4295    NULL if unsuccessful (e.g. TYPE is not a pointer type).  */
   4296 
   4297 static tree
   4298 deref_n_times (tree type, int n)
   4299 {
   4300   gcc_assert (type);
   4301 
   4302   for (int i = n; i > 0; i--)
   4303     {
   4304       if (TREE_CODE (type) != POINTER_TYPE)
   4305 	return NULL_TREE;
   4306       type = TREE_TYPE (type);
   4307     }
   4308   /* Strip off any "const" etc.  */
   4309   return build_qualified_type (type, 0);
   4310 }
   4311 
   4312 /* Lookup the format code for FORMAT_LEN within FLI,
   4313    returning the string code for expressing it, or NULL
   4314    if it is not found.  */
   4315 
   4316 static const char *
   4317 get_modifier_for_format_len (const format_length_info *fli,
   4318 			     enum format_lengths format_len)
   4319 {
   4320   for (; fli->name; fli++)
   4321     {
   4322       if (fli->index == format_len)
   4323 	return fli->name;
   4324       if (fli->double_index == format_len)
   4325 	return fli->double_name;
   4326     }
   4327   return NULL;
   4328 }
   4329 
   4330 #if CHECKING_P
   4331 
   4332 namespace selftest {
   4333 
   4334 static void
   4335 test_get_modifier_for_format_len ()
   4336 {
   4337   ASSERT_STREQ ("h",
   4338 		get_modifier_for_format_len (printf_length_specs, FMT_LEN_h));
   4339   ASSERT_STREQ ("hh",
   4340 		get_modifier_for_format_len (printf_length_specs, FMT_LEN_hh));
   4341   ASSERT_STREQ ("L",
   4342 		get_modifier_for_format_len (printf_length_specs, FMT_LEN_L));
   4343   ASSERT_EQ (NULL,
   4344 	     get_modifier_for_format_len (printf_length_specs, FMT_LEN_none));
   4345 }
   4346 
   4347 } // namespace selftest
   4348 
   4349 #endif /* CHECKING_P */
   4350 
   4351 /* Determine if SPEC_TYPE and ARG_TYPE are sufficiently similar for a
   4352    format_type_detail using SPEC_TYPE to be offered as a suggestion for
   4353    Wformat type errors where the argument has type ARG_TYPE.  */
   4354 
   4355 static bool
   4356 matching_type_p (tree spec_type, tree arg_type)
   4357 {
   4358   gcc_assert (spec_type);
   4359   gcc_assert (arg_type);
   4360 
   4361   /* If any of the types requires structural equality, we can't compare
   4362      their canonical types.  */
   4363   if (TYPE_STRUCTURAL_EQUALITY_P (spec_type)
   4364       || TYPE_STRUCTURAL_EQUALITY_P (arg_type))
   4365     return false;
   4366 
   4367   spec_type = TYPE_CANONICAL (spec_type);
   4368   arg_type = TYPE_CANONICAL (arg_type);
   4369 
   4370   if (TREE_CODE (spec_type) == INTEGER_TYPE
   4371       && TREE_CODE (arg_type) == INTEGER_TYPE
   4372       && (TYPE_UNSIGNED (spec_type)
   4373 	  ? spec_type == c_common_unsigned_type (arg_type)
   4374 	  : spec_type == c_common_signed_type (arg_type)))
   4375     return true;
   4376 
   4377   return spec_type == arg_type;
   4378 }
   4379 
   4380 /* Subroutine of get_format_for_type.
   4381 
   4382    Generate a string containing the length modifier and conversion specifier
   4383    that should be used to format arguments of type ARG_TYPE within FKI
   4384    (effectively the inverse of the checking code).
   4385 
   4386    If CONVERSION_CHAR is not zero (the first pass), the resulting suggestion
   4387    is required to use it, for correcting bogus length modifiers.
   4388    If CONVERSION_CHAR is zero (the second pass), then allow any suggestion
   4389    that matches ARG_TYPE.
   4390 
   4391    If successful, returns a non-NULL string which should be freed
   4392    by the caller.
   4393    Otherwise, returns NULL.  */
   4394 
   4395 static char *
   4396 get_format_for_type_1 (const format_kind_info *fki, tree arg_type,
   4397 		       char conversion_char)
   4398 {
   4399   gcc_assert (arg_type);
   4400 
   4401   const format_char_info *spec;
   4402   for (spec = &fki->conversion_specs[0];
   4403        spec->format_chars;
   4404        spec++)
   4405     {
   4406       if (conversion_char)
   4407 	if (!strchr (spec->format_chars, conversion_char))
   4408 	  continue;
   4409 
   4410       tree effective_arg_type = deref_n_times (arg_type,
   4411 					       spec->pointer_count);
   4412       if (!effective_arg_type)
   4413 	continue;
   4414       for (int i = 0; i < FMT_LEN_MAX; i++)
   4415 	{
   4416 	  const format_type_detail *ftd = &spec->types[i];
   4417 	  if (!ftd->type || *ftd->type == NULL_TREE)
   4418 	    continue;
   4419 	  if (matching_type_p (*ftd->type, effective_arg_type))
   4420 	    {
   4421 	      const char *len_modifier
   4422 		= get_modifier_for_format_len (fki->length_char_specs,
   4423 					       (enum format_lengths)i);
   4424 	      if (!len_modifier)
   4425 		len_modifier = "";
   4426 
   4427 	      if (conversion_char)
   4428 		/* We found a match, using the given conversion char - the
   4429 		   length modifier was incorrect (or absent).
   4430 		   Provide a suggestion using the conversion char with the
   4431 		   correct length modifier for the type.  */
   4432 		return xasprintf ("%s%c", len_modifier, conversion_char);
   4433 	      else
   4434 		/* 2nd pass: no match was possible using the user-provided
   4435 		   conversion char, but we do have a match without using it.
   4436 		   Provide a suggestion using the first conversion char
   4437 		   listed for the given type.  */
   4438 		return xasprintf ("%s%c", len_modifier, spec->format_chars[0]);
   4439 	    }
   4440 	}
   4441    }
   4442 
   4443   return NULL;
   4444 }
   4445 
   4446 /* Generate a string containing the length modifier and conversion specifier
   4447    that should be used to format arguments of type ARG_TYPE within FKI
   4448    (effectively the inverse of the checking code).
   4449 
   4450    If successful, returns a non-NULL string which should be freed
   4451    by the caller.
   4452    Otherwise, returns NULL.  */
   4453 
   4454 static char *
   4455 get_format_for_type (const format_kind_info *fki, tree arg_type,
   4456 		     char conversion_char)
   4457 {
   4458   gcc_assert (arg_type);
   4459   gcc_assert (conversion_char);
   4460 
   4461   /* First pass: look for a format_char_info containing CONVERSION_CHAR
   4462      If we find one, then presumably the length modifier was incorrect
   4463      (or absent).  */
   4464   char *result = get_format_for_type_1 (fki, arg_type, conversion_char);
   4465   if (result)
   4466     return result;
   4467 
   4468   /* Second pass: we didn't find a match for CONVERSION_CHAR, so try
   4469      matching just on the type. */
   4470   return get_format_for_type_1 (fki, arg_type, '\0');
   4471 }
   4472 
   4473 /* Attempt to get a string for use as a replacement fix-it hint for the
   4474    source range in FMT_LOC.
   4475 
   4476    Preserve all of the text within the range of FMT_LOC up to
   4477    OFFSET_TO_TYPE_START, replacing the rest with an appropriate
   4478    length modifier and conversion specifier for ARG_TYPE, attempting
   4479    to keep the user-provided CONVERSION_CHAR if possible.
   4480 
   4481    For example, given a long vs long long mismatch for arg5 here:
   4482 
   4483     000000000111111111122222222223333333333|
   4484     123456789012345678901234567890123456789` column numbers
   4485                    0000000000111111111122|
   4486                    0123456789012345678901` string offsets
   4487                           V~~~~~~~~ : range of FMT_LOC, from cols 23-31
   4488       sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
   4489                                 ^ ^
   4490                                 | ` CONVERSION_CHAR: 'd'
   4491                                 type starts here
   4492 
   4493    where OFFSET_TO_TYPE_START is 13 (the offset to the "lld" within the
   4494    STRING_CST), where the user provided:
   4495      %-+*.*lld
   4496    the result (assuming "long" argument 5) should be:
   4497      %-+*.*ld
   4498 
   4499    If successful, returns a non-NULL string which should be freed
   4500    by the caller.
   4501    Otherwise, returns NULL.  */
   4502 
   4503 static char *
   4504 get_corrected_substring (const substring_loc &fmt_loc,
   4505 			 format_wanted_type *type, tree arg_type,
   4506 			 const format_kind_info *fki,
   4507 			 int offset_to_type_start, char conversion_char)
   4508 {
   4509   /* Attempt to provide hints for argument types, but not for field widths
   4510      and precisions.  */
   4511   if (!arg_type)
   4512     return NULL;
   4513   if (type->kind != CF_KIND_FORMAT)
   4514     return NULL;
   4515 
   4516   /* Locate the current code within the source range, rejecting
   4517      any awkward cases where the format string occupies more than
   4518      one line.
   4519      Lookup the place where the type starts (including any length
   4520      modifiers), getting it as the caret location.  */
   4521   substring_loc type_loc (fmt_loc);
   4522   type_loc.set_caret_index (offset_to_type_start);
   4523 
   4524   location_t fmt_substring_loc;
   4525   const char *err = type_loc.get_location (&fmt_substring_loc);
   4526   if (err)
   4527     return NULL;
   4528 
   4529   source_range fmt_substring_range
   4530     = get_range_from_loc (line_table, fmt_substring_loc);
   4531 
   4532   expanded_location caret
   4533     = expand_location_to_spelling_point (fmt_substring_loc);
   4534   expanded_location start
   4535     = expand_location_to_spelling_point (fmt_substring_range.m_start);
   4536   expanded_location finish
   4537     = expand_location_to_spelling_point (fmt_substring_range.m_finish);
   4538   if (caret.file != start.file)
   4539     return NULL;
   4540   if (start.file != finish.file)
   4541     return NULL;
   4542   if (caret.line != start.line)
   4543     return NULL;
   4544   if (start.line != finish.line)
   4545     return NULL;
   4546   if (start.column > caret.column)
   4547     return NULL;
   4548   if (start.column > finish.column)
   4549     return NULL;
   4550   if (caret.column > finish.column)
   4551     return NULL;
   4552 
   4553   char_span line = location_get_source_line (start.file, start.line);
   4554   if (!line)
   4555     return NULL;
   4556 
   4557   /* If we got this far, then we have the line containing the
   4558      existing conversion specification.
   4559 
   4560      Generate a trimmed copy, containing the prefix part of the conversion
   4561      specification, up to the (but not including) the length modifier.
   4562      In the above example, this would be "%-+*.*".  */
   4563   int length_up_to_type = caret.column - start.column;
   4564   char_span prefix_span = line.subspan (start.column - 1, length_up_to_type);
   4565   char *prefix = prefix_span.xstrdup ();
   4566 
   4567   /* Now attempt to generate a suggestion for the rest of the specification
   4568      (length modifier and conversion char), based on ARG_TYPE and
   4569      CONVERSION_CHAR.
   4570      In the above example, this would be "ld".  */
   4571   char *format_for_type = get_format_for_type (fki, arg_type, conversion_char);
   4572   if (!format_for_type)
   4573     {
   4574       free (prefix);
   4575       return NULL;
   4576     }
   4577 
   4578   /* Success.  Generate the resulting suggestion for the whole range of
   4579      FMT_LOC by concatenating the two strings.
   4580      In the above example, this would be "%-+*.*ld".  */
   4581   char *result = concat (prefix, format_for_type, NULL);
   4582   free (format_for_type);
   4583   free (prefix);
   4584   return result;
   4585 }
   4586 
   4587 /* Helper class for adding zero or more trailing '*' to types.
   4588 
   4589    The format type and name exclude any '*' for pointers, so those
   4590    must be formatted manually.  For all the types we currently have,
   4591    this is adequate, but formats taking pointers to functions or
   4592    arrays would require the full type to be built up in order to
   4593    print it with %T.  */
   4594 
   4595 class indirection_suffix
   4596 {
   4597  public:
   4598   indirection_suffix (int pointer_count) : m_pointer_count (pointer_count) {}
   4599 
   4600   /* Determine the size of the buffer (including NUL-terminator).  */
   4601 
   4602   size_t get_buffer_size () const
   4603   {
   4604     return m_pointer_count + 2;
   4605   }
   4606 
   4607   /* Write the '*' to DST and add a NUL-terminator.  */
   4608 
   4609   void fill_buffer (char *dst) const
   4610   {
   4611     if (m_pointer_count == 0)
   4612       dst[0] = 0;
   4613     else if (c_dialect_cxx ())
   4614       {
   4615 	memset (dst, '*', m_pointer_count);
   4616 	dst[m_pointer_count] = 0;
   4617       }
   4618     else
   4619       {
   4620 	dst[0] = ' ';
   4621 	memset (dst + 1, '*', m_pointer_count);
   4622 	dst[m_pointer_count + 1] = 0;
   4623       }
   4624   }
   4625 
   4626  private:
   4627   int m_pointer_count;
   4628 };
   4629 
   4630 /* Subclass of range_label for labelling the range in the format string
   4631    with the type in question, adding trailing '*' for pointer_count.  */
   4632 
   4633 class range_label_for_format_type_mismatch
   4634   : public range_label_for_type_mismatch
   4635 {
   4636  public:
   4637   range_label_for_format_type_mismatch (tree labelled_type, tree other_type,
   4638 					int pointer_count)
   4639   : range_label_for_type_mismatch (labelled_type, other_type),
   4640     m_pointer_count (pointer_count)
   4641   {
   4642   }
   4643 
   4644   label_text get_text (unsigned range_idx) const FINAL OVERRIDE
   4645   {
   4646     label_text text = range_label_for_type_mismatch::get_text (range_idx);
   4647     if (text.m_buffer == NULL)
   4648       return text;
   4649 
   4650     indirection_suffix suffix (m_pointer_count);
   4651     char *p = (char *) alloca (suffix.get_buffer_size ());
   4652     suffix.fill_buffer (p);
   4653 
   4654     char *result = concat (text.m_buffer, p, NULL);
   4655     text.maybe_free ();
   4656     return label_text::take (result);
   4657   }
   4658 
   4659  private:
   4660   int m_pointer_count;
   4661 };
   4662 
   4663 /* Give a warning about a format argument of different type from that expected.
   4664    The range of the diagnostic is taken from WHOLE_FMT_LOC; the caret location
   4665    is based on the location of the char at TYPE->offset_loc.
   4666    PARAM_LOC is the location of the relevant argument, or UNKNOWN_LOCATION
   4667    if this is unavailable.
   4668    WANTED_TYPE is the type the argument should have,
   4669    possibly stripped of pointer dereferences.  The description (such as "field
   4670    precision"), the placement in the format string, a possibly more
   4671    friendly name of WANTED_TYPE, and the number of pointer dereferences
   4672    are taken from TYPE.  ARG_TYPE is the type of the actual argument,
   4673    or NULL if it is missing.
   4674 
   4675    OFFSET_TO_TYPE_START is the offset within the execution-charset encoded
   4676    format string to where type information begins for the conversion
   4677    (the length modifier and conversion specifier).
   4678    CONVERSION_CHAR is the user-provided conversion specifier.
   4679 
   4680    For example, given a type mismatch for argument 5 here:
   4681 
   4682     00000000011111111112222222222333333333344444444445555555555|
   4683     12345678901234567890123456789012345678901234567890123456789` column numbers
   4684                    0000000000111111111122|
   4685                    0123456789012345678901` offsets within STRING_CST
   4686                           V~~~~~~~~ : range of WHOLE_FMT_LOC, from cols 23-31
   4687       sprintf (d, "before %-+*.*lld after", int_expr, int_expr, long_expr);
   4688                                 ^ ^                             ^~~~~~~~~
   4689                                 | ` CONVERSION_CHAR: 'd'        PARAM_LOC
   4690                                 type starts here
   4691 
   4692    OFFSET_TO_TYPE_START is 13, the offset to the "lld" within the
   4693    STRING_CST.  */
   4694 
   4695 static void
   4696 format_type_warning (const substring_loc &whole_fmt_loc,
   4697 		     location_t param_loc,
   4698 		     format_wanted_type *type,
   4699 		     tree wanted_type, tree arg_type,
   4700 		     const format_kind_info *fki,
   4701 		     int offset_to_type_start,
   4702 		     char conversion_char)
   4703 {
   4704   enum format_specifier_kind kind = type->kind;
   4705   const char *wanted_type_name = type->wanted_type_name;
   4706   const char *format_start = type->format_start;
   4707   int format_length = type->format_length;
   4708   int pointer_count = type->pointer_count;
   4709   int arg_num = type->arg_num;
   4710 
   4711   /* If ARG_TYPE is a typedef with a misleading name (for example,
   4712      size_t but not the standard size_t expected by printf %zu), avoid
   4713      printing the typedef name.  */
   4714   if (wanted_type_name
   4715       && arg_type
   4716       && TYPE_NAME (arg_type)
   4717       && TREE_CODE (TYPE_NAME (arg_type)) == TYPE_DECL
   4718       && DECL_NAME (TYPE_NAME (arg_type))
   4719       && !strcmp (wanted_type_name,
   4720 		  lang_hooks.decl_printable_name (TYPE_NAME (arg_type), 2)))
   4721     arg_type = TYPE_MAIN_VARIANT (arg_type);
   4722 
   4723   indirection_suffix suffix (pointer_count);
   4724   char *p = (char *) alloca (suffix.get_buffer_size ());
   4725   suffix.fill_buffer (p);
   4726 
   4727   /* WHOLE_FMT_LOC has the caret at the end of the range.
   4728      Set the caret to be at the offset from TYPE.  Subtract one
   4729      from the offset for the same reason as in format_warning_at_char.  */
   4730   substring_loc fmt_loc (whole_fmt_loc);
   4731   fmt_loc.set_caret_index (type->offset_loc - 1);
   4732 
   4733   range_label_for_format_type_mismatch fmt_label (wanted_type, arg_type,
   4734 						  pointer_count);
   4735   range_label_for_type_mismatch param_label (arg_type, wanted_type);
   4736 
   4737   /* Get a string for use as a replacement fix-it hint for the range in
   4738      fmt_loc, or NULL.  */
   4739   char *corrected_substring
   4740     = get_corrected_substring (fmt_loc, type, arg_type, fki,
   4741 			       offset_to_type_start, conversion_char);
   4742   format_string_diagnostic_t diag (fmt_loc, &fmt_label, param_loc, &param_label,
   4743 				   corrected_substring);
   4744   if (wanted_type_name)
   4745     {
   4746       if (arg_type)
   4747 	diag.emit_warning
   4748 	  (OPT_Wformat_,
   4749 	   "%s %<%s%.*s%> expects argument of type %<%s%s%>, "
   4750 	   "but argument %d has type %qT",
   4751 	   gettext (kind_descriptions[kind]),
   4752 	   (kind == CF_KIND_FORMAT ? "%" : ""),
   4753 	   format_length, format_start,
   4754 	   wanted_type_name, p, arg_num, arg_type);
   4755       else
   4756 	diag.emit_warning
   4757 	  (OPT_Wformat_,
   4758 	   "%s %<%s%.*s%> expects a matching %<%s%s%> argument",
   4759 	   gettext (kind_descriptions[kind]),
   4760 	   (kind == CF_KIND_FORMAT ? "%" : ""),
   4761 	   format_length, format_start, wanted_type_name, p);
   4762     }
   4763   else
   4764     {
   4765       if (arg_type)
   4766 	diag.emit_warning
   4767 	  (OPT_Wformat_,
   4768 	   "%s %<%s%.*s%> expects argument of type %<%T%s%>, "
   4769 	   "but argument %d has type %qT",
   4770 	   gettext (kind_descriptions[kind]),
   4771 	   (kind == CF_KIND_FORMAT ? "%" : ""),
   4772 	   format_length, format_start,
   4773 	   wanted_type, p, arg_num, arg_type);
   4774       else
   4775 	diag.emit_warning
   4776 	  (OPT_Wformat_,
   4777 	   "%s %<%s%.*s%> expects a matching %<%T%s%> argument",
   4778 	   gettext (kind_descriptions[kind]),
   4779 	   (kind == CF_KIND_FORMAT ? "%" : ""),
   4780 	   format_length, format_start, wanted_type, p);
   4781     }
   4782 
   4783   free (corrected_substring);
   4784 }
   4785 
   4786 
   4787 /* Given a format_char_info array FCI, and a character C, this function
   4788    returns the index into the conversion_specs where that specifier's
   4789    data is located.  The character must exist.  */
   4790 static unsigned int
   4791 find_char_info_specifier_index (const format_char_info *fci, int c)
   4792 {
   4793   unsigned i;
   4794 
   4795   for (i = 0; fci->format_chars; i++, fci++)
   4796     if (strchr (fci->format_chars, c))
   4797       return i;
   4798 
   4799   /* We shouldn't be looking for a non-existent specifier.  */
   4800   gcc_unreachable ();
   4801 }
   4802 
   4803 /* Given a format_length_info array FLI, and a character C, this
   4804    function returns the index into the conversion_specs where that
   4805    modifier's data is located.  The character must exist.  */
   4806 static unsigned int
   4807 find_length_info_modifier_index (const format_length_info *fli, int c)
   4808 {
   4809   unsigned i;
   4810 
   4811   for (i = 0; fli->name; i++, fli++)
   4812     if (strchr (fli->name, c))
   4813       return i;
   4814 
   4815   /* We shouldn't be looking for a non-existent modifier.  */
   4816   gcc_unreachable ();
   4817 }
   4818 
   4819 /* Determine the type of HOST_WIDE_INT in the code being compiled for
   4820    use in GCC's __asm_fprintf__ custom format attribute.  You must
   4821    have set dynamic_format_types before calling this function.  */
   4822 static void
   4823 init_dynamic_asm_fprintf_info (void)
   4824 {
   4825   static tree hwi;
   4826 
   4827   if (!hwi)
   4828     {
   4829       format_length_info *new_asm_fprintf_length_specs;
   4830       unsigned int i;
   4831 
   4832       /* Find the underlying type for HOST_WIDE_INT.  For the %w
   4833 	 length modifier to work, one must have issued: "typedef
   4834 	 HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code
   4835 	 prior to using that modifier.  */
   4836       hwi = maybe_get_identifier ("__gcc_host_wide_int__");
   4837       if (!hwi)
   4838 	{
   4839 	  error ("%<__gcc_host_wide_int__%> is not defined as a type");
   4840 	  return;
   4841 	}
   4842       hwi = identifier_global_value (hwi);
   4843       if (!hwi || TREE_CODE (hwi) != TYPE_DECL)
   4844 	{
   4845 	  error ("%<__gcc_host_wide_int__%> is not defined as a type");
   4846 	  return;
   4847 	}
   4848       hwi = DECL_ORIGINAL_TYPE (hwi);
   4849       gcc_assert (hwi);
   4850       if (hwi != long_integer_type_node && hwi != long_long_integer_type_node)
   4851 	{
   4852 	  error ("%<__gcc_host_wide_int__%> is not defined as %<long%>"
   4853 		 " or %<long long%>");
   4854 	  return;
   4855 	}
   4856 
   4857       /* Create a new (writable) copy of asm_fprintf_length_specs.  */
   4858       new_asm_fprintf_length_specs = (format_length_info *)
   4859 				     xmemdup (asm_fprintf_length_specs,
   4860 					      sizeof (asm_fprintf_length_specs),
   4861 					      sizeof (asm_fprintf_length_specs));
   4862 
   4863       /* HOST_WIDE_INT must be one of 'long' or 'long long'.  */
   4864       i = find_length_info_modifier_index (new_asm_fprintf_length_specs, 'w');
   4865       if (hwi == long_integer_type_node)
   4866 	new_asm_fprintf_length_specs[i].index = FMT_LEN_l;
   4867       else if (hwi == long_long_integer_type_node)
   4868 	new_asm_fprintf_length_specs[i].index = FMT_LEN_ll;
   4869       else
   4870 	gcc_unreachable ();
   4871 
   4872       /* Assign the new data for use.  */
   4873       dynamic_format_types[asm_fprintf_format_type].length_char_specs =
   4874 	new_asm_fprintf_length_specs;
   4875     }
   4876 }
   4877 
   4878 static const format_length_info*
   4879 get_init_dynamic_hwi (void)
   4880 {
   4881   static tree hwi;
   4882   static format_length_info *diag_ls;
   4883 
   4884   if (!hwi)
   4885     {
   4886       unsigned int i;
   4887 
   4888       /* Find the underlying type for HOST_WIDE_INT.  For the 'w'
   4889 	 length modifier to work, one must have issued: "typedef
   4890 	 HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code
   4891 	 prior to using that modifier.  */
   4892       if ((hwi = maybe_get_identifier ("__gcc_host_wide_int__")))
   4893 	{
   4894 	  hwi = identifier_global_value (hwi);
   4895 	  if (hwi)
   4896 	    {
   4897 	      if (TREE_CODE (hwi) != TYPE_DECL)
   4898 		{
   4899 		  error ("%<__gcc_host_wide_int__%> is not defined as a type");
   4900 		  hwi = 0;
   4901 		}
   4902 	      else
   4903 		{
   4904 		  hwi = DECL_ORIGINAL_TYPE (hwi);
   4905 		  gcc_assert (hwi);
   4906 		  if (hwi != long_integer_type_node
   4907 		      && hwi != long_long_integer_type_node)
   4908 		    {
   4909 		      error ("%<__gcc_host_wide_int__%> is not defined"
   4910 			     " as %<long%> or %<long long%>");
   4911 		      hwi = 0;
   4912 		    }
   4913 		}
   4914 	    }
   4915 	}
   4916       if (!diag_ls)
   4917 	diag_ls = (format_length_info *)
   4918 		  xmemdup (gcc_diag_length_specs,
   4919 			   sizeof (gcc_diag_length_specs),
   4920 			   sizeof (gcc_diag_length_specs));
   4921       if (hwi)
   4922 	{
   4923 	  /* HOST_WIDE_INT must be one of 'long' or 'long long'.  */
   4924 	  i = find_length_info_modifier_index (diag_ls, 'w');
   4925 	  if (hwi == long_integer_type_node)
   4926 	    diag_ls[i].index = FMT_LEN_l;
   4927 	  else if (hwi == long_long_integer_type_node)
   4928 	    diag_ls[i].index = FMT_LEN_ll;
   4929 	  else
   4930 	    gcc_unreachable ();
   4931 	}
   4932     }
   4933   return diag_ls;
   4934 }
   4935 
   4936 /* Determine the type of a "locus" in the code being compiled for use
   4937    in GCC's __gcc_gfc__ custom format attribute.  You must have set
   4938    dynamic_format_types before calling this function.  */
   4939 static void
   4940 init_dynamic_gfc_info (void)
   4941 {
   4942   dynamic_format_types[gcc_gfc_format_type].length_char_specs
   4943     = get_init_dynamic_hwi ();
   4944 
   4945   if (!locus)
   4946     {
   4947       static format_char_info *gfc_fci;
   4948 
   4949       /* For the GCC __gcc_gfc__ custom format specifier to work, one
   4950 	 must have declared 'locus' prior to using this attribute.  If
   4951 	 we haven't seen this declarations then you shouldn't use the
   4952 	 specifier requiring that type.  */
   4953       if ((locus = maybe_get_identifier ("locus")))
   4954 	{
   4955 	  locus = identifier_global_value (locus);
   4956 	  if (locus)
   4957 	    {
   4958 	      if (TREE_CODE (locus) != TYPE_DECL
   4959 		  || TREE_TYPE (locus) == error_mark_node)
   4960 		{
   4961 		  error ("%<locus%> is not defined as a type");
   4962 		  locus = 0;
   4963 		}
   4964 	      else
   4965 		locus = TREE_TYPE (locus);
   4966 	    }
   4967 	}
   4968 
   4969       /* Assign the new data for use.  */
   4970 
   4971       /* Handle the __gcc_gfc__ format specifics.  */
   4972       if (!gfc_fci)
   4973 	dynamic_format_types[gcc_gfc_format_type].conversion_specs =
   4974 	  gfc_fci = (format_char_info *)
   4975 		     xmemdup (gcc_gfc_char_table,
   4976 			      sizeof (gcc_gfc_char_table),
   4977 			      sizeof (gcc_gfc_char_table));
   4978       if (locus)
   4979 	{
   4980 	  const unsigned i = find_char_info_specifier_index (gfc_fci, 'L');
   4981 	  gfc_fci[i].types[0].type = &locus;
   4982 	  gfc_fci[i].pointer_count = 1;
   4983 	}
   4984     }
   4985 }
   4986 
   4987 /* Lookup the type named NAME and return a NAME type if found.
   4988    Otherwise, return void_type_node if NAME has not been used yet,
   4989    or NULL_TREE if NAME is not a type (issuing an error).  */
   4990 
   4991 static tree
   4992 get_named_type (const char *name)
   4993 {
   4994   if (tree result = maybe_get_identifier (name))
   4995     {
   4996       result = identifier_global_tag (result);
   4997       if (result)
   4998 	{
   4999 	  if (TYPE_P (result))
   5000 	    ;
   5001 	  else if (TREE_CODE (result) == TYPE_DECL)
   5002 	    result = TREE_TYPE (result);
   5003 	  else
   5004 	    {
   5005 	      error ("%qs is not defined as a type", name);
   5006 	      result = NULL_TREE;
   5007 	    }
   5008 	}
   5009       return result;
   5010     }
   5011   else
   5012     return void_type_node;
   5013 }
   5014 
   5015 /* Determine the types of "tree" and "location_t" in the code being
   5016    compiled for use in GCC's diagnostic custom format attributes.  You
   5017    must have set dynamic_format_types before calling this function.  */
   5018 static void
   5019 init_dynamic_diag_info (void)
   5020 {
   5021   /* For the GCC-diagnostics custom format specifiers to work, one
   5022      must have declared 'tree' and 'location_t' prior to using those
   5023      attributes.  If we haven't seen these declarations then
   5024      the specifiers requiring these types shouldn't be used.
   5025      However we don't force a hard ICE because we may see only one
   5026      or the other type.  */
   5027   if (tree loc = maybe_get_identifier ("location_t"))
   5028     {
   5029       loc = identifier_global_value (loc);
   5030       if (loc && TREE_CODE (loc) != TYPE_DECL)
   5031 	error ("%<location_t%> is not defined as a type");
   5032     }
   5033 
   5034   /* Initialize the global tree node type local to this file.  */
   5035   if (!local_tree_type_node
   5036       || local_tree_type_node == void_type_node)
   5037     {
   5038       /* We need to grab the underlying 'union tree_node' so peek into
   5039 	 an extra type level.  */
   5040       if ((local_tree_type_node = maybe_get_identifier ("tree")))
   5041 	{
   5042 	  local_tree_type_node
   5043 	    = identifier_global_value (local_tree_type_node);
   5044 	  if (local_tree_type_node)
   5045 	    {
   5046 	      if (TREE_CODE (local_tree_type_node) != TYPE_DECL)
   5047 		{
   5048 		  error ("%<tree%> is not defined as a type");
   5049 		  local_tree_type_node = NULL_TREE;
   5050 		}
   5051 	      else if (TREE_CODE (TREE_TYPE (local_tree_type_node))
   5052 		       != POINTER_TYPE)
   5053 		{
   5054 		  error ("%<tree%> is not defined as a pointer type");
   5055 		  local_tree_type_node = NULL_TREE;
   5056 		}
   5057 	      else
   5058 		local_tree_type_node
   5059 		  = TREE_TYPE (TREE_TYPE (local_tree_type_node));
   5060 	    }
   5061 	}
   5062       else
   5063 	local_tree_type_node = void_type_node;
   5064     }
   5065 
   5066   /* Similar to the above but for gimple*.  */
   5067   if (!local_gimple_ptr_node
   5068       || local_gimple_ptr_node == void_type_node)
   5069     local_gimple_ptr_node = get_named_type ("gimple");
   5070 
   5071   /* Similar to the above but for cgraph_node*.  */
   5072   if (!local_cgraph_node_ptr_node
   5073       || local_cgraph_node_ptr_node == void_type_node)
   5074     local_cgraph_node_ptr_node = get_named_type ("cgraph_node");
   5075 
   5076   /* Similar to the above but for diagnostic_event_id_t*.  */
   5077   if (!local_event_ptr_node
   5078       || local_event_ptr_node == void_type_node)
   5079     local_event_ptr_node = get_named_type ("diagnostic_event_id_t");
   5080 
   5081   /* All the GCC diag formats use the same length specs.  */
   5082   dynamic_format_types[gcc_diag_format_type].length_char_specs =
   5083     dynamic_format_types[gcc_tdiag_format_type].length_char_specs =
   5084     dynamic_format_types[gcc_cdiag_format_type].length_char_specs =
   5085     dynamic_format_types[gcc_cxxdiag_format_type].length_char_specs =
   5086     dynamic_format_types[gcc_dump_printf_format_type].length_char_specs
   5087     = get_init_dynamic_hwi ();
   5088 
   5089   /* It's safe to "re-initialize these to the same values.  */
   5090   dynamic_format_types[gcc_diag_format_type].conversion_specs =
   5091     gcc_diag_char_table;
   5092   dynamic_format_types[gcc_tdiag_format_type].conversion_specs =
   5093     gcc_tdiag_char_table;
   5094   dynamic_format_types[gcc_cdiag_format_type].conversion_specs =
   5095     gcc_cdiag_char_table;
   5096   dynamic_format_types[gcc_cxxdiag_format_type].conversion_specs =
   5097     gcc_cxxdiag_char_table;
   5098   dynamic_format_types[gcc_dump_printf_format_type].conversion_specs =
   5099     gcc_dump_printf_char_table;
   5100 }
   5101 
   5102 #ifdef TARGET_FORMAT_TYPES
   5103 extern const format_kind_info TARGET_FORMAT_TYPES[];
   5104 #endif
   5105 
   5106 #ifdef TARGET_OVERRIDES_FORMAT_ATTRIBUTES
   5107 extern const target_ovr_attr TARGET_OVERRIDES_FORMAT_ATTRIBUTES[];
   5108 #endif
   5109 #ifdef TARGET_OVERRIDES_FORMAT_INIT
   5110   extern void TARGET_OVERRIDES_FORMAT_INIT (void);
   5111 #endif
   5112 
   5113 /* Attributes such as "printf" are equivalent to those such as
   5114    "gnu_printf" unless this is overridden by a target.  */
   5115 static const target_ovr_attr gnu_target_overrides_format_attributes[] =
   5116 {
   5117   { "gnu_printf",   "printf" },
   5118   { "gnu_syslog",   "syslog" },
   5119   { "gnu_scanf",    "scanf" },
   5120   { "gnu_strftime", "strftime" },
   5121   { "gnu_strfmon",  "strfmon" },
   5122   { NULL,           NULL }
   5123 };
   5124 
   5125 /* Translate to unified attribute name. This is used in decode_format_type and
   5126    decode_format_attr. In attr_name the user specified argument is passed. It
   5127    returns the unified format name from TARGET_OVERRIDES_FORMAT_ATTRIBUTES
   5128    or the attr_name passed to this function, if there is no matching entry.  */
   5129 static const char *
   5130 convert_format_name_to_system_name (const char *attr_name)
   5131 {
   5132   int i;
   5133 
   5134   if (attr_name == NULL || *attr_name == 0
   5135       || startswith (attr_name, "gcc_"))
   5136     return attr_name;
   5137 #ifdef TARGET_OVERRIDES_FORMAT_INIT
   5138   TARGET_OVERRIDES_FORMAT_INIT ();
   5139 #endif
   5140 
   5141 #ifdef TARGET_OVERRIDES_FORMAT_ATTRIBUTES
   5142   /* Check if format attribute is overridden by target.  */
   5143   if (TARGET_OVERRIDES_FORMAT_ATTRIBUTES != NULL
   5144       && TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT > 0)
   5145     {
   5146       for (i = 0; i < TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT; ++i)
   5147         {
   5148           if (cmp_attribs (TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_src,
   5149 			   attr_name))
   5150             return attr_name;
   5151           if (cmp_attribs (TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_dst,
   5152 			   attr_name))
   5153             return TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_src;
   5154         }
   5155     }
   5156 #endif
   5157   /* Otherwise default to gnu format.  */
   5158   for (i = 0;
   5159        gnu_target_overrides_format_attributes[i].named_attr_src != NULL;
   5160        ++i)
   5161     {
   5162       if (cmp_attribs (gnu_target_overrides_format_attributes[i].named_attr_src,
   5163 		       attr_name))
   5164         return attr_name;
   5165       if (cmp_attribs (gnu_target_overrides_format_attributes[i].named_attr_dst,
   5166 		       attr_name))
   5167         return gnu_target_overrides_format_attributes[i].named_attr_src;
   5168     }
   5169 
   5170   return attr_name;
   5171 }
   5172 
   5173 /* Handle a "format" attribute; arguments as in
   5174    struct attribute_spec.handler.  */
   5175 tree
   5176 handle_format_attribute (tree *node, tree atname, tree args,
   5177 			 int flags, bool *no_add_attrs)
   5178 {
   5179   const_tree type = *node;
   5180   function_format_info info;
   5181 
   5182 #ifdef TARGET_FORMAT_TYPES
   5183   /* If the target provides additional format types, we need to
   5184      add them to FORMAT_TYPES at first use.  */
   5185   if (!dynamic_format_types)
   5186     {
   5187       dynamic_format_types = XNEWVEC (format_kind_info,
   5188 				      n_format_types + TARGET_N_FORMAT_TYPES);
   5189       memcpy (dynamic_format_types, format_types_orig,
   5190 	      sizeof (format_types_orig));
   5191       memcpy (&dynamic_format_types[n_format_types], TARGET_FORMAT_TYPES,
   5192 	      TARGET_N_FORMAT_TYPES * sizeof (dynamic_format_types[0]));
   5193 
   5194       format_types = dynamic_format_types;
   5195       /* Provide a reference for the first potential external type.  */
   5196       first_target_format_type = n_format_types;
   5197       n_format_types += TARGET_N_FORMAT_TYPES;
   5198     }
   5199 #endif
   5200 
   5201   /* Canonicalize name of format function.  */
   5202   if (TREE_CODE (TREE_VALUE (args)) == IDENTIFIER_NODE)
   5203     TREE_VALUE (args) = canonicalize_attr_name (TREE_VALUE (args));
   5204 
   5205   if (!decode_format_attr (type, atname, args, &info, /* validated_p = */false))
   5206     {
   5207       *no_add_attrs = true;
   5208       return NULL_TREE;
   5209     }
   5210 
   5211   if (prototype_p (type))
   5212     {
   5213       if (!check_format_string (type, info.format_num, flags,
   5214 				no_add_attrs, info.format_type))
   5215 	return NULL_TREE;
   5216 
   5217       if (info.first_arg_num != 0)
   5218 	{
   5219 	  unsigned HOST_WIDE_INT arg_num = 1;
   5220 	  function_args_iterator iter;
   5221 	  tree arg_type;
   5222 
   5223 	  /* Verify that first_arg_num points to the last arg,
   5224 	     the ...  */
   5225 	  FOREACH_FUNCTION_ARGS (type, arg_type, iter)
   5226 	    arg_num++;
   5227 
   5228 	  if (arg_num != info.first_arg_num)
   5229 	    {
   5230 	      if (!(flags & (int) ATTR_FLAG_BUILT_IN))
   5231 		error ("argument to be formatted is not %<...%>");
   5232 	      *no_add_attrs = true;
   5233 	      return NULL_TREE;
   5234 	    }
   5235 	}
   5236     }
   5237 
   5238   /* Check if this is a strftime variant. Just for this variant
   5239      FMT_FLAG_ARG_CONVERT is not set.  */
   5240   if ((format_types[info.format_type].flags & (int) FMT_FLAG_ARG_CONVERT) == 0
   5241       && info.first_arg_num != 0)
   5242     {
   5243       error ("strftime formats cannot format arguments");
   5244       *no_add_attrs = true;
   5245       return NULL_TREE;
   5246     }
   5247 
   5248   /* If this is a custom GCC-internal format type, we have to
   5249      initialize certain bits at runtime.  */
   5250   if (info.format_type == asm_fprintf_format_type
   5251       || info.format_type == gcc_gfc_format_type
   5252       || info.format_type == gcc_diag_format_type
   5253       || info.format_type == gcc_tdiag_format_type
   5254       || info.format_type == gcc_cdiag_format_type
   5255       || info.format_type == gcc_cxxdiag_format_type
   5256       || info.format_type == gcc_dump_printf_format_type)
   5257     {
   5258       /* Our first time through, we have to make sure that our
   5259 	 format_type data is allocated dynamically and is modifiable.  */
   5260       if (!dynamic_format_types)
   5261 	format_types = dynamic_format_types = (format_kind_info *)
   5262 	  xmemdup (format_types_orig, sizeof (format_types_orig),
   5263 		   sizeof (format_types_orig));
   5264 
   5265       /* If this is format __asm_fprintf__, we have to initialize
   5266 	 GCC's notion of HOST_WIDE_INT for checking %wd.  */
   5267       if (info.format_type == asm_fprintf_format_type)
   5268 	init_dynamic_asm_fprintf_info ();
   5269       /* If this is format __gcc_gfc__, we have to initialize GCC's
   5270 	 notion of 'locus' at runtime for %L.  */
   5271       else if (info.format_type == gcc_gfc_format_type)
   5272 	init_dynamic_gfc_info ();
   5273       /* If this is one of the diagnostic attributes, then we have to
   5274 	 initialize 'location_t' and 'tree' at runtime.  */
   5275       else if (info.format_type == gcc_diag_format_type
   5276 	       || info.format_type == gcc_tdiag_format_type
   5277 	       || info.format_type == gcc_cdiag_format_type
   5278 	       || info.format_type == gcc_cxxdiag_format_type
   5279 	       || info.format_type == gcc_dump_printf_format_type)
   5280 	init_dynamic_diag_info ();
   5281       else
   5282 	gcc_unreachable ();
   5283     }
   5284 
   5285   return NULL_TREE;
   5286 }
   5287 
   5288 #if CHECKING_P
   5289 
   5290 namespace selftest {
   5291 
   5292 /* Selftests of location handling.  */
   5293 
   5294 /* Get the format_kind_info with the given name.  */
   5295 
   5296 static const format_kind_info *
   5297 get_info (const char *name)
   5298 {
   5299   int idx = decode_format_type (name);
   5300   const format_kind_info *fki = &format_types[idx];
   5301   ASSERT_STREQ (fki->name, name);
   5302   return fki;
   5303 }
   5304 
   5305 /* Verify that get_format_for_type (FKI, TYPE, CONVERSION_CHAR)
   5306    is EXPECTED_FORMAT.  */
   5307 
   5308 static void
   5309 assert_format_for_type_streq (const location &loc, const format_kind_info *fki,
   5310 			      const char *expected_format, tree type,
   5311 			      char conversion_char)
   5312 {
   5313   gcc_assert (fki);
   5314   gcc_assert (expected_format);
   5315   gcc_assert (type);
   5316 
   5317   char *actual_format = get_format_for_type (fki, type, conversion_char);
   5318   ASSERT_STREQ_AT (loc, expected_format, actual_format);
   5319   free (actual_format);
   5320 }
   5321 
   5322 /* Selftests for get_format_for_type.  */
   5323 
   5324 #define ASSERT_FORMAT_FOR_TYPE_STREQ(EXPECTED_FORMAT, TYPE, CONVERSION_CHAR) \
   5325   assert_format_for_type_streq (SELFTEST_LOCATION, (fki), (EXPECTED_FORMAT), \
   5326 				(TYPE), (CONVERSION_CHAR))
   5327 
   5328 /* Selftest for get_format_for_type for "printf"-style functions.  */
   5329 
   5330 static void
   5331 test_get_format_for_type_printf ()
   5332 {
   5333   const format_kind_info *fki = get_info ("gnu_printf");
   5334   ASSERT_NE (fki, NULL);
   5335 
   5336   ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node, 'i');
   5337   ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node, 'i');
   5338   ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node, 'o');
   5339   ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node, 'o');
   5340   ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node, 'x');
   5341   ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node, 'x');
   5342   ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node, 'X');
   5343   ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node, 'X');
   5344   ASSERT_FORMAT_FOR_TYPE_STREQ ("d", integer_type_node, 'd');
   5345   ASSERT_FORMAT_FOR_TYPE_STREQ ("i", integer_type_node, 'i');
   5346   ASSERT_FORMAT_FOR_TYPE_STREQ ("o", integer_type_node, 'o');
   5347   ASSERT_FORMAT_FOR_TYPE_STREQ ("x", integer_type_node, 'x');
   5348   ASSERT_FORMAT_FOR_TYPE_STREQ ("X", integer_type_node, 'X');
   5349   ASSERT_FORMAT_FOR_TYPE_STREQ ("d", unsigned_type_node, 'd');
   5350   ASSERT_FORMAT_FOR_TYPE_STREQ ("i", unsigned_type_node, 'i');
   5351   ASSERT_FORMAT_FOR_TYPE_STREQ ("o", unsigned_type_node, 'o');
   5352   ASSERT_FORMAT_FOR_TYPE_STREQ ("x", unsigned_type_node, 'x');
   5353   ASSERT_FORMAT_FOR_TYPE_STREQ ("X", unsigned_type_node, 'X');
   5354   ASSERT_FORMAT_FOR_TYPE_STREQ ("ld", long_integer_type_node, 'd');
   5355   ASSERT_FORMAT_FOR_TYPE_STREQ ("li", long_integer_type_node, 'i');
   5356   ASSERT_FORMAT_FOR_TYPE_STREQ ("lx", long_integer_type_node, 'x');
   5357   ASSERT_FORMAT_FOR_TYPE_STREQ ("lo", long_unsigned_type_node, 'o');
   5358   ASSERT_FORMAT_FOR_TYPE_STREQ ("lx", long_unsigned_type_node, 'x');
   5359   ASSERT_FORMAT_FOR_TYPE_STREQ ("lld", long_long_integer_type_node, 'd');
   5360   ASSERT_FORMAT_FOR_TYPE_STREQ ("lli", long_long_integer_type_node, 'i');
   5361   ASSERT_FORMAT_FOR_TYPE_STREQ ("llo", long_long_unsigned_type_node, 'o');
   5362   ASSERT_FORMAT_FOR_TYPE_STREQ ("llx", long_long_unsigned_type_node, 'x');
   5363   ASSERT_FORMAT_FOR_TYPE_STREQ ("s", build_pointer_type (char_type_node), 'i');
   5364 }
   5365 
   5366 /* Selftest for get_format_for_type for "scanf"-style functions.  */
   5367 
   5368 static void
   5369 test_get_format_for_type_scanf ()
   5370 {
   5371   const format_kind_info *fki = get_info ("gnu_scanf");
   5372   ASSERT_NE (fki, NULL);
   5373   ASSERT_FORMAT_FOR_TYPE_STREQ ("d", build_pointer_type (integer_type_node), 'd');
   5374   ASSERT_FORMAT_FOR_TYPE_STREQ ("u", build_pointer_type (unsigned_type_node), 'u');
   5375   ASSERT_FORMAT_FOR_TYPE_STREQ ("ld",
   5376 				build_pointer_type (long_integer_type_node), 'd');
   5377   ASSERT_FORMAT_FOR_TYPE_STREQ ("lu",
   5378 				build_pointer_type (long_unsigned_type_node), 'u');
   5379   ASSERT_FORMAT_FOR_TYPE_STREQ
   5380     ("lld", build_pointer_type (long_long_integer_type_node), 'd');
   5381   ASSERT_FORMAT_FOR_TYPE_STREQ
   5382     ("llu", build_pointer_type (long_long_unsigned_type_node), 'u');
   5383   ASSERT_FORMAT_FOR_TYPE_STREQ ("e", build_pointer_type (float_type_node), 'e');
   5384   ASSERT_FORMAT_FOR_TYPE_STREQ ("le", build_pointer_type (double_type_node), 'e');
   5385 }
   5386 
   5387 #undef ASSERT_FORMAT_FOR_TYPE_STREQ
   5388 
   5389 /* Exercise the type-printing label code, to give some coverage
   5390    under "make selftest-valgrind" (in particular, to ensure that
   5391    the label-printing machinery doesn't leak).  */
   5392 
   5393 static void
   5394 test_type_mismatch_range_labels ()
   5395 {
   5396   /* Create a tempfile and write some text to it.
   5397      ....................0000000001 11111111 12 22222222
   5398      ....................1234567890 12345678 90 12345678.  */
   5399   const char *content = "  printf (\"msg: %i\\n\", msg);\n";
   5400   temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
   5401   line_table_test ltt;
   5402 
   5403   linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
   5404 
   5405   location_t c17 = linemap_position_for_column (line_table, 17);
   5406   ASSERT_EQ (LOCATION_COLUMN (c17), 17);
   5407   location_t c18 = linemap_position_for_column (line_table, 18);
   5408   location_t c24 = linemap_position_for_column (line_table, 24);
   5409   location_t c26 = linemap_position_for_column (line_table, 26);
   5410 
   5411   /* Don't attempt to run the tests if column data might be unavailable.  */
   5412   if (c26 > LINE_MAP_MAX_LOCATION_WITH_COLS)
   5413     return;
   5414 
   5415   location_t fmt = make_location (c18, c17, c18);
   5416   ASSERT_EQ (LOCATION_COLUMN (fmt), 18);
   5417 
   5418   location_t param = make_location (c24, c24, c26);
   5419   ASSERT_EQ (LOCATION_COLUMN (param), 24);
   5420 
   5421   range_label_for_format_type_mismatch fmt_label (char_type_node,
   5422 						  integer_type_node, 1);
   5423   range_label_for_type_mismatch param_label (integer_type_node,
   5424 					     char_type_node);
   5425   gcc_rich_location richloc (fmt, &fmt_label);
   5426   richloc.add_range (param, SHOW_RANGE_WITHOUT_CARET, &param_label);
   5427 
   5428   test_diagnostic_context dc;
   5429   diagnostic_show_locus (&dc, &richloc, DK_ERROR);
   5430   if (c_dialect_cxx ())
   5431     /* "char*", without a space.  */
   5432     ASSERT_STREQ ("   printf (\"msg: %i\\n\", msg);\n"
   5433 		  "                 ~^     ~~~\n"
   5434 		  "                  |     |\n"
   5435 		  "                  char* int\n",
   5436 		  pp_formatted_text (dc.printer));
   5437   else
   5438     /* "char *", with a space.  */
   5439     ASSERT_STREQ ("   printf (\"msg: %i\\n\", msg);\n"
   5440 		  "                 ~^     ~~~\n"
   5441 		  "                  |     |\n"
   5442 		  "                  |     int\n"
   5443 		  "                  char *\n",
   5444 		  pp_formatted_text (dc.printer));
   5445 }
   5446 
   5447 /* Run all of the selftests within this file.  */
   5448 
   5449 void
   5450 c_format_cc_tests ()
   5451 {
   5452   test_get_modifier_for_format_len ();
   5453   test_get_format_for_type_printf ();
   5454   test_get_format_for_type_scanf ();
   5455   test_type_mismatch_range_labels ();
   5456 }
   5457 
   5458 } // namespace selftest
   5459 
   5460 #endif /* CHECKING_P */
   5461 
   5462 #include "gt-c-family-c-format.h"
   5463