GCC47: Add local modifications
[dragonfly.git] / contrib / gcc-4.1 / gcc / c-format.c
1 /* Check calls to formatted I/O functions (-Wformat).
2    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3    2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING.  If not, write to the Free
19 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301, USA.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "tree.h"
27 #include "flags.h"
28 #include "c-common.h"
29 #include "toplev.h"
30 #include "intl.h"
31 #include "diagnostic.h"
32 #include "langhooks.h"
33 #include "c-format.h"
34 \f
35 /* Set format warning options according to a -Wformat=n option.  */
36
37 void
38 set_Wformat (int setting)
39 {
40   warn_format = setting;
41   warn_format_extra_args = setting;
42   warn_format_zero_length = setting;
43   if (setting != 1)
44     {
45       warn_format_nonliteral = setting;
46       warn_format_security = setting;
47       warn_format_y2k = setting;
48     }
49   /* Make sure not to disable -Wnonnull if -Wformat=0 is specified.  */
50   if (setting)
51     warn_nonnull = setting;
52 }
53
54 \f
55 /* Handle attributes associated with format checking.  */
56
57 /* This must be in the same order as format_types, except for
58    format_type_error.  Target-specific format types do not have
59    matching enum values.  */
60 enum format_type { printf_format_type, asm_fprintf_format_type,
61                    gcc_diag_format_type, gcc_tdiag_format_type,
62                    gcc_cdiag_format_type,
63                    gcc_cxxdiag_format_type, gcc_gfc_format_type,
64                    scanf_format_type, strftime_format_type,
65                    strfmon_format_type, format_type_error = -1};
66
67 typedef struct function_format_info
68 {
69   int format_type;                      /* type of format (printf, scanf, etc.) */
70   unsigned HOST_WIDE_INT format_num;    /* number of format argument */
71   unsigned HOST_WIDE_INT first_arg_num; /* number of first arg (zero for varargs) */
72 } function_format_info;
73
74 static bool decode_format_attr (tree, function_format_info *, int);
75 static int decode_format_type (const char *);
76
77 static bool check_format_string (tree argument,
78                                  unsigned HOST_WIDE_INT format_num,
79                                  int flags, bool *no_add_attrs);
80 static bool get_constant (tree expr, unsigned HOST_WIDE_INT *value,
81                           int validated_p);
82
83
84 /* Handle a "format_arg" attribute; arguments as in
85    struct attribute_spec.handler.  */
86 tree
87 handle_format_arg_attribute (tree *node, tree ARG_UNUSED (name),
88                              tree args, int flags, bool *no_add_attrs)
89 {
90   tree type = *node;
91   tree format_num_expr = TREE_VALUE (args);
92   unsigned HOST_WIDE_INT format_num = 0;
93   tree argument;
94
95   if (!get_constant (format_num_expr, &format_num, 0))
96     {
97       error ("format string has invalid operand number");
98       *no_add_attrs = true;
99       return NULL_TREE;
100     }
101
102   argument = TYPE_ARG_TYPES (type);
103   if (argument)
104     {
105       if (!check_format_string (argument, format_num, flags, no_add_attrs))
106         return NULL_TREE;
107     }
108
109   if (TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
110       || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
111           != char_type_node))
112     {
113       if (!(flags & (int) ATTR_FLAG_BUILT_IN))
114         error ("function does not return string type");
115       *no_add_attrs = true;
116       return NULL_TREE;
117     }
118
119   return NULL_TREE;
120 }
121
122 /* Verify that the format_num argument is actually a string, in case
123    the format attribute is in error.  */
124 static bool
125 check_format_string (tree argument, unsigned HOST_WIDE_INT format_num,
126                      int flags, bool *no_add_attrs)
127 {
128   unsigned HOST_WIDE_INT i;
129
130   for (i = 1; i != format_num; i++)
131     {
132       if (argument == 0)
133         break;
134       argument = TREE_CHAIN (argument);
135     }
136
137   if (!argument
138       || TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE
139       || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (argument)))
140           != char_type_node))
141     {
142       if (!(flags & (int) ATTR_FLAG_BUILT_IN))
143         error ("format string argument not a string type");
144       *no_add_attrs = true;
145       return false;
146     }
147
148   return true;
149 }
150
151 /* Verify EXPR is a constant, and store its value.
152    If validated_p is true there should be no errors.
153    Returns true on success, false otherwise.  */
154 static bool
155 get_constant (tree expr, unsigned HOST_WIDE_INT *value, int validated_p)
156 {
157   if (TREE_CODE (expr) != INTEGER_CST || TREE_INT_CST_HIGH (expr) != 0)
158     {
159       gcc_assert (!validated_p);
160       return false;
161     }
162
163   *value = TREE_INT_CST_LOW (expr);
164
165   return true;
166 }
167
168 /* Decode the arguments to a "format" attribute into a
169    function_format_info structure.  It is already known that the list
170    is of the right length.  If VALIDATED_P is true, then these
171    attributes have already been validated and must not be erroneous;
172    if false, it will give an error message.  Returns true if the
173    attributes are successfully decoded, false otherwise.  */
174
175 static bool
176 decode_format_attr (tree args, function_format_info *info, int validated_p)
177 {
178   tree format_type_id = TREE_VALUE (args);
179   tree format_num_expr = TREE_VALUE (TREE_CHAIN (args));
180   tree first_arg_num_expr
181     = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
182
183   if (TREE_CODE (format_type_id) != IDENTIFIER_NODE)
184     {
185       gcc_assert (!validated_p);
186       error ("unrecognized format specifier");
187       return false;
188     }
189   else
190     {
191       const char *p = IDENTIFIER_POINTER (format_type_id);
192
193       info->format_type = decode_format_type (p);
194
195       if (info->format_type == format_type_error)
196         {
197           gcc_assert (!validated_p);
198           warning (OPT_Wformat, "%qE is an unrecognized format function type",
199                    format_type_id);
200           return false;
201         }
202     }
203
204   if (!get_constant (format_num_expr, &info->format_num, validated_p))
205     {
206       error ("format string has invalid operand number");
207       return false;
208     }
209
210   if (!get_constant (first_arg_num_expr, &info->first_arg_num, validated_p))
211     {
212       error ("%<...%> has invalid operand number");
213       return false;
214     }
215
216   if (info->first_arg_num != 0 && info->first_arg_num <= info->format_num)
217     {
218       gcc_assert (!validated_p);
219       error ("format string argument follows the args to be formatted");
220       return false;
221     }
222
223   return true;
224 }
225 \f
226 /* Check a call to a format function against a parameter list.  */
227
228 /* The C standard version C++ is treated as equivalent to
229    or inheriting from, for the purpose of format features supported.  */
230 #define CPLUSPLUS_STD_VER       STD_C94
231 /* The C standard version we are checking formats against when pedantic.  */
232 #define C_STD_VER               ((int) (c_dialect_cxx ()                   \
233                                  ? CPLUSPLUS_STD_VER                       \
234                                  : (flag_isoc99                            \
235                                     ? STD_C99                              \
236                                     : (flag_isoc94 ? STD_C94 : STD_C89))))
237 /* The name to give to the standard version we are warning about when
238    pedantic.  FEATURE_VER is the version in which the feature warned out
239    appeared, which is higher than C_STD_VER.  */
240 #define C_STD_NAME(FEATURE_VER) (c_dialect_cxx ()               \
241                                  ? "ISO C++"                    \
242                                  : ((FEATURE_VER) == STD_EXT    \
243                                     ? "ISO C"                   \
244                                     : "ISO C90"))
245 /* Adjust a C standard version, which may be STD_C9L, to account for
246    -Wno-long-long.  Returns other standard versions unchanged.  */
247 #define ADJ_STD(VER)            ((int) ((VER) == STD_C9L                      \
248                                        ? (warn_long_long ? STD_C99 : STD_C89) \
249                                        : (VER)))
250
251 /* Structure describing details of a type expected in format checking,
252    and the type to check against it.  */
253 typedef struct format_wanted_type
254 {
255   /* The type wanted.  */
256   tree wanted_type;
257   /* The name of this type to use in diagnostics.  */
258   const char *wanted_type_name;
259   /* The level of indirection through pointers at which this type occurs.  */
260   int pointer_count;
261   /* Whether, when pointer_count is 1, to allow any character type when
262      pedantic, rather than just the character or void type specified.  */
263   int char_lenient_flag;
264   /* Whether the argument, dereferenced once, is written into and so the
265      argument must not be a pointer to a const-qualified type.  */
266   int writing_in_flag;
267   /* Whether the argument, dereferenced once, is read from and so
268      must not be a NULL pointer.  */
269   int reading_from_flag;
270   /* If warnings should be of the form "field precision should have
271      type 'int'", the name to use (in this case "field precision"),
272      otherwise NULL, for "format expects type 'long'" type
273      messages.  */
274   const char *name;
275   /* The actual parameter to check against the wanted type.  */
276   tree param;
277   /* The argument number of that parameter.  */
278   int arg_num;
279   /* The next type to check for this format conversion, or NULL if none.  */
280   struct format_wanted_type *next;
281 } format_wanted_type;
282
283
284 static const format_length_info printf_length_specs[] =
285 {
286   { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99 },
287   { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L },
288   { "q", FMT_LEN_ll, STD_EXT, NULL, 0, 0 },
289   { "L", FMT_LEN_L, STD_C89, NULL, 0, 0 },
290   { "z", FMT_LEN_z, STD_C99, NULL, 0, 0 },
291   { "Z", FMT_LEN_z, STD_EXT, NULL, 0, 0 },
292   { "t", FMT_LEN_t, STD_C99, NULL, 0, 0 },
293   { "j", FMT_LEN_j, STD_C99, NULL, 0, 0 },
294   { NULL, 0, 0, NULL, 0, 0 }
295 };
296
297 /* Length specifiers valid for asm_fprintf.  */
298 static const format_length_info asm_fprintf_length_specs[] =
299 {
300   { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89 },
301   { "w", FMT_LEN_none, STD_C89, NULL, 0, 0 },
302   { NULL, 0, 0, NULL, 0, 0 }
303 };
304
305 /* Length specifiers valid for GCC diagnostics.  */
306 static const format_length_info gcc_diag_length_specs[] =
307 {
308   { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89 },
309   { "w", FMT_LEN_none, STD_C89, NULL, 0, 0 },
310   { NULL, 0, 0, NULL, 0, 0 }
311 };
312
313 /* The custom diagnostics all accept the same length specifiers.  */
314 #define gcc_tdiag_length_specs gcc_diag_length_specs
315 #define gcc_cdiag_length_specs gcc_diag_length_specs
316 #define gcc_cxxdiag_length_specs gcc_diag_length_specs
317
318 /* This differs from printf_length_specs only in that "Z" is not accepted.  */
319 static const format_length_info scanf_length_specs[] =
320 {
321   { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99 },
322   { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L },
323   { "q", FMT_LEN_ll, STD_EXT, NULL, 0, 0 },
324   { "L", FMT_LEN_L, STD_C89, NULL, 0, 0 },
325   { "z", FMT_LEN_z, STD_C99, NULL, 0, 0 },
326   { "t", FMT_LEN_t, STD_C99, NULL, 0, 0 },
327   { "j", FMT_LEN_j, STD_C99, NULL, 0, 0 },
328   { NULL, 0, 0, NULL, 0, 0 }
329 };
330
331
332 /* All tables for strfmon use STD_C89 everywhere, since -pedantic warnings
333    make no sense for a format type not part of any C standard version.  */
334 static const format_length_info strfmon_length_specs[] =
335 {
336   /* A GNU extension.  */
337   { "L", FMT_LEN_L, STD_C89, NULL, 0, 0 },
338   { NULL, 0, 0, NULL, 0, 0 }
339 };
340
341 static const format_flag_spec printf_flag_specs[] =
342 {
343   { ' ',  0, 0, N_("' ' flag"),        N_("the ' ' printf flag"),              STD_C89 },
344   { '+',  0, 0, N_("'+' flag"),        N_("the '+' printf flag"),              STD_C89 },
345   { '#',  0, 0, N_("'#' flag"),        N_("the '#' printf flag"),              STD_C89 },
346   { '0',  0, 0, N_("'0' flag"),        N_("the '0' printf flag"),              STD_C89 },
347   { '-',  0, 0, N_("'-' flag"),        N_("the '-' printf flag"),              STD_C89 },
348   { '\'', 0, 0, N_("''' flag"),        N_("the ''' printf flag"),              STD_EXT },
349   { 'I',  0, 0, N_("'I' flag"),        N_("the 'I' printf flag"),              STD_EXT },
350   { 'w',  0, 0, N_("field width"),     N_("field width in printf format"),     STD_C89 },
351   { 'p',  0, 0, N_("precision"),       N_("precision in printf format"),       STD_C89 },
352   { 'L',  0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
353   { 0, 0, 0, NULL, NULL, 0 }
354 };
355
356
357 static const format_flag_pair printf_flag_pairs[] =
358 {
359   { ' ', '+', 1, 0   },
360   { '0', '-', 1, 0   },
361   { '0', 'p', 1, 'i' },
362   { 0, 0, 0, 0 }
363 };
364
365 static const format_flag_spec asm_fprintf_flag_specs[] =
366 {
367   { ' ',  0, 0, N_("' ' flag"),        N_("the ' ' printf flag"),              STD_C89 },
368   { '+',  0, 0, N_("'+' flag"),        N_("the '+' printf flag"),              STD_C89 },
369   { '#',  0, 0, N_("'#' flag"),        N_("the '#' printf flag"),              STD_C89 },
370   { '0',  0, 0, N_("'0' flag"),        N_("the '0' printf flag"),              STD_C89 },
371   { '-',  0, 0, N_("'-' flag"),        N_("the '-' printf flag"),              STD_C89 },
372   { 'w',  0, 0, N_("field width"),     N_("field width in printf format"),     STD_C89 },
373   { 'p',  0, 0, N_("precision"),       N_("precision in printf format"),       STD_C89 },
374   { 'L',  0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
375   { 0, 0, 0, NULL, NULL, 0 }
376 };
377
378 static const format_flag_pair asm_fprintf_flag_pairs[] =
379 {
380   { ' ', '+', 1, 0   },
381   { '0', '-', 1, 0   },
382   { '0', 'p', 1, 'i' },
383   { 0, 0, 0, 0 }
384 };
385
386 static const format_flag_pair gcc_diag_flag_pairs[] =
387 {
388   { 0, 0, 0, 0 }
389 };
390
391 #define gcc_tdiag_flag_pairs gcc_diag_flag_pairs
392 #define gcc_cdiag_flag_pairs gcc_diag_flag_pairs
393 #define gcc_cxxdiag_flag_pairs gcc_diag_flag_pairs
394
395 static const format_flag_pair gcc_gfc_flag_pairs[] =
396 {
397   { 0, 0, 0, 0 }
398 };
399
400 static const format_flag_spec gcc_diag_flag_specs[] =
401 {
402   { '+',  0, 0, N_("'+' flag"),        N_("the '+' printf flag"),              STD_C89 },
403   { 'q',  0, 0, N_("'q' flag"),        N_("the 'q' diagnostic flag"),          STD_C89 },
404   { 'p',  0, 0, N_("precision"),       N_("precision in printf format"),       STD_C89 },
405   { 'L',  0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
406   { 0, 0, 0, NULL, NULL, 0 }
407 };
408
409 #define gcc_tdiag_flag_specs gcc_diag_flag_specs
410 #define gcc_cdiag_flag_specs gcc_diag_flag_specs
411
412 static const format_flag_spec gcc_cxxdiag_flag_specs[] =
413 {
414   { '+',  0, 0, N_("'+' flag"),        N_("the '+' printf flag"),              STD_C89 },
415   { '#',  0, 0, N_("'#' flag"),        N_("the '#' printf flag"),              STD_C89 },
416   { 'q',  0, 0, N_("'q' flag"),        N_("the 'q' diagnostic flag"),          STD_C89 },
417   { 'p',  0, 0, N_("precision"),       N_("precision in printf format"),       STD_C89 },
418   { 'L',  0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
419   { 0, 0, 0, NULL, NULL, 0 }
420 };
421
422 static const format_flag_spec scanf_flag_specs[] =
423 {
424   { '*',  0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89 },
425   { 'a',  0, 0, N_("'a' flag"),               N_("the 'a' scanf flag"),                       STD_EXT },
426   { 'w',  0, 0, N_("field width"),            N_("field width in scanf format"),              STD_C89 },
427   { 'L',  0, 0, N_("length modifier"),        N_("length modifier in scanf format"),          STD_C89 },
428   { '\'', 0, 0, N_("''' flag"),               N_("the ''' scanf flag"),                       STD_EXT },
429   { 'I',  0, 0, N_("'I' flag"),               N_("the 'I' scanf flag"),                       STD_EXT },
430   { 0, 0, 0, NULL, NULL, 0 }
431 };
432
433
434 static const format_flag_pair scanf_flag_pairs[] =
435 {
436   { '*', 'L', 0, 0 },
437   { 0, 0, 0, 0 }
438 };
439
440
441 static const format_flag_spec strftime_flag_specs[] =
442 {
443   { '_', 0,   0, N_("'_' flag"),     N_("the '_' strftime flag"),          STD_EXT },
444   { '-', 0,   0, N_("'-' flag"),     N_("the '-' strftime flag"),          STD_EXT },
445   { '0', 0,   0, N_("'0' flag"),     N_("the '0' strftime flag"),          STD_EXT },
446   { '^', 0,   0, N_("'^' flag"),     N_("the '^' strftime flag"),          STD_EXT },
447   { '#', 0,   0, N_("'#' flag"),     N_("the '#' strftime flag"),          STD_EXT },
448   { 'w', 0,   0, N_("field width"),  N_("field width in strftime format"), STD_EXT },
449   { 'E', 0,   0, N_("'E' modifier"), N_("the 'E' strftime modifier"),      STD_C99 },
450   { 'O', 0,   0, N_("'O' modifier"), N_("the 'O' strftime modifier"),      STD_C99 },
451   { 'O', 'o', 0, NULL,               N_("the 'O' modifier"),               STD_EXT },
452   { 0, 0, 0, NULL, NULL, 0 }
453 };
454
455
456 static const format_flag_pair strftime_flag_pairs[] =
457 {
458   { 'E', 'O', 0, 0 },
459   { '_', '-', 0, 0 },
460   { '_', '0', 0, 0 },
461   { '-', '0', 0, 0 },
462   { '^', '#', 0, 0 },
463   { 0, 0, 0, 0 }
464 };
465
466
467 static const format_flag_spec strfmon_flag_specs[] =
468 {
469   { '=',  0, 1, N_("fill character"),  N_("fill character in strfmon format"),  STD_C89 },
470   { '^',  0, 0, N_("'^' flag"),        N_("the '^' strfmon flag"),              STD_C89 },
471   { '+',  0, 0, N_("'+' flag"),        N_("the '+' strfmon flag"),              STD_C89 },
472   { '(',  0, 0, N_("'(' flag"),        N_("the '(' strfmon flag"),              STD_C89 },
473   { '!',  0, 0, N_("'!' flag"),        N_("the '!' strfmon flag"),              STD_C89 },
474   { '-',  0, 0, N_("'-' flag"),        N_("the '-' strfmon flag"),              STD_C89 },
475   { 'w',  0, 0, N_("field width"),     N_("field width in strfmon format"),     STD_C89 },
476   { '#',  0, 0, N_("left precision"),  N_("left precision in strfmon format"),  STD_C89 },
477   { 'p',  0, 0, N_("right precision"), N_("right precision in strfmon format"), STD_C89 },
478   { 'L',  0, 0, N_("length modifier"), N_("length modifier in strfmon format"), STD_C89 },
479   { 0, 0, 0, NULL, NULL, 0 }
480 };
481
482 static const format_flag_pair strfmon_flag_pairs[] =
483 {
484   { '+', '(', 0, 0 },
485   { 0, 0, 0, 0 }
486 };
487
488 static const format_char_info dfly_ext_char_info =
489 { NULL,   1, STD_EXT, { T89_C,  BADLEN,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "",   "cR", NULL };
490
491 static const format_char_info print_char_table[] =
492 {
493   /* C89 conversion specifiers.  */
494   { "di",  0, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  TEX_LL,  T99_SST, T99_PD,  T99_IM  }, "-wp0 +'I",  "i",  NULL },
495   { "oxX", 0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "-wp0#",     "i",  NULL },
496   { "u",   0, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "-wp0'I",    "i",  NULL },
497   { "fgG", 0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#'I", "",   NULL },
498   { "eE",  0, STD_C89, { T89_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#I",  "",   NULL },
499   { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T94_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w",        "",   NULL },
500   { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",       "cR", NULL },
501   { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w",        "c",  NULL },
502   { "n",   1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  T99_IM  }, "",          "W",  NULL },
503   /* C99 conversion specifiers.  */
504   { "F",   0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#'I", "",   NULL },
505   { "aA",  0, STD_C99, { T99_D,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#",   "",   NULL },
506   /* X/Open conversion specifiers.  */
507   { "C",   0, STD_EXT, { TEX_WI,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w",        "",   NULL },
508   { "S",   1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",       "R",  NULL },
509   /* GNU conversion specifiers.  */
510   { "m",   0, STD_EXT, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",       "",   NULL },
511   /* BSD conversion specifiers.  */
512   /* DragonFly kernel extensions (src/sys/kern/subr_prf.c).
513      The format %b is supported to decode error registers.
514      Its usage is:      printf("reg=%b\n", regval, "<base><arg>*");
515      which produces:    reg=3<BITTWO,BITONE>
516      The format %D provides a hexdump given a pointer and separator string:
517      ("%6D", ptr, ":")          -> XX:XX:XX:XX:XX:XX
518      ("%*D", len, ptr, " ")     -> XX XX XX XX ...
519    */
520   { "D",   1, STD_EXT, { T89_V,  BADLEN,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",      "cR",   &dfly_ext_char_info },
521   { "b",   0, STD_EXT, { T89_I,  BADLEN,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",      "",     &dfly_ext_char_info },
522   { "ry",  0, STD_EXT, { T89_I,  BADLEN,   BADLEN,   T89_L,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +#",  "i",    NULL  },
523   { NULL,  0, 0, NOLENGTHS, NULL, NULL, NULL }
524 };
525
526 static const format_char_info asm_fprintf_char_table[] =
527 {
528   /* C89 conversion specifiers.  */
529   { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0 +",  "i", NULL },
530   { "oxX", 0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0#",   "i", NULL },
531   { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp0",    "i", NULL },
532   { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-w",       "", NULL },
533   { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "-wp",    "cR", NULL },
534
535   /* asm_fprintf conversion specifiers.  */
536   { "O",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
537   { "R",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
538   { "I",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
539   { "L",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
540   { "U",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
541   { "r",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "",  "", NULL },
542   { "@",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
543   { NULL,  0, 0, NOLENGTHS, NULL, NULL, NULL }
544 };
545
546 static const format_char_info gcc_diag_char_table[] =
547 {
548   /* C89 conversion specifiers.  */
549   { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
550   { "ox",  0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
551   { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
552   { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
553   { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "pq", "cR", NULL },
554   { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "c",  NULL },
555
556   /* Custom conversion specifiers.  */
557
558   /* %H will require "location_t" at runtime.  */
559   { "H",   0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
560
561   /* These will require a "tree" at runtime.  */
562   { "J", 0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",    "",   NULL },
563
564   { "<>'", 0, STD_C89, NOARGUMENTS, "",      "",   NULL },
565   { "m",   0, STD_C89, NOARGUMENTS, "q",     "",   NULL },
566   { NULL,  0, 0, NOLENGTHS, NULL, NULL, NULL }
567 };
568
569 static const format_char_info gcc_tdiag_char_table[] =
570 {
571   /* C89 conversion specifiers.  */
572   { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
573   { "ox",  0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
574   { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
575   { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
576   { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "pq", "cR", NULL },
577   { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "c",  NULL },
578
579   /* Custom conversion specifiers.  */
580
581   /* %H will require "location_t" at runtime.  */
582   { "H",   0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
583
584   /* These will require a "tree" at runtime.  */
585   { "DFJT", 0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+", "",   NULL },
586
587   { "<>'", 0, STD_C89, NOARGUMENTS, "",      "",   NULL },
588   { "m",   0, STD_C89, NOARGUMENTS, "q",     "",   NULL },
589   { NULL,  0, 0, NOLENGTHS, NULL, NULL, NULL }
590 };
591
592 static const format_char_info gcc_cdiag_char_table[] =
593 {
594   /* C89 conversion specifiers.  */
595   { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
596   { "ox",  0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
597   { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
598   { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
599   { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "pq", "cR", NULL },
600   { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "c",  NULL },
601
602   /* Custom conversion specifiers.  */
603
604   /* %H will require "location_t" at runtime.  */
605   { "H",   0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
606
607   /* These will require a "tree" at runtime.  */
608   { "DEFJT", 0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+", "",   NULL },
609
610   { "<>'", 0, STD_C89, NOARGUMENTS, "",      "",   NULL },
611   { "m",   0, STD_C89, NOARGUMENTS, "q",     "",   NULL },
612   { NULL,  0, 0, NOLENGTHS, NULL, NULL, NULL }
613 };
614
615 static const format_char_info gcc_cxxdiag_char_table[] =
616 {
617   /* C89 conversion specifiers.  */
618   { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  T89_L,   T9L_LL,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
619   { "ox",  0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
620   { "u",   0, STD_C89, { T89_UI,  BADLEN,  BADLEN,  T89_UL,  T9L_ULL, BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
621   { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
622   { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "pq", "cR", NULL },
623   { "p",   1, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "c",  NULL },
624
625   /* Custom conversion specifiers.  */
626
627   /* %H will require "location_t" at runtime.  */
628   { "H",   0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
629
630   /* These will require a "tree" at runtime.  */
631   { "ADEFJTV",0,STD_C89,{ T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q+#",   "",   NULL },
632
633   /* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.)  */
634   { "CLOPQ",0,STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "q",  "",   NULL },
635
636   { "<>'", 0, STD_C89, NOARGUMENTS, "",      "",   NULL },
637   { "m",   0, STD_C89, NOARGUMENTS, "q",     "",   NULL },
638   { NULL,  0, 0, NOLENGTHS, NULL, NULL, NULL }
639 };
640
641 static const format_char_info gcc_gfc_char_table[] =
642 {
643   /* C89 conversion specifiers.  */
644   { "di",  0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "", "", NULL },
645   { "c",   0, STD_C89, { T89_I,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "", "", NULL },
646   { "s",   1, STD_C89, { T89_C,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "", "cR", NULL },
647
648   /* gfc conversion specifiers.  */
649
650   { "C",   0, STD_C89, NOARGUMENTS, "",      "",   NULL },
651
652   /* This will require a "locus" at runtime.  */
653   { "L",   0, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "", "R", NULL },
654
655   { NULL,  0, 0, NOLENGTHS, NULL, NULL, NULL }
656 };
657
658 static const format_char_info scan_char_table[] =
659 {
660   /* C89 conversion specifiers.  */
661   { "di",    1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  TEX_LL,  T99_SST, T99_PD,  T99_IM  }, "*w'I", "W",   NULL },
662   { "u",     1, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "*w'I", "W",   NULL },
663   { "oxX",   1, STD_C89, { T89_UI,  T99_UC,  T89_US,  T89_UL,  T9L_ULL, TEX_ULL, T99_ST,  T99_UPD, T99_UIM }, "*w",   "W",   NULL },
664   { "efgEG", 1, STD_C89, { T89_F,   BADLEN,  BADLEN,  T89_D,   BADLEN,  T89_LD,  BADLEN,  BADLEN,  BADLEN  }, "*w'",  "W",   NULL },
665   { "c",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*w",   "cW",  NULL },
666   { "s",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*aw",  "cW",  NULL },
667   { "[",     1, STD_C89, { T89_C,   BADLEN,  BADLEN,  T94_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*aw",  "cW[", NULL },
668   { "p",     2, STD_C89, { T89_V,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*w",   "W",   NULL },
669   { "n",     1, STD_C89, { T89_I,   T99_SC,  T89_S,   T89_L,   T9L_LL,  BADLEN,  T99_SST, T99_PD,  T99_IM  }, "",     "W",   NULL },
670   /* C99 conversion specifiers.  */
671   { "FaA",   1, STD_C99, { T99_F,   BADLEN,  BADLEN,  T99_D,   BADLEN,  T99_LD,  BADLEN,  BADLEN,  BADLEN  }, "*w'",  "W",   NULL },
672   /* X/Open conversion specifiers.  */
673   { "C",     1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*w",   "W",   NULL },
674   { "S",     1, STD_EXT, { TEX_W,   BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN,  BADLEN  }, "*aw",  "W",   NULL },
675   { NULL, 0, 0, NOLENGTHS, NULL, NULL, NULL }
676 };
677
678 static const format_char_info time_char_table[] =
679 {
680   /* C89 conversion specifiers.  */
681   { "ABZab",            0, STD_C89, NOLENGTHS, "^#",     "",   NULL },
682   { "cx",               0, STD_C89, NOLENGTHS, "E",      "3",  NULL },
683   { "HIMSUWdmw",        0, STD_C89, NOLENGTHS, "-_0Ow",  "",   NULL },
684   { "j",                0, STD_C89, NOLENGTHS, "-_0Ow",  "o",  NULL },
685   { "p",                0, STD_C89, NOLENGTHS, "#",      "",   NULL },
686   { "X",                0, STD_C89, NOLENGTHS, "E",      "",   NULL },
687   { "y",                0, STD_C89, NOLENGTHS, "EO-_0w", "4",  NULL },
688   { "Y",                0, STD_C89, NOLENGTHS, "-_0EOw", "o",  NULL },
689   { "%",                0, STD_C89, NOLENGTHS, "",       "",   NULL },
690   /* C99 conversion specifiers.  */
691   { "C",                0, STD_C99, NOLENGTHS, "-_0EOw", "o",  NULL },
692   { "D",                0, STD_C99, NOLENGTHS, "",       "2",  NULL },
693   { "eVu",              0, STD_C99, NOLENGTHS, "-_0Ow",  "",   NULL },
694   { "FRTnrt",           0, STD_C99, NOLENGTHS, "",       "",   NULL },
695   { "g",                0, STD_C99, NOLENGTHS, "O-_0w",  "2o", NULL },
696   { "G",                0, STD_C99, NOLENGTHS, "-_0Ow",  "o",  NULL },
697   { "h",                0, STD_C99, NOLENGTHS, "^#",     "",   NULL },
698   { "z",                0, STD_C99, NOLENGTHS, "O",      "o",  NULL },
699   /* GNU conversion specifiers.  */
700   { "kls",              0, STD_EXT, NOLENGTHS, "-_0Ow",  "",   NULL },
701   { "P",                0, STD_EXT, NOLENGTHS, "",       "",   NULL },
702   { NULL,               0, 0, NOLENGTHS, NULL, NULL, NULL }
703 };
704
705 static const format_char_info monetary_char_table[] =
706 {
707   { "in", 0, STD_C89, { T89_D, BADLEN, BADLEN, BADLEN, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN }, "=^+(!-w#p", "", NULL },
708   { NULL, 0, 0, NOLENGTHS, NULL, NULL, NULL }
709 };
710
711 /* This must be in the same order as enum format_type.  */
712 static const format_kind_info format_types_orig[] =
713 {
714   { "printf",   printf_length_specs,  print_char_table, " +#0-'I", NULL, 
715     printf_flag_specs, printf_flag_pairs,
716     FMT_FLAG_ARG_CONVERT|FMT_FLAG_DOLLAR_MULTIPLE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_EMPTY_PREC_OK,
717     'w', 0, 'p', 0, 'L',
718     &integer_type_node, &integer_type_node
719   },
720   { "asm_fprintf",   asm_fprintf_length_specs,  asm_fprintf_char_table, " +#0-", NULL, 
721     asm_fprintf_flag_specs, asm_fprintf_flag_pairs,
722     FMT_FLAG_ARG_CONVERT|FMT_FLAG_EMPTY_PREC_OK,
723     'w', 0, 'p', 0, 'L',
724     NULL, NULL
725   },
726   { "gcc_diag",   gcc_diag_length_specs,  gcc_diag_char_table, "q+", NULL, 
727     gcc_diag_flag_specs, gcc_diag_flag_pairs,
728     FMT_FLAG_ARG_CONVERT,
729     0, 0, 'p', 0, 'L',
730     NULL, &integer_type_node
731   },
732   { "gcc_tdiag",   gcc_tdiag_length_specs,  gcc_tdiag_char_table, "q+", NULL, 
733     gcc_tdiag_flag_specs, gcc_tdiag_flag_pairs,
734     FMT_FLAG_ARG_CONVERT,
735     0, 0, 'p', 0, 'L',
736     NULL, &integer_type_node
737   },
738   { "gcc_cdiag",   gcc_cdiag_length_specs,  gcc_cdiag_char_table, "q+", NULL, 
739     gcc_cdiag_flag_specs, gcc_cdiag_flag_pairs,
740     FMT_FLAG_ARG_CONVERT,
741     0, 0, 'p', 0, 'L',
742     NULL, &integer_type_node
743   },
744   { "gcc_cxxdiag",   gcc_cxxdiag_length_specs,  gcc_cxxdiag_char_table, "q+#", NULL, 
745     gcc_cxxdiag_flag_specs, gcc_cxxdiag_flag_pairs,
746     FMT_FLAG_ARG_CONVERT,
747     0, 0, 'p', 0, 'L',
748     NULL, &integer_type_node
749   },
750   { "gcc_gfc", NULL, gcc_gfc_char_table, "", NULL, 
751     NULL, gcc_gfc_flag_pairs,
752     FMT_FLAG_ARG_CONVERT,
753     0, 0, 0, 0, 0,
754     NULL, NULL
755   },
756   { "scanf",    scanf_length_specs,   scan_char_table,  "*'I", NULL, 
757     scanf_flag_specs, scanf_flag_pairs,
758     FMT_FLAG_ARG_CONVERT|FMT_FLAG_SCANF_A_KLUDGE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_ZERO_WIDTH_BAD|FMT_FLAG_DOLLAR_GAP_POINTER_OK,
759     'w', 0, 0, '*', 'L',
760     NULL, NULL
761   },
762   { "strftime", NULL,                 time_char_table,  "_-0^#", "EO",
763     strftime_flag_specs, strftime_flag_pairs,
764     FMT_FLAG_FANCY_PERCENT_OK, 'w', 0, 0, 0, 0,
765     NULL, NULL
766   },
767   { "strfmon",  strfmon_length_specs, monetary_char_table, "=^+(!-", NULL, 
768     strfmon_flag_specs, strfmon_flag_pairs,
769     FMT_FLAG_ARG_CONVERT, 'w', '#', 'p', 0, 'L',
770     NULL, NULL
771   }
772 };
773
774 /* This layer of indirection allows GCC to reassign format_types with
775    new data if necessary, while still allowing the original data to be
776    const.  */
777 static const format_kind_info *format_types = format_types_orig;
778 /* We can modify this one.  We also add target-specific format types
779    to the end of the array.  */
780 static format_kind_info *dynamic_format_types;
781
782 static int n_format_types = ARRAY_SIZE (format_types_orig);
783
784 /* Structure detailing the results of checking a format function call
785    where the format expression may be a conditional expression with
786    many leaves resulting from nested conditional expressions.  */
787 typedef struct
788 {
789   /* Number of leaves of the format argument that could not be checked
790      as they were not string literals.  */
791   int number_non_literal;
792   /* Number of leaves of the format argument that were null pointers or
793      string literals, but had extra format arguments.  */
794   int number_extra_args;
795   /* Number of leaves of the format argument that were null pointers or
796      string literals, but had extra format arguments and used $ operand
797      numbers.  */
798   int number_dollar_extra_args;
799   /* Number of leaves of the format argument that were wide string
800      literals.  */
801   int number_wide;
802   /* Number of leaves of the format argument that were empty strings.  */
803   int number_empty;
804   /* Number of leaves of the format argument that were unterminated
805      strings.  */
806   int number_unterminated;
807   /* Number of leaves of the format argument that were not counted above.  */
808   int number_other;
809 } format_check_results;
810
811 typedef struct
812 {
813   format_check_results *res;
814   function_format_info *info;
815   tree params;
816 } format_check_context;
817
818 static void check_format_info (function_format_info *, tree);
819 static void check_format_arg (void *, tree, unsigned HOST_WIDE_INT);
820 static void check_format_info_main (format_check_results *,
821                                     function_format_info *,
822                                     const char *, int, tree,
823                                     unsigned HOST_WIDE_INT);
824
825 static void init_dollar_format_checking (int, tree);
826 static int maybe_read_dollar_number (const char **, int,
827                                      tree, tree *, const format_kind_info *);
828 static bool avoid_dollar_number (const char *);
829 static void finish_dollar_format_checking (format_check_results *, int);
830
831 static const format_flag_spec *get_flag_spec (const format_flag_spec *,
832                                               int, const char *);
833
834 static void check_format_types (format_wanted_type *, const char *, int);
835 static void format_type_warning (const char *, const char *, int, tree,
836                                  int, const char *, tree, int);
837
838 /* Decode a format type from a string, returning the type, or
839    format_type_error if not valid, in which case the caller should print an
840    error message.  */
841 static int
842 decode_format_type (const char *s)
843 {
844   int i;
845   int slen;
846   slen = strlen (s);
847   for (i = 0; i < n_format_types; i++)
848     {
849       int alen;
850       if (!strcmp (s, format_types[i].name))
851         return i;
852       alen = strlen (format_types[i].name);
853       if (slen == alen + 4 && s[0] == '_' && s[1] == '_'
854           && s[slen - 1] == '_' && s[slen - 2] == '_'
855           && !strncmp (s + 2, format_types[i].name, alen))
856         return i;
857     }
858   return format_type_error;
859 }
860
861 \f
862 /* Check the argument list of a call to printf, scanf, etc.
863    ATTRS are the attributes on the function type.
864    PARAMS is the list of argument values.  Also, if -Wmissing-format-attribute,
865    warn for calls to vprintf or vscanf in functions with no such format
866    attribute themselves.  */
867
868 void
869 check_function_format (tree attrs, tree params)
870 {
871   tree a;
872
873   /* See if this function has any format attributes.  */
874   for (a = attrs; a; a = TREE_CHAIN (a))
875     {
876       if (is_attribute_p ("format", TREE_PURPOSE (a)))
877         {
878           /* Yup; check it.  */
879           function_format_info info;
880           decode_format_attr (TREE_VALUE (a), &info, 1);
881           if (warn_format)
882             check_format_info (&info, params);
883           if (warn_missing_format_attribute && info.first_arg_num == 0
884               && (format_types[info.format_type].flags
885                   & (int) FMT_FLAG_ARG_CONVERT))
886             {
887               tree c;
888               for (c = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
889                    c;
890                    c = TREE_CHAIN (c))
891                 if (is_attribute_p ("format", TREE_PURPOSE (c))
892                     && (decode_format_type (IDENTIFIER_POINTER
893                                             (TREE_VALUE (TREE_VALUE (c))))
894                         == info.format_type))
895                   break;
896               if (c == NULL_TREE)
897                 {
898                   /* Check if the current function has a parameter to which
899                      the format attribute could be attached; if not, it
900                      can't be a candidate for a format attribute, despite
901                      the vprintf-like or vscanf-like call.  */
902                   tree args;
903                   for (args = DECL_ARGUMENTS (current_function_decl);
904                        args != 0;
905                        args = TREE_CHAIN (args))
906                     {
907                       if (TREE_CODE (TREE_TYPE (args)) == POINTER_TYPE
908                           && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (args)))
909                               == char_type_node))
910                         break;
911                     }
912                   if (args != 0)
913                     warning (OPT_Wmissing_format_attribute, "function might "
914                              "be possible candidate for %qs format attribute",
915                              format_types[info.format_type].name);
916                 }
917             }
918         }
919     }
920 }
921
922
923 /* Variables used by the checking of $ operand number formats.  */
924 static char *dollar_arguments_used = NULL;
925 static char *dollar_arguments_pointer_p = NULL;
926 static int dollar_arguments_alloc = 0;
927 static int dollar_arguments_count;
928 static int dollar_first_arg_num;
929 static int dollar_max_arg_used;
930 static int dollar_format_warned;
931
932 /* Initialize the checking for a format string that may contain $
933    parameter number specifications; we will need to keep track of whether
934    each parameter has been used.  FIRST_ARG_NUM is the number of the first
935    argument that is a parameter to the format, or 0 for a vprintf-style
936    function; PARAMS is the list of arguments starting at this argument.  */
937
938 static void
939 init_dollar_format_checking (int first_arg_num, tree params)
940 {
941   tree oparams = params;
942
943   dollar_first_arg_num = first_arg_num;
944   dollar_arguments_count = 0;
945   dollar_max_arg_used = 0;
946   dollar_format_warned = 0;
947   if (first_arg_num > 0)
948     {
949       while (params)
950         {
951           dollar_arguments_count++;
952           params = TREE_CHAIN (params);
953         }
954     }
955   if (dollar_arguments_alloc < dollar_arguments_count)
956     {
957       if (dollar_arguments_used)
958         free (dollar_arguments_used);
959       if (dollar_arguments_pointer_p)
960         free (dollar_arguments_pointer_p);
961       dollar_arguments_alloc = dollar_arguments_count;
962       dollar_arguments_used = XNEWVEC (char, dollar_arguments_alloc);
963       dollar_arguments_pointer_p = XNEWVEC (char, dollar_arguments_alloc);
964     }
965   if (dollar_arguments_alloc)
966     {
967       memset (dollar_arguments_used, 0, dollar_arguments_alloc);
968       if (first_arg_num > 0)
969         {
970           int i = 0;
971           params = oparams;
972           while (params)
973             {
974               dollar_arguments_pointer_p[i] = (TREE_CODE (TREE_TYPE (TREE_VALUE (params)))
975                                                == POINTER_TYPE);
976               params = TREE_CHAIN (params);
977               i++;
978             }
979         }
980     }
981 }
982
983
984 /* Look for a decimal number followed by a $ in *FORMAT.  If DOLLAR_NEEDED
985    is set, it is an error if one is not found; otherwise, it is OK.  If
986    such a number is found, check whether it is within range and mark that
987    numbered operand as being used for later checking.  Returns the operand
988    number if found and within range, zero if no such number was found and
989    this is OK, or -1 on error.  PARAMS points to the first operand of the
990    format; PARAM_PTR is made to point to the parameter referred to.  If
991    a $ format is found, *FORMAT is updated to point just after it.  */
992
993 static int
994 maybe_read_dollar_number (const char **format,
995                           int dollar_needed, tree params, tree *param_ptr,
996                           const format_kind_info *fki)
997 {
998   int argnum;
999   int overflow_flag;
1000   const char *fcp = *format;
1001   if (!ISDIGIT (*fcp))
1002     {
1003       if (dollar_needed)
1004         {
1005           warning (OPT_Wformat, "missing $ operand number in format");
1006           return -1;
1007         }
1008       else
1009         return 0;
1010     }
1011   argnum = 0;
1012   overflow_flag = 0;
1013   while (ISDIGIT (*fcp))
1014     {
1015       int nargnum;
1016       nargnum = 10 * argnum + (*fcp - '0');
1017       if (nargnum < 0 || nargnum / 10 != argnum)
1018         overflow_flag = 1;
1019       argnum = nargnum;
1020       fcp++;
1021     }
1022   if (*fcp != '$')
1023     {
1024       if (dollar_needed)
1025         {
1026           warning (OPT_Wformat, "missing $ operand number in format");
1027           return -1;
1028         }
1029       else
1030         return 0;
1031     }
1032   *format = fcp + 1;
1033   if (pedantic && !dollar_format_warned)
1034     {
1035       warning (OPT_Wformat, "%s does not support %%n$ operand number formats",
1036                C_STD_NAME (STD_EXT));
1037       dollar_format_warned = 1;
1038     }
1039   if (overflow_flag || argnum == 0
1040       || (dollar_first_arg_num && argnum > dollar_arguments_count))
1041     {
1042       warning (OPT_Wformat, "operand number out of range in format");
1043       return -1;
1044     }
1045   if (argnum > dollar_max_arg_used)
1046     dollar_max_arg_used = argnum;
1047   /* For vprintf-style functions we may need to allocate more memory to
1048      track which arguments are used.  */
1049   while (dollar_arguments_alloc < dollar_max_arg_used)
1050     {
1051       int nalloc;
1052       nalloc = 2 * dollar_arguments_alloc + 16;
1053       dollar_arguments_used = XRESIZEVEC (char, dollar_arguments_used,
1054                                           nalloc);
1055       dollar_arguments_pointer_p = XRESIZEVEC (char, dollar_arguments_pointer_p,
1056                                                nalloc);
1057       memset (dollar_arguments_used + dollar_arguments_alloc, 0,
1058               nalloc - dollar_arguments_alloc);
1059       dollar_arguments_alloc = nalloc;
1060     }
1061   if (!(fki->flags & (int) FMT_FLAG_DOLLAR_MULTIPLE)
1062       && dollar_arguments_used[argnum - 1] == 1)
1063     {
1064       dollar_arguments_used[argnum - 1] = 2;
1065       warning (OPT_Wformat, "format argument %d used more than once in %s format",
1066                argnum, fki->name);
1067     }
1068   else
1069     dollar_arguments_used[argnum - 1] = 1;
1070   if (dollar_first_arg_num)
1071     {
1072       int i;
1073       *param_ptr = params;
1074       for (i = 1; i < argnum && *param_ptr != 0; i++)
1075         *param_ptr = TREE_CHAIN (*param_ptr);
1076
1077       /* This case shouldn't be caught here.  */
1078       gcc_assert (*param_ptr);
1079     }
1080   else
1081     *param_ptr = 0;
1082   return argnum;
1083 }
1084
1085 /* Ensure that FORMAT does not start with a decimal number followed by
1086    a $; give a diagnostic and return true if it does, false otherwise.  */
1087
1088 static bool
1089 avoid_dollar_number (const char *format)
1090 {
1091   if (!ISDIGIT (*format))
1092     return false;
1093   while (ISDIGIT (*format))
1094     format++;
1095   if (*format == '$')
1096     {
1097       warning (OPT_Wformat, "$ operand number used after format without operand number");
1098       return true;
1099     }
1100   return false;
1101 }
1102
1103
1104 /* Finish the checking for a format string that used $ operand number formats
1105    instead of non-$ formats.  We check for unused operands before used ones
1106    (a serious error, since the implementation of the format function
1107    can't know what types to pass to va_arg to find the later arguments).
1108    and for unused operands at the end of the format (if we know how many
1109    arguments the format had, so not for vprintf).  If there were operand
1110    numbers out of range on a non-vprintf-style format, we won't have reached
1111    here.  If POINTER_GAP_OK, unused arguments are OK if all arguments are
1112    pointers.  */
1113
1114 static void
1115 finish_dollar_format_checking (format_check_results *res, int pointer_gap_ok)
1116 {
1117   int i;
1118   bool found_pointer_gap = false;
1119   for (i = 0; i < dollar_max_arg_used; i++)
1120     {
1121       if (!dollar_arguments_used[i])
1122         {
1123           if (pointer_gap_ok && (dollar_first_arg_num == 0
1124                                  || dollar_arguments_pointer_p[i]))
1125             found_pointer_gap = true;
1126           else
1127             warning (OPT_Wformat,
1128                      "format argument %d unused before used argument %d in $-style format",
1129                      i + 1, dollar_max_arg_used);
1130         }
1131     }
1132   if (found_pointer_gap
1133       || (dollar_first_arg_num
1134           && dollar_max_arg_used < dollar_arguments_count))
1135     {
1136       res->number_other--;
1137       res->number_dollar_extra_args++;
1138     }
1139 }
1140
1141
1142 /* Retrieve the specification for a format flag.  SPEC contains the
1143    specifications for format flags for the applicable kind of format.
1144    FLAG is the flag in question.  If PREDICATES is NULL, the basic
1145    spec for that flag must be retrieved and must exist.  If
1146    PREDICATES is not NULL, it is a string listing possible predicates
1147    for the spec entry; if an entry predicated on any of these is
1148    found, it is returned, otherwise NULL is returned.  */
1149
1150 static const format_flag_spec *
1151 get_flag_spec (const format_flag_spec *spec, int flag, const char *predicates)
1152 {
1153   int i;
1154   for (i = 0; spec[i].flag_char != 0; i++)
1155     {
1156       if (spec[i].flag_char != flag)
1157         continue;
1158       if (predicates != NULL)
1159         {
1160           if (spec[i].predicate != 0
1161               && strchr (predicates, spec[i].predicate) != 0)
1162             return &spec[i];
1163         }
1164       else if (spec[i].predicate == 0)
1165         return &spec[i];
1166     }
1167   gcc_assert (predicates);
1168   return NULL;
1169 }
1170
1171
1172 /* Check the argument list of a call to printf, scanf, etc.
1173    INFO points to the function_format_info structure.
1174    PARAMS is the list of argument values.  */
1175
1176 static void
1177 check_format_info (function_format_info *info, tree params)
1178 {
1179   format_check_context format_ctx;
1180   unsigned HOST_WIDE_INT arg_num;
1181   tree format_tree;
1182   format_check_results res;
1183   /* Skip to format argument.  If the argument isn't available, there's
1184      no work for us to do; prototype checking will catch the problem.  */
1185   for (arg_num = 1; ; ++arg_num)
1186     {
1187       if (params == 0)
1188         return;
1189       if (arg_num == info->format_num)
1190         break;
1191       params = TREE_CHAIN (params);
1192     }
1193   format_tree = TREE_VALUE (params);
1194   params = TREE_CHAIN (params);
1195   if (format_tree == 0)
1196     return;
1197
1198   res.number_non_literal = 0;
1199   res.number_extra_args = 0;
1200   res.number_dollar_extra_args = 0;
1201   res.number_wide = 0;
1202   res.number_empty = 0;
1203   res.number_unterminated = 0;
1204   res.number_other = 0;
1205
1206   format_ctx.res = &res;
1207   format_ctx.info = info;
1208   format_ctx.params = params;
1209
1210   check_function_arguments_recurse (check_format_arg, &format_ctx,
1211                                     format_tree, arg_num);
1212
1213   if (res.number_non_literal > 0)
1214     {
1215       /* Functions taking a va_list normally pass a non-literal format
1216          string.  These functions typically are declared with
1217          first_arg_num == 0, so avoid warning in those cases.  */
1218       if (!(format_types[info->format_type].flags & (int) FMT_FLAG_ARG_CONVERT))
1219         {
1220           /* For strftime-like formats, warn for not checking the format
1221              string; but there are no arguments to check.  */
1222           warning (OPT_Wformat_nonliteral,
1223                    "format not a string literal, format string not checked");
1224         }
1225       else if (info->first_arg_num != 0)
1226         {
1227           /* If there are no arguments for the format at all, we may have
1228              printf (foo) which is likely to be a security hole.  */
1229           while (arg_num + 1 < info->first_arg_num)
1230             {
1231               if (params == 0)
1232                 break;
1233               params = TREE_CHAIN (params);
1234               ++arg_num;
1235             }
1236           if (params == 0 && warn_format_security)
1237             warning (OPT_Wformat_security,
1238                      "format not a string literal and no format arguments");
1239           else if (params == 0 && warn_format_nonliteral)
1240             warning (OPT_Wformat_nonliteral,
1241                      "format not a string literal and no format arguments");
1242           else
1243             warning (OPT_Wformat_nonliteral,
1244                      "format not a string literal, argument types not checked");
1245         }
1246     }
1247
1248   /* If there were extra arguments to the format, normally warn.  However,
1249      the standard does say extra arguments are ignored, so in the specific
1250      case where we have multiple leaves (conditional expressions or
1251      ngettext) allow extra arguments if at least one leaf didn't have extra
1252      arguments, but was otherwise OK (either non-literal or checked OK).
1253      If the format is an empty string, this should be counted similarly to the
1254      case of extra format arguments.  */
1255   if (res.number_extra_args > 0 && res.number_non_literal == 0
1256       && res.number_other == 0)
1257     warning (OPT_Wformat_extra_args, "too many arguments for format");
1258   if (res.number_dollar_extra_args > 0 && res.number_non_literal == 0
1259       && res.number_other == 0)
1260     warning (OPT_Wformat_extra_args, "unused arguments in $-style format");
1261   if (res.number_empty > 0 && res.number_non_literal == 0
1262       && res.number_other == 0)
1263     warning (OPT_Wformat_zero_length, "zero-length %s format string",
1264              format_types[info->format_type].name);
1265
1266   if (res.number_wide > 0)
1267     warning (OPT_Wformat, "format is a wide character string");
1268
1269   if (res.number_unterminated > 0)
1270     warning (OPT_Wformat, "unterminated format string");
1271 }
1272
1273 /* Callback from check_function_arguments_recurse to check a
1274    format string.  FORMAT_TREE is the format parameter.  ARG_NUM
1275    is the number of the format argument.  CTX points to a
1276    format_check_context.  */
1277
1278 static void
1279 check_format_arg (void *ctx, tree format_tree,
1280                   unsigned HOST_WIDE_INT arg_num)
1281 {
1282   format_check_context *format_ctx = (format_check_context *) ctx;
1283   format_check_results *res = format_ctx->res;
1284   function_format_info *info = format_ctx->info;
1285   tree params = format_ctx->params;
1286
1287   int format_length;
1288   HOST_WIDE_INT offset;
1289   const char *format_chars;
1290   tree array_size = 0;
1291   tree array_init;
1292
1293   if (integer_zerop (format_tree))
1294     {
1295       /* Skip to first argument to check, so we can see if this format
1296          has any arguments (it shouldn't).  */
1297       while (arg_num + 1 < info->first_arg_num)
1298         {
1299           if (params == 0)
1300             return;
1301           params = TREE_CHAIN (params);
1302           ++arg_num;
1303         }
1304
1305       if (params == 0)
1306         res->number_other++;
1307       else
1308         res->number_extra_args++;
1309
1310       return;
1311     }
1312
1313   offset = 0;
1314   if (TREE_CODE (format_tree) == PLUS_EXPR)
1315     {
1316       tree arg0, arg1;
1317
1318       arg0 = TREE_OPERAND (format_tree, 0);
1319       arg1 = TREE_OPERAND (format_tree, 1);
1320       STRIP_NOPS (arg0);
1321       STRIP_NOPS (arg1);
1322       if (TREE_CODE (arg1) == INTEGER_CST)
1323         format_tree = arg0;
1324       else if (TREE_CODE (arg0) == INTEGER_CST)
1325         {
1326           format_tree = arg1;
1327           arg1 = arg0;
1328         }
1329       else
1330         {
1331           res->number_non_literal++;
1332           return;
1333         }
1334       if (!host_integerp (arg1, 0)
1335           || (offset = tree_low_cst (arg1, 0)) < 0)
1336         {
1337           res->number_non_literal++;
1338           return;
1339         }
1340     }
1341   if (TREE_CODE (format_tree) != ADDR_EXPR)
1342     {
1343       res->number_non_literal++;
1344       return;
1345     }
1346   format_tree = TREE_OPERAND (format_tree, 0);
1347   if (TREE_CODE (format_tree) == ARRAY_REF
1348       && host_integerp (TREE_OPERAND (format_tree, 1), 0)
1349       && (offset += tree_low_cst (TREE_OPERAND (format_tree, 1), 0)) >= 0)
1350     format_tree = TREE_OPERAND (format_tree, 0);
1351   if (TREE_CODE (format_tree) == VAR_DECL
1352       && TREE_CODE (TREE_TYPE (format_tree)) == ARRAY_TYPE
1353       && (array_init = decl_constant_value (format_tree)) != format_tree
1354       && TREE_CODE (array_init) == STRING_CST)
1355     {
1356       /* Extract the string constant initializer.  Note that this may include
1357          a trailing NUL character that is not in the array (e.g.
1358          const char a[3] = "foo";).  */
1359       array_size = DECL_SIZE_UNIT (format_tree);
1360       format_tree = array_init;
1361     }
1362   if (TREE_CODE (format_tree) != STRING_CST)
1363     {
1364       res->number_non_literal++;
1365       return;
1366     }
1367   if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (format_tree))) != char_type_node)
1368     {
1369       res->number_wide++;
1370       return;
1371     }
1372   format_chars = TREE_STRING_POINTER (format_tree);
1373   format_length = TREE_STRING_LENGTH (format_tree);
1374   if (array_size != 0)
1375     {
1376       /* Variable length arrays can't be initialized.  */
1377       gcc_assert (TREE_CODE (array_size) == INTEGER_CST);
1378       
1379       if (host_integerp (array_size, 0))
1380         {
1381           HOST_WIDE_INT array_size_value = TREE_INT_CST_LOW (array_size);
1382           if (array_size_value > 0
1383               && array_size_value == (int) array_size_value
1384               && format_length > array_size_value)
1385             format_length = array_size_value;
1386         }
1387     }
1388   if (offset)
1389     {
1390       if (offset >= format_length)
1391         {
1392           res->number_non_literal++;
1393           return;
1394         }
1395       format_chars += offset;
1396       format_length -= offset;
1397     }
1398   if (format_length < 1)
1399     {
1400       res->number_unterminated++;
1401       return;
1402     }
1403   if (format_length == 1)
1404     {
1405       res->number_empty++;
1406       return;
1407     }
1408   if (format_chars[--format_length] != 0)
1409     {
1410       res->number_unterminated++;
1411       return;
1412     }
1413
1414   /* Skip to first argument to check.  */
1415   while (arg_num + 1 < info->first_arg_num)
1416     {
1417       if (params == 0)
1418         return;
1419       params = TREE_CHAIN (params);
1420       ++arg_num;
1421     }
1422   /* Provisionally increment res->number_other; check_format_info_main
1423      will decrement it if it finds there are extra arguments, but this way
1424      need not adjust it for every return.  */
1425   res->number_other++;
1426   check_format_info_main (res, info, format_chars, format_length,
1427                           params, arg_num);
1428 }
1429
1430
1431 /* Do the main part of checking a call to a format function.  FORMAT_CHARS
1432    is the NUL-terminated format string (which at this point may contain
1433    internal NUL characters); FORMAT_LENGTH is its length (excluding the
1434    terminating NUL character).  ARG_NUM is one less than the number of
1435    the first format argument to check; PARAMS points to that format
1436    argument in the list of arguments.  */
1437
1438 static void
1439 check_format_info_main (format_check_results *res,
1440                         function_format_info *info, const char *format_chars,
1441                         int format_length, tree params,
1442                         unsigned HOST_WIDE_INT arg_num)
1443 {
1444   const char *orig_format_chars = format_chars;
1445   tree first_fillin_param = params;
1446
1447   const format_kind_info *fki = &format_types[info->format_type];
1448   const format_flag_spec *flag_specs = fki->flag_specs;
1449   const format_flag_pair *bad_flag_pairs = fki->bad_flag_pairs;
1450
1451   /* -1 if no conversions taking an operand have been found; 0 if one has
1452      and it didn't use $; 1 if $ formats are in use.  */
1453   int has_operand_number = -1;
1454
1455   init_dollar_format_checking (info->first_arg_num, first_fillin_param);
1456
1457   while (1)
1458     {
1459       int i;
1460       int suppressed = FALSE;
1461       const char *length_chars = NULL;
1462       enum format_lengths length_chars_val = FMT_LEN_none;
1463       enum format_std_version length_chars_std = STD_C89;
1464       int format_char;
1465       tree cur_param;
1466       tree wanted_type;
1467       int main_arg_num = 0;
1468       tree main_arg_params = 0;
1469       enum format_std_version wanted_type_std;
1470       const char *wanted_type_name;
1471       format_wanted_type width_wanted_type;
1472       format_wanted_type precision_wanted_type;
1473       format_wanted_type main_wanted_type;
1474       format_wanted_type *first_wanted_type = NULL;
1475       format_wanted_type *last_wanted_type = NULL;
1476       const format_length_info *fli = NULL;
1477       const format_char_info *fci = NULL;
1478       char flag_chars[256];
1479       int aflag = 0;
1480       const char *format_start = format_chars;
1481       if (*format_chars == 0)
1482         {
1483           if (format_chars - orig_format_chars != format_length)
1484             warning (OPT_Wformat, "embedded %<\\0%> in format");
1485           if (info->first_arg_num != 0 && params != 0
1486               && has_operand_number <= 0)
1487             {
1488               res->number_other--;
1489               res->number_extra_args++;
1490             }
1491           if (has_operand_number > 0)
1492             finish_dollar_format_checking (res, fki->flags & (int) FMT_FLAG_DOLLAR_GAP_POINTER_OK);
1493           return;
1494         }
1495       if (*format_chars++ != '%')
1496         continue;
1497       if (*format_chars == 0)
1498         {
1499           warning (OPT_Wformat, "spurious trailing %<%%%> in format");
1500           continue;
1501         }
1502       if (*format_chars == '%')
1503         {
1504           ++format_chars;
1505           continue;
1506         }
1507       flag_chars[0] = 0;
1508
1509       if ((fki->flags & (int) FMT_FLAG_USE_DOLLAR) && has_operand_number != 0)
1510         {
1511           /* Possibly read a $ operand number at the start of the format.
1512              If one was previously used, one is required here.  If one
1513              is not used here, we can't immediately conclude this is a
1514              format without them, since it could be printf %m or scanf %*.  */
1515           int opnum;
1516           opnum = maybe_read_dollar_number (&format_chars, 0,
1517                                             first_fillin_param,
1518                                             &main_arg_params, fki);
1519           if (opnum == -1)
1520             return;
1521           else if (opnum > 0)
1522             {
1523               has_operand_number = 1;
1524               main_arg_num = opnum + info->first_arg_num - 1;
1525             }
1526         }
1527       else if (fki->flags & FMT_FLAG_USE_DOLLAR)
1528         {
1529           if (avoid_dollar_number (format_chars))
1530             return;
1531         }
1532
1533       /* Read any format flags, but do not yet validate them beyond removing
1534          duplicates, since in general validation depends on the rest of
1535          the format.  */
1536       while (*format_chars != 0
1537              && strchr (fki->flag_chars, *format_chars) != 0)
1538         {
1539           const format_flag_spec *s = get_flag_spec (flag_specs,
1540                                                      *format_chars, NULL);
1541           if (strchr (flag_chars, *format_chars) != 0)
1542             {
1543               warning (OPT_Wformat, "repeated %s in format", _(s->name));
1544             }
1545           else
1546             {
1547               i = strlen (flag_chars);
1548               flag_chars[i++] = *format_chars;
1549               flag_chars[i] = 0;
1550             }
1551           if (s->skip_next_char)
1552             {
1553               ++format_chars;
1554               if (*format_chars == 0)
1555                 {
1556                   warning (OPT_Wformat, "missing fill character at end of strfmon format");
1557                   return;
1558                 }
1559             }
1560           ++format_chars;
1561         }
1562
1563       /* Read any format width, possibly * or *m$.  */
1564       if (fki->width_char != 0)
1565         {
1566           if (fki->width_type != NULL && *format_chars == '*')
1567             {
1568               i = strlen (flag_chars);
1569               flag_chars[i++] = fki->width_char;
1570               flag_chars[i] = 0;
1571               /* "...a field width...may be indicated by an asterisk.
1572                  In this case, an int argument supplies the field width..."  */
1573               ++format_chars;
1574               if (has_operand_number != 0)
1575                 {
1576                   int opnum;
1577                   opnum = maybe_read_dollar_number (&format_chars,
1578                                                     has_operand_number == 1,
1579                                                     first_fillin_param,
1580                                                     &params, fki);
1581                   if (opnum == -1)
1582                     return;
1583                   else if (opnum > 0)
1584                     {
1585                       has_operand_number = 1;
1586                       arg_num = opnum + info->first_arg_num - 1;
1587                     }
1588                   else
1589                     has_operand_number = 0;
1590                 }
1591               else
1592                 {
1593                   if (avoid_dollar_number (format_chars))
1594                     return;
1595                 }
1596               if (info->first_arg_num != 0)
1597                 {
1598                   if (params == 0)
1599                     {
1600                       warning (OPT_Wformat, "too few arguments for format");
1601                       return;
1602                     }
1603                   cur_param = TREE_VALUE (params);
1604                   if (has_operand_number <= 0)
1605                     {
1606                       params = TREE_CHAIN (params);
1607                       ++arg_num;
1608                     }
1609                   width_wanted_type.wanted_type = *fki->width_type;
1610                   width_wanted_type.wanted_type_name = NULL;
1611                   width_wanted_type.pointer_count = 0;
1612                   width_wanted_type.char_lenient_flag = 0;
1613                   width_wanted_type.writing_in_flag = 0;
1614                   width_wanted_type.reading_from_flag = 0;
1615                   width_wanted_type.name = _("field width");
1616                   width_wanted_type.param = cur_param;
1617                   width_wanted_type.arg_num = arg_num;
1618                   width_wanted_type.next = NULL;
1619                   if (last_wanted_type != 0)
1620                     last_wanted_type->next = &width_wanted_type;
1621                   if (first_wanted_type == 0)
1622                     first_wanted_type = &width_wanted_type;
1623                   last_wanted_type = &width_wanted_type;
1624                 }
1625             }
1626           else
1627             {
1628               /* Possibly read a numeric width.  If the width is zero,
1629                  we complain if appropriate.  */
1630               int non_zero_width_char = FALSE;
1631               int found_width = FALSE;
1632               while (ISDIGIT (*format_chars))
1633                 {
1634                   found_width = TRUE;
1635                   if (*format_chars != '0')
1636                     non_zero_width_char = TRUE;
1637                   ++format_chars;
1638                 }
1639               if (found_width && !non_zero_width_char &&
1640                   (fki->flags & (int) FMT_FLAG_ZERO_WIDTH_BAD))
1641                 warning (OPT_Wformat, "zero width in %s format", fki->name);
1642               if (found_width)
1643                 {
1644                   i = strlen (flag_chars);
1645                   flag_chars[i++] = fki->width_char;
1646                   flag_chars[i] = 0;
1647                 }
1648             }
1649         }
1650
1651       /* Read any format left precision (must be a number, not *).  */
1652       if (fki->left_precision_char != 0 && *format_chars == '#')
1653         {
1654           ++format_chars;
1655           i = strlen (flag_chars);
1656           flag_chars[i++] = fki->left_precision_char;
1657           flag_chars[i] = 0;
1658           if (!ISDIGIT (*format_chars))
1659             warning (OPT_Wformat, "empty left precision in %s format", fki->name);
1660           while (ISDIGIT (*format_chars))
1661             ++format_chars;
1662         }
1663
1664       /* Read any format precision, possibly * or *m$.  */
1665       if (fki->precision_char != 0 && *format_chars == '.')
1666         {
1667           ++format_chars;
1668           i = strlen (flag_chars);
1669           flag_chars[i++] = fki->precision_char;
1670           flag_chars[i] = 0;
1671           if (fki->precision_type != NULL && *format_chars == '*')
1672             {
1673               /* "...a...precision...may be indicated by an asterisk.
1674                  In this case, an int argument supplies the...precision."  */
1675               ++format_chars;
1676               if (has_operand_number != 0)
1677                 {
1678                   int opnum;
1679                   opnum = maybe_read_dollar_number (&format_chars,
1680                                                     has_operand_number == 1,
1681                                                     first_fillin_param,
1682                                                     &params, fki);
1683                   if (opnum == -1)
1684                     return;
1685                   else if (opnum > 0)
1686                     {
1687                       has_operand_number = 1;
1688                       arg_num = opnum + info->first_arg_num - 1;
1689                     }
1690                   else
1691                     has_operand_number = 0;
1692                 }
1693               else
1694                 {
1695                   if (avoid_dollar_number (format_chars))
1696                     return;
1697                 }
1698               if (info->first_arg_num != 0)
1699                 {
1700                   if (params == 0)
1701                     {
1702                       warning (OPT_Wformat, "too few arguments for format");
1703                       return;
1704                     }
1705                   cur_param = TREE_VALUE (params);
1706                   if (has_operand_number <= 0)
1707                     {
1708                       params = TREE_CHAIN (params);
1709                       ++arg_num;
1710                     }
1711                   precision_wanted_type.wanted_type = *fki->precision_type;
1712                   precision_wanted_type.wanted_type_name = NULL;
1713                   precision_wanted_type.pointer_count = 0;
1714                   precision_wanted_type.char_lenient_flag = 0;
1715                   precision_wanted_type.writing_in_flag = 0;
1716                   precision_wanted_type.reading_from_flag = 0;
1717                   precision_wanted_type.name = _("field precision");
1718                   precision_wanted_type.param = cur_param;
1719                   precision_wanted_type.arg_num = arg_num;
1720                   precision_wanted_type.next = NULL;
1721                   if (last_wanted_type != 0)
1722                     last_wanted_type->next = &precision_wanted_type;
1723                   if (first_wanted_type == 0)
1724                     first_wanted_type = &precision_wanted_type;
1725                   last_wanted_type = &precision_wanted_type;
1726                 }
1727             }
1728           else
1729             {
1730               if (!(fki->flags & (int) FMT_FLAG_EMPTY_PREC_OK)
1731                   && !ISDIGIT (*format_chars))
1732                 warning (OPT_Wformat, "empty precision in %s format", fki->name);
1733               while (ISDIGIT (*format_chars))
1734                 ++format_chars;
1735             }
1736         }
1737
1738       /* Read any length modifier, if this kind of format has them.  */
1739       fli = fki->length_char_specs;
1740       length_chars = NULL;
1741       length_chars_val = FMT_LEN_none;
1742       length_chars_std = STD_C89;
1743       if (fli)
1744         {
1745           while (fli->name != 0 && fli->name[0] != *format_chars)
1746             fli++;
1747           if (fli->name != 0)
1748             {
1749               format_chars++;
1750               if (fli->double_name != 0 && fli->name[0] == *format_chars)
1751                 {
1752                   format_chars++;
1753                   length_chars = fli->double_name;
1754                   length_chars_val = fli->double_index;
1755                   length_chars_std = fli->double_std;
1756                 }
1757               else
1758                 {
1759                   length_chars = fli->name;
1760                   length_chars_val = fli->index;
1761                   length_chars_std = fli->std;
1762                 }
1763               i = strlen (flag_chars);
1764               flag_chars[i++] = fki->length_code_char;
1765               flag_chars[i] = 0;
1766             }
1767           if (pedantic)
1768             {
1769               /* Warn if the length modifier is non-standard.  */
1770               if (ADJ_STD (length_chars_std) > C_STD_VER)
1771                 warning (OPT_Wformat,
1772                          "%s does not support the %qs %s length modifier",
1773                          C_STD_NAME (length_chars_std), length_chars,
1774                          fki->name);
1775             }
1776         }
1777
1778       /* Read any modifier (strftime E/O).  */
1779       if (fki->modifier_chars != NULL)
1780         {
1781           while (*format_chars != 0
1782                  && strchr (fki->modifier_chars, *format_chars) != 0)
1783             {
1784               if (strchr (flag_chars, *format_chars) != 0)
1785                 {
1786                   const format_flag_spec *s = get_flag_spec (flag_specs,
1787                                                              *format_chars, NULL);
1788                   warning (OPT_Wformat, "repeated %s in format", _(s->name));
1789                 }
1790               else
1791                 {
1792                   i = strlen (flag_chars);
1793                   flag_chars[i++] = *format_chars;
1794                   flag_chars[i] = 0;
1795                 }
1796               ++format_chars;
1797             }
1798         }
1799
1800       /* Handle the scanf allocation kludge.  */
1801       if (fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE)
1802         {
1803           if (*format_chars == 'a' && !flag_isoc99)
1804             {
1805               if (format_chars[1] == 's' || format_chars[1] == 'S'
1806                   || format_chars[1] == '[')
1807                 {
1808                   /* 'a' is used as a flag.  */
1809                   i = strlen (flag_chars);
1810                   flag_chars[i++] = 'a';
1811                   flag_chars[i] = 0;
1812                   format_chars++;
1813                 }
1814             }
1815         }
1816
1817       format_char = *format_chars;
1818       if (format_char == 0
1819           || (!(fki->flags & (int) FMT_FLAG_FANCY_PERCENT_OK)
1820               && format_char == '%'))
1821         {
1822           warning (OPT_Wformat, "conversion lacks type at end of format");
1823           continue;
1824         }
1825       format_chars++;
1826       fci = fki->conversion_specs;
1827       while (fci->format_chars != 0
1828              && strchr (fci->format_chars, format_char) == 0)
1829           ++fci;
1830       if (fci->format_chars == 0)
1831         {
1832           if (ISGRAPH (format_char))
1833             warning (OPT_Wformat, "unknown conversion type character %qc in format",
1834                      format_char);
1835           else
1836             warning (OPT_Wformat, "unknown conversion type character 0x%x in format",
1837                      format_char);
1838           continue;
1839         }
1840       if (pedantic)
1841         {
1842           if (ADJ_STD (fci->std) > C_STD_VER)
1843             warning (OPT_Wformat, "%s does not support the %<%%%c%> %s format",
1844                      C_STD_NAME (fci->std), format_char, fki->name);
1845         }
1846
1847       /* Validate the individual flags used, removing any that are invalid.  */
1848       {
1849         int d = 0;
1850         for (i = 0; flag_chars[i] != 0; i++)
1851           {
1852             const format_flag_spec *s = get_flag_spec (flag_specs,
1853                                                        flag_chars[i], NULL);
1854             flag_chars[i - d] = flag_chars[i];
1855             if (flag_chars[i] == fki->length_code_char)
1856               continue;
1857             if (strchr (fci->flag_chars, flag_chars[i]) == 0)
1858               {
1859                 warning (OPT_Wformat, "%s used with %<%%%c%> %s format",
1860                          _(s->name), format_char, fki->name);
1861                 d++;
1862                 continue;
1863               }
1864             if (pedantic)
1865               {
1866                 const format_flag_spec *t;
1867                 if (ADJ_STD (s->std) > C_STD_VER)
1868                   warning (OPT_Wformat, "%s does not support %s",
1869                            C_STD_NAME (s->std), _(s->long_name));
1870                 t = get_flag_spec (flag_specs, flag_chars[i], fci->flags2);
1871                 if (t != NULL && ADJ_STD (t->std) > ADJ_STD (s->std))
1872                   {
1873                     const char *long_name = (t->long_name != NULL
1874                                              ? t->long_name
1875                                              : s->long_name);
1876                     if (ADJ_STD (t->std) > C_STD_VER)
1877                       warning (OPT_Wformat,
1878                                "%s does not support %s with the %<%%%c%> %s format",
1879                                C_STD_NAME (t->std), _(long_name),
1880                                format_char, fki->name);
1881                   }
1882               }
1883           }
1884         flag_chars[i - d] = 0;
1885       }
1886
1887       if ((fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE)
1888           && strchr (flag_chars, 'a') != 0)
1889         aflag = 1;
1890
1891       if (fki->suppression_char
1892           && strchr (flag_chars, fki->suppression_char) != 0)
1893         suppressed = 1;
1894
1895       /* Validate the pairs of flags used.  */
1896       for (i = 0; bad_flag_pairs[i].flag_char1 != 0; i++)
1897         {
1898           const format_flag_spec *s, *t;
1899           if (strchr (flag_chars, bad_flag_pairs[i].flag_char1) == 0)
1900             continue;
1901           if (strchr (flag_chars, bad_flag_pairs[i].flag_char2) == 0)
1902             continue;
1903           if (bad_flag_pairs[i].predicate != 0
1904               && strchr (fci->flags2, bad_flag_pairs[i].predicate) == 0)
1905             continue;
1906           s = get_flag_spec (flag_specs, bad_flag_pairs[i].flag_char1, NULL);
1907           t = get_flag_spec (flag_specs, bad_flag_pairs[i].flag_char2, NULL);
1908           if (bad_flag_pairs[i].ignored)
1909             {
1910               if (bad_flag_pairs[i].predicate != 0)
1911                 warning (OPT_Wformat,
1912                          "%s ignored with %s and %<%%%c%> %s format",
1913                          _(s->name), _(t->name), format_char,
1914                          fki->name);
1915               else
1916                 warning (OPT_Wformat, "%s ignored with %s in %s format",
1917                          _(s->name), _(t->name), fki->name);
1918             }
1919           else
1920             {
1921               if (bad_flag_pairs[i].predicate != 0)
1922                 warning (OPT_Wformat,
1923                          "use of %s and %s together with %<%%%c%> %s format",
1924                          _(s->name), _(t->name), format_char,
1925                          fki->name);
1926               else
1927                 warning (OPT_Wformat, "use of %s and %s together in %s format",
1928                          _(s->name), _(t->name), fki->name);
1929             }
1930         }
1931
1932       /* Give Y2K warnings.  */
1933       if (warn_format_y2k)
1934         {
1935           int y2k_level = 0;
1936           if (strchr (fci->flags2, '4') != 0)
1937             if (strchr (flag_chars, 'E') != 0)
1938               y2k_level = 3;
1939             else
1940               y2k_level = 2;
1941           else if (strchr (fci->flags2, '3') != 0)
1942             y2k_level = 3;
1943           else if (strchr (fci->flags2, '2') != 0)
1944             y2k_level = 2;
1945           if (y2k_level == 3)
1946             warning (OPT_Wformat_y2k, "%<%%%c%> yields only last 2 digits of "
1947                      "year in some locales on non-BSD systems", format_char);
1948           else if (y2k_level == 2)
1949             warning (OPT_Wformat_y2k, "%<%%%c%> yields only last 2 digits of "
1950                      "year", format_char);
1951         }
1952
1953       if (strchr (fci->flags2, '[') != 0)
1954         {
1955           /* Skip over scan set, in case it happens to have '%' in it.  */
1956           if (*format_chars == '^')
1957             ++format_chars;
1958           /* Find closing bracket; if one is hit immediately, then
1959              it's part of the scan set rather than a terminator.  */
1960           if (*format_chars == ']')
1961             ++format_chars;
1962           while (*format_chars && *format_chars != ']')
1963             ++format_chars;
1964           if (*format_chars != ']')
1965             /* The end of the format string was reached.  */
1966             warning (OPT_Wformat, "no closing %<]%> for %<%%[%> format");
1967         }
1968
1969       wanted_type = 0;
1970       wanted_type_name = 0;
1971       if (fki->flags & (int) FMT_FLAG_ARG_CONVERT)
1972         {
1973           wanted_type = (fci->types[length_chars_val].type
1974                          ? *fci->types[length_chars_val].type : 0);
1975           wanted_type_name = fci->types[length_chars_val].name;
1976           wanted_type_std = fci->types[length_chars_val].std;
1977           if (wanted_type == 0)
1978             {
1979               warning (OPT_Wformat,
1980                        "use of %qs length modifier with %qc type character",
1981                        length_chars, format_char);
1982               /* Heuristic: skip one argument when an invalid length/type
1983                  combination is encountered.  */
1984               arg_num++;
1985               if (params == 0)
1986                 {
1987                   warning (OPT_Wformat, "too few arguments for format");
1988                   return;
1989                 }
1990               params = TREE_CHAIN (params);
1991               continue;
1992             }
1993           else if (pedantic
1994                    /* Warn if non-standard, provided it is more non-standard
1995                       than the length and type characters that may already
1996                       have been warned for.  */
1997                    && ADJ_STD (wanted_type_std) > ADJ_STD (length_chars_std)
1998                    && ADJ_STD (wanted_type_std) > ADJ_STD (fci->std))
1999             {
2000               if (ADJ_STD (wanted_type_std) > C_STD_VER)
2001                 warning (OPT_Wformat,
2002                          "%s does not support the %<%%%s%c%> %s format",
2003                          C_STD_NAME (wanted_type_std), length_chars,
2004                          format_char, fki->name);
2005             }
2006         }
2007
2008       main_wanted_type.next = NULL;
2009
2010       /* Finally. . .check type of argument against desired type!  */
2011       if (info->first_arg_num == 0)
2012         continue;
2013       if ((fci->pointer_count == 0 && wanted_type == void_type_node)
2014           || suppressed)
2015         {
2016           if (main_arg_num != 0)
2017             {
2018               if (suppressed)
2019                 warning (OPT_Wformat, "operand number specified with "
2020                          "suppressed assignment");
2021               else
2022                 warning (OPT_Wformat, "operand number specified for format "
2023                          "taking no argument");
2024             }
2025         }
2026       else
2027         {
2028           format_wanted_type *wanted_type_ptr;
2029
2030           if (main_arg_num != 0)
2031             {
2032               arg_num = main_arg_num;
2033               params = main_arg_params;
2034             }
2035           else
2036             {
2037               ++arg_num;
2038               if (has_operand_number > 0)
2039                 {
2040                   warning (OPT_Wformat, "missing $ operand number in format");
2041                   return;
2042                 }
2043               else
2044                 has_operand_number = 0;
2045             }
2046
2047           wanted_type_ptr = &main_wanted_type;
2048           while (fci)
2049             {
2050               if (params == 0)
2051                 {
2052                   warning (OPT_Wformat, "too few arguments for format");
2053                   return;
2054                 }
2055
2056               cur_param = TREE_VALUE (params);
2057               params = TREE_CHAIN (params);
2058
2059               wanted_type_ptr->wanted_type = wanted_type;
2060               wanted_type_ptr->wanted_type_name = wanted_type_name;
2061               wanted_type_ptr->pointer_count = fci->pointer_count + aflag;
2062               wanted_type_ptr->char_lenient_flag = 0;
2063               if (strchr (fci->flags2, 'c') != 0)
2064                 wanted_type_ptr->char_lenient_flag = 1;
2065               wanted_type_ptr->writing_in_flag = 0;
2066               wanted_type_ptr->reading_from_flag = 0;
2067               if (aflag)
2068                 wanted_type_ptr->writing_in_flag = 1;
2069               else
2070                 {
2071                   if (strchr (fci->flags2, 'W') != 0)
2072                     wanted_type_ptr->writing_in_flag = 1;
2073                   if (strchr (fci->flags2, 'R') != 0)
2074                     wanted_type_ptr->reading_from_flag = 1;
2075                 }
2076               wanted_type_ptr->name = NULL;
2077               wanted_type_ptr->param = cur_param;
2078               wanted_type_ptr->arg_num = arg_num;
2079               wanted_type_ptr->next = NULL;
2080               if (last_wanted_type != 0)
2081                 last_wanted_type->next = wanted_type_ptr;
2082               if (first_wanted_type == 0)
2083                 first_wanted_type = wanted_type_ptr;
2084               last_wanted_type = wanted_type_ptr;
2085
2086               fci = fci->chain;
2087               if (fci)
2088                 {
2089                   wanted_type_ptr = ggc_alloc (sizeof (main_wanted_type));
2090                   arg_num++;
2091                   wanted_type = *fci->types[length_chars_val].type;
2092                   wanted_type_name = fci->types[length_chars_val].name;
2093                 }
2094             }
2095         }
2096
2097       if (first_wanted_type != 0)
2098         check_format_types (first_wanted_type, format_start,
2099                             format_chars - format_start);
2100
2101       if (main_wanted_type.next != NULL)
2102         {
2103           format_wanted_type *wanted_type_ptr = main_wanted_type.next;
2104           while (wanted_type_ptr)
2105             {
2106               format_wanted_type *next = wanted_type_ptr->next;
2107               ggc_free (wanted_type_ptr);
2108               wanted_type_ptr = next;
2109             }
2110         }
2111     }
2112 }
2113
2114
2115 /* Check the argument types from a single format conversion (possibly
2116    including width and precision arguments).  */
2117 static void
2118 check_format_types (format_wanted_type *types, const char *format_start,
2119                     int format_length)
2120 {
2121   for (; types != 0; types = types->next)
2122     {
2123       tree cur_param;
2124       tree cur_type;
2125       tree orig_cur_type;
2126       tree wanted_type;
2127       int arg_num;
2128       int i;
2129       int char_type_flag;
2130       cur_param = types->param;
2131       cur_type = TREE_TYPE (cur_param);
2132       if (cur_type == error_mark_node)
2133         continue;
2134       orig_cur_type = cur_type;
2135       char_type_flag = 0;
2136       wanted_type = types->wanted_type;
2137       arg_num = types->arg_num;
2138
2139       /* The following should not occur here.  */
2140       gcc_assert (wanted_type);
2141       gcc_assert (wanted_type != void_type_node || types->pointer_count);
2142
2143       if (types->pointer_count == 0)
2144         wanted_type = lang_hooks.types.type_promotes_to (wanted_type);
2145
2146       wanted_type = TYPE_MAIN_VARIANT (wanted_type);
2147
2148       STRIP_NOPS (cur_param);
2149
2150       /* Check the types of any additional pointer arguments
2151          that precede the "real" argument.  */
2152       for (i = 0; i < types->pointer_count; ++i)
2153         {
2154           if (TREE_CODE (cur_type) == POINTER_TYPE)
2155             {
2156               cur_type = TREE_TYPE (cur_type);
2157               if (cur_type == error_mark_node)
2158                 break;
2159
2160               /* Check for writing through a NULL pointer.  */
2161               if (types->writing_in_flag
2162                   && i == 0
2163                   && cur_param != 0
2164                   && integer_zerop (cur_param))
2165                 warning (OPT_Wformat, "writing through null pointer "
2166                          "(argument %d)", arg_num);
2167
2168               /* Check for reading through a NULL pointer.  */
2169               if (types->reading_from_flag
2170                   && i == 0
2171                   && cur_param != 0
2172                   && integer_zerop (cur_param))
2173                 warning (OPT_Wformat, "reading through null pointer "
2174                          "(argument %d)", arg_num);
2175
2176               if (cur_param != 0 && TREE_CODE (cur_param) == ADDR_EXPR)
2177                 cur_param = TREE_OPERAND (cur_param, 0);
2178               else
2179                 cur_param = 0;
2180
2181               /* See if this is an attempt to write into a const type with
2182                  scanf or with printf "%n".  Note: the writing in happens
2183                  at the first indirection only, if for example
2184                  void * const * is passed to scanf %p; passing
2185                  const void ** is simply passing an incompatible type.  */
2186               if (types->writing_in_flag
2187                   && i == 0
2188                   && (TYPE_READONLY (cur_type)
2189                       || (cur_param != 0
2190                           && (CONSTANT_CLASS_P (cur_param)
2191                               || (DECL_P (cur_param)
2192                                   && TREE_READONLY (cur_param))))))
2193                 warning (OPT_Wformat, "writing into constant object "
2194                          "(argument %d)", arg_num);
2195
2196               /* If there are extra type qualifiers beyond the first
2197                  indirection, then this makes the types technically
2198                  incompatible.  */
2199               if (i > 0
2200                   && pedantic
2201                   && (TYPE_READONLY (cur_type)
2202                       || TYPE_VOLATILE (cur_type)
2203                       || TYPE_RESTRICT (cur_type)))
2204                 warning (OPT_Wformat, "extra type qualifiers in format "
2205                          "argument (argument %d)",
2206                          arg_num);
2207
2208             }
2209           else
2210             {
2211               format_type_warning (types->name, format_start, format_length,
2212                                    wanted_type, types->pointer_count,
2213                                    types->wanted_type_name, orig_cur_type,
2214                                    arg_num);
2215               break;
2216             }
2217         }
2218
2219       if (i < types->pointer_count)
2220         continue;
2221
2222       cur_type = TYPE_MAIN_VARIANT (cur_type);
2223
2224       /* Check whether the argument type is a character type.  This leniency
2225          only applies to certain formats, flagged with 'c'.
2226       */
2227       if (types->char_lenient_flag)
2228         char_type_flag = (cur_type == char_type_node
2229                           || cur_type == signed_char_type_node
2230                           || cur_type == unsigned_char_type_node);
2231
2232       /* Check the type of the "real" argument, if there's a type we want.  */
2233       if (lang_hooks.types_compatible_p (wanted_type, cur_type))
2234         continue;
2235       /* If we want 'void *', allow any pointer type.
2236          (Anything else would already have got a warning.)
2237          With -pedantic, only allow pointers to void and to character
2238          types.  */
2239       if (wanted_type == void_type_node
2240           && (!pedantic || (i == 1 && char_type_flag)))
2241         continue;
2242       /* Don't warn about differences merely in signedness, unless
2243          -pedantic.  With -pedantic, warn if the type is a pointer
2244          target and not a character type, and for character types at
2245          a second level of indirection.  */
2246       if (TREE_CODE (wanted_type) == INTEGER_TYPE
2247           && TREE_CODE (cur_type) == INTEGER_TYPE
2248           && (!pedantic || i == 0 || (i == 1 && char_type_flag))
2249           && (TYPE_UNSIGNED (wanted_type)
2250               ? wanted_type == c_common_unsigned_type (cur_type)
2251               : wanted_type == c_common_signed_type (cur_type)))
2252         continue;
2253       /* Likewise, "signed char", "unsigned char" and "char" are
2254          equivalent but the above test won't consider them equivalent.  */
2255       if (wanted_type == char_type_node
2256           && (!pedantic || i < 2)
2257           && char_type_flag)
2258         continue;
2259       /* Now we have a type mismatch.  */
2260       format_type_warning (types->name, format_start, format_length,
2261                            wanted_type, types->pointer_count,
2262                            types->wanted_type_name, orig_cur_type, arg_num);
2263     }
2264 }
2265
2266
2267 /* Give a warning about a format argument of different type from that
2268    expected.  DESCR is a description such as "field precision", or
2269    NULL for an ordinary format.  For an ordinary format, FORMAT_START
2270    points to where the format starts in the format string and
2271    FORMAT_LENGTH is its length.  WANTED_TYPE is the type the argument
2272    should have after POINTER_COUNT pointer dereferences.
2273    WANTED_NAME_NAME is a possibly more friendly name of WANTED_TYPE,
2274    or NULL if the ordinary name of the type should be used.  ARG_TYPE
2275    is the type of the actual argument.  ARG_NUM is the number of that
2276    argument.  */
2277 static void
2278 format_type_warning (const char *descr, const char *format_start,
2279                      int format_length, tree wanted_type, int pointer_count,
2280                      const char *wanted_type_name, tree arg_type, int arg_num)
2281 {
2282   char *p;
2283   /* If ARG_TYPE is a typedef with a misleading name (for example,
2284      size_t but not the standard size_t expected by printf %zu), avoid
2285      printing the typedef name.  */
2286   if (wanted_type_name
2287       && TYPE_NAME (arg_type)
2288       && TREE_CODE (TYPE_NAME (arg_type)) == TYPE_DECL
2289       && DECL_NAME (TYPE_NAME (arg_type))
2290       && !strcmp (wanted_type_name,
2291                   lang_hooks.decl_printable_name (TYPE_NAME (arg_type), 2)))
2292     arg_type = TYPE_MAIN_VARIANT (arg_type);
2293   /* The format type and name exclude any '*' for pointers, so those
2294      must be formatted manually.  For all the types we currently have,
2295      this is adequate, but formats taking pointers to functions or
2296      arrays would require the full type to be built up in order to
2297      print it with %T.  */
2298   p = alloca (pointer_count + 2);
2299   if (pointer_count == 0)
2300     p[0] = 0;
2301   else if (c_dialect_cxx ())
2302     {
2303       memset (p, '*', pointer_count);
2304       p[pointer_count] = 0;
2305     }
2306   else
2307     {
2308       p[0] = ' ';
2309       memset (p + 1, '*', pointer_count);
2310       p[pointer_count + 1] = 0;
2311     }
2312   if (wanted_type_name)
2313     {
2314       if (descr)
2315         warning (OPT_Wformat, "%s should have type %<%s%s%>, "
2316                  "but argument %d has type %qT",
2317                  descr, wanted_type_name, p, arg_num, arg_type);
2318       else
2319         warning (OPT_Wformat, "format %q.*s expects type %<%s%s%>, "
2320                  "but argument %d has type %qT",
2321                  format_length, format_start, wanted_type_name, p,
2322                  arg_num, arg_type);
2323     }
2324   else
2325     {
2326       if (descr)
2327         warning (OPT_Wformat, "%s should have type %<%T%s%>, "
2328                  "but argument %d has type %qT",
2329                  descr, wanted_type, p, arg_num, arg_type);
2330       else
2331         warning (OPT_Wformat, "format %q.*s expects type %<%T%s%>, "
2332                  "but argument %d has type %qT",
2333                  format_length, format_start, wanted_type, p, arg_num, arg_type);
2334     }
2335 }
2336
2337
2338 /* Given a format_char_info array FCI, and a character C, this function
2339    returns the index into the conversion_specs where that specifier's
2340    data is located.  The character must exist.  */
2341 static unsigned int
2342 find_char_info_specifier_index (const format_char_info *fci, int c)
2343 {
2344   unsigned i;
2345
2346   for (i = 0; fci->format_chars; i++, fci++)
2347     if (strchr (fci->format_chars, c))
2348       return i;
2349   
2350   /* We shouldn't be looking for a non-existent specifier.  */
2351   gcc_unreachable ();
2352 }
2353
2354 /* Given a format_length_info array FLI, and a character C, this
2355    function returns the index into the conversion_specs where that
2356    modifier's data is located.  The character must exist.  */
2357 static unsigned int
2358 find_length_info_modifier_index (const format_length_info *fli, int c)
2359 {
2360   unsigned i;
2361
2362   for (i = 0; fli->name; i++, fli++)
2363     if (strchr (fli->name, c))
2364       return i;
2365   
2366   /* We shouldn't be looking for a non-existent modifier.  */
2367   gcc_unreachable ();
2368 }
2369
2370 /* Determine the type of HOST_WIDE_INT in the code being compiled for
2371    use in GCC's __asm_fprintf__ custom format attribute.  You must
2372    have set dynamic_format_types before calling this function.  */
2373 static void
2374 init_dynamic_asm_fprintf_info (void)
2375 {
2376   static tree hwi;
2377
2378   if (!hwi)
2379     {
2380       format_length_info *new_asm_fprintf_length_specs;
2381       unsigned int i;
2382           
2383       /* Find the underlying type for HOST_WIDE_INT.  For the %w
2384          length modifier to work, one must have issued: "typedef
2385          HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code
2386          prior to using that modifier.  */
2387       hwi = maybe_get_identifier ("__gcc_host_wide_int__");
2388       if (!hwi)
2389         {
2390           error ("%<__gcc_host_wide_int__%> is not defined as a type");
2391           return;
2392         }
2393       hwi = identifier_global_value (hwi);
2394       if (!hwi || TREE_CODE (hwi) != TYPE_DECL)
2395         {
2396           error ("%<__gcc_host_wide_int__%> is not defined as a type");
2397           return;
2398         }
2399       hwi = DECL_ORIGINAL_TYPE (hwi);
2400       gcc_assert (hwi);
2401       if (hwi != long_integer_type_node && hwi != long_long_integer_type_node)
2402         {
2403           error ("%<__gcc_host_wide_int__%> is not defined as %<long%>"
2404                  " or %<long long%>");
2405           return;
2406         }
2407
2408       /* Create a new (writable) copy of asm_fprintf_length_specs.  */
2409       new_asm_fprintf_length_specs = (format_length_info *)
2410                                      xmemdup (asm_fprintf_length_specs,
2411                                               sizeof (asm_fprintf_length_specs),
2412                                               sizeof (asm_fprintf_length_specs));
2413
2414       /* HOST_WIDE_INT must be one of 'long' or 'long long'.  */
2415       i = find_length_info_modifier_index (new_asm_fprintf_length_specs, 'w');
2416       if (hwi == long_integer_type_node)
2417         new_asm_fprintf_length_specs[i].index = FMT_LEN_l;
2418       else if (hwi == long_long_integer_type_node)
2419         new_asm_fprintf_length_specs[i].index = FMT_LEN_ll;
2420       else
2421         gcc_unreachable ();
2422
2423       /* Assign the new data for use.  */
2424       dynamic_format_types[asm_fprintf_format_type].length_char_specs =
2425         new_asm_fprintf_length_specs;
2426     }
2427 }
2428
2429 /* Determine the type of a "locus" in the code being compiled for use
2430    in GCC's __gcc_gfc__ custom format attribute.  You must have set
2431    dynamic_format_types before calling this function.  */
2432 static void
2433 init_dynamic_gfc_info (void)
2434 {
2435   static tree locus;
2436   
2437   if (!locus)
2438     {
2439       static format_char_info *gfc_fci;
2440
2441       /* For the GCC __gcc_gfc__ custom format specifier to work, one
2442          must have declared 'locus' prior to using this attribute.  If
2443          we haven't seen this declarations then you shouldn't use the
2444          specifier requiring that type.  */
2445       if ((locus = maybe_get_identifier ("locus")))
2446         {
2447           locus = identifier_global_value (locus);
2448           if (locus)
2449             {
2450               if (TREE_CODE (locus) != TYPE_DECL)
2451                 {
2452                   error ("%<locus%> is not defined as a type");
2453                   locus = 0;
2454                 }
2455               else
2456                 locus = TREE_TYPE (locus);
2457             }
2458         }
2459
2460       /* Assign the new data for use.  */
2461
2462       /* Handle the __gcc_gfc__ format specifics.  */
2463       if (!gfc_fci)
2464         dynamic_format_types[gcc_gfc_format_type].conversion_specs =
2465           gfc_fci = (format_char_info *)
2466                      xmemdup (gcc_gfc_char_table,
2467                               sizeof (gcc_gfc_char_table),
2468                               sizeof (gcc_gfc_char_table));
2469       if (locus)
2470         {
2471           const unsigned i = find_char_info_specifier_index (gfc_fci, 'L');
2472           gfc_fci[i].types[0].type = &locus;
2473           gfc_fci[i].pointer_count = 1;
2474         }
2475     }
2476 }
2477
2478 /* Determine the types of "tree" and "location_t" in the code being
2479    compiled for use in GCC's diagnostic custom format attributes.  You
2480    must have set dynamic_format_types before calling this function.  */
2481 static void
2482 init_dynamic_diag_info (void)
2483 {
2484   static tree t, loc, hwi;
2485
2486   if (!loc || !t || !hwi)
2487     {
2488       static format_char_info *diag_fci, *tdiag_fci, *cdiag_fci, *cxxdiag_fci;
2489       static format_length_info *diag_ls;
2490       unsigned int i;
2491
2492       /* For the GCC-diagnostics custom format specifiers to work, one
2493          must have declared 'tree' and/or 'location_t' prior to using
2494          those attributes.  If we haven't seen these declarations then
2495          you shouldn't use the specifiers requiring these types.
2496          However we don't force a hard ICE because we may see only one
2497          or the other type.  */
2498       if ((loc = maybe_get_identifier ("location_t")))
2499         {
2500           loc = identifier_global_value (loc);
2501           if (loc)
2502             {
2503               if (TREE_CODE (loc) != TYPE_DECL)
2504                 {
2505                   error ("%<location_t%> is not defined as a type");
2506                   loc = 0;
2507                 }
2508               else
2509                 loc = TREE_TYPE (loc);
2510             }
2511         }
2512
2513       /* We need to grab the underlying 'union tree_node' so peek into
2514          an extra type level.  */
2515       if ((t = maybe_get_identifier ("tree")))
2516         {
2517           t = identifier_global_value (t);
2518           if (t)
2519             {
2520               if (TREE_CODE (t) != TYPE_DECL)
2521                 {
2522                   error ("%<tree%> is not defined as a type");
2523                   t = 0;
2524                 }
2525               else if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE)
2526                 {
2527                   error ("%<tree%> is not defined as a pointer type");
2528                   t = 0;
2529                 }
2530               else
2531                 t = TREE_TYPE (TREE_TYPE (t));
2532             }
2533         }
2534     
2535       /* Find the underlying type for HOST_WIDE_INT.  For the %w
2536          length modifier to work, one must have issued: "typedef
2537          HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code
2538          prior to using that modifier.  */
2539       if ((hwi = maybe_get_identifier ("__gcc_host_wide_int__")))
2540         {
2541           hwi = identifier_global_value (hwi);
2542           if (hwi)
2543             {
2544               if (TREE_CODE (hwi) != TYPE_DECL)
2545                 {
2546                   error ("%<__gcc_host_wide_int__%> is not defined as a type");
2547                   hwi = 0;
2548                 }
2549               else
2550                 {
2551                   hwi = DECL_ORIGINAL_TYPE (hwi);
2552                   gcc_assert (hwi);
2553                   if (hwi != long_integer_type_node
2554                       && hwi != long_long_integer_type_node)
2555                     {
2556                       error ("%<__gcc_host_wide_int__%> is not defined"
2557                              " as %<long%> or %<long long%>");
2558                       hwi = 0;
2559                     }
2560                 }
2561             }
2562         }
2563       
2564       /* Assign the new data for use.  */
2565
2566       /* All the GCC diag formats use the same length specs.  */
2567       if (!diag_ls)
2568         dynamic_format_types[gcc_diag_format_type].length_char_specs =
2569           dynamic_format_types[gcc_tdiag_format_type].length_char_specs =
2570           dynamic_format_types[gcc_cdiag_format_type].length_char_specs =
2571           dynamic_format_types[gcc_cxxdiag_format_type].length_char_specs =
2572           diag_ls = (format_length_info *)
2573                     xmemdup (gcc_diag_length_specs,
2574                              sizeof (gcc_diag_length_specs),
2575                              sizeof (gcc_diag_length_specs)); 
2576       if (hwi)
2577         {
2578           /* HOST_WIDE_INT must be one of 'long' or 'long long'.  */
2579           i = find_length_info_modifier_index (diag_ls, 'w');
2580           if (hwi == long_integer_type_node)
2581             diag_ls[i].index = FMT_LEN_l;
2582           else if (hwi == long_long_integer_type_node)
2583             diag_ls[i].index = FMT_LEN_ll;
2584           else
2585             gcc_unreachable ();
2586         }
2587
2588       /* Handle the __gcc_diag__ format specifics.  */
2589       if (!diag_fci)
2590         dynamic_format_types[gcc_diag_format_type].conversion_specs =
2591           diag_fci = (format_char_info *)
2592                      xmemdup (gcc_diag_char_table,
2593                               sizeof (gcc_diag_char_table),
2594                               sizeof (gcc_diag_char_table));
2595       if (loc)
2596         {
2597           i = find_char_info_specifier_index (diag_fci, 'H');
2598           diag_fci[i].types[0].type = &loc;
2599           diag_fci[i].pointer_count = 1;
2600         }
2601       if (t)
2602         {
2603           i = find_char_info_specifier_index (diag_fci, 'J');
2604           diag_fci[i].types[0].type = &t;
2605           diag_fci[i].pointer_count = 1;
2606         }
2607
2608       /* Handle the __gcc_tdiag__ format specifics.  */
2609       if (!tdiag_fci)
2610         dynamic_format_types[gcc_tdiag_format_type].conversion_specs =
2611           tdiag_fci = (format_char_info *)
2612                       xmemdup (gcc_tdiag_char_table,
2613                                sizeof (gcc_tdiag_char_table),
2614                                sizeof (gcc_tdiag_char_table));
2615       if (loc)
2616         {
2617           i = find_char_info_specifier_index (tdiag_fci, 'H');
2618           tdiag_fci[i].types[0].type = &loc;
2619           tdiag_fci[i].pointer_count = 1;
2620         }
2621       if (t)
2622         {
2623           /* All specifiers taking a tree share the same struct.  */
2624           i = find_char_info_specifier_index (tdiag_fci, 'D');
2625           tdiag_fci[i].types[0].type = &t;
2626           tdiag_fci[i].pointer_count = 1;
2627           i = find_char_info_specifier_index (tdiag_fci, 'J');
2628           tdiag_fci[i].types[0].type = &t;
2629           tdiag_fci[i].pointer_count = 1;
2630         }
2631
2632       /* Handle the __gcc_cdiag__ format specifics.  */
2633       if (!cdiag_fci)
2634         dynamic_format_types[gcc_cdiag_format_type].conversion_specs =
2635           cdiag_fci = (format_char_info *)
2636                       xmemdup (gcc_cdiag_char_table,
2637                                sizeof (gcc_cdiag_char_table),
2638                                sizeof (gcc_cdiag_char_table));
2639       if (loc)
2640         {
2641           i = find_char_info_specifier_index (cdiag_fci, 'H');
2642           cdiag_fci[i].types[0].type = &loc;
2643           cdiag_fci[i].pointer_count = 1;
2644         }
2645       if (t)
2646         {
2647           /* All specifiers taking a tree share the same struct.  */
2648           i = find_char_info_specifier_index (cdiag_fci, 'D');
2649           cdiag_fci[i].types[0].type = &t;
2650           cdiag_fci[i].pointer_count = 1;
2651           i = find_char_info_specifier_index (cdiag_fci, 'J');
2652           cdiag_fci[i].types[0].type = &t;
2653           cdiag_fci[i].pointer_count = 1;
2654         }
2655
2656       /* Handle the __gcc_cxxdiag__ format specifics.  */
2657       if (!cxxdiag_fci)
2658         dynamic_format_types[gcc_cxxdiag_format_type].conversion_specs =
2659           cxxdiag_fci = (format_char_info *)
2660                         xmemdup (gcc_cxxdiag_char_table,
2661                                  sizeof (gcc_cxxdiag_char_table),
2662                                  sizeof (gcc_cxxdiag_char_table));
2663       if (loc)
2664         {
2665           i = find_char_info_specifier_index (cxxdiag_fci, 'H');
2666           cxxdiag_fci[i].types[0].type = &loc;
2667           cxxdiag_fci[i].pointer_count = 1;
2668         }
2669       if (t)
2670         {
2671           /* All specifiers taking a tree share the same struct.  */
2672           i = find_char_info_specifier_index (cxxdiag_fci, 'D');
2673           cxxdiag_fci[i].types[0].type = &t;
2674           cxxdiag_fci[i].pointer_count = 1;
2675           i = find_char_info_specifier_index (cxxdiag_fci, 'J');
2676           cxxdiag_fci[i].types[0].type = &t;
2677           cxxdiag_fci[i].pointer_count = 1;
2678         }
2679     }
2680 }
2681
2682 #ifdef TARGET_FORMAT_TYPES
2683 extern const format_kind_info TARGET_FORMAT_TYPES[];
2684 #endif
2685
2686 /* Handle a "format" attribute; arguments as in
2687    struct attribute_spec.handler.  */
2688 tree
2689 handle_format_attribute (tree *node, tree ARG_UNUSED (name), tree args,
2690                          int flags, bool *no_add_attrs)
2691 {
2692   tree type = *node;
2693   function_format_info info;
2694   tree argument;
2695
2696 #ifdef TARGET_FORMAT_TYPES
2697   /* If the target provides additional format types, we need to
2698      add them to FORMAT_TYPES at first use.  */
2699   if (TARGET_FORMAT_TYPES != NULL && !dynamic_format_types)
2700     {
2701       dynamic_format_types = xmalloc ((n_format_types + TARGET_N_FORMAT_TYPES)
2702                                       * sizeof (dynamic_format_types[0]));
2703       memcpy (dynamic_format_types, format_types_orig,
2704               sizeof (format_types_orig));
2705       memcpy (&dynamic_format_types[n_format_types], TARGET_FORMAT_TYPES,
2706               TARGET_N_FORMAT_TYPES * sizeof (dynamic_format_types[0]));
2707
2708       format_types = dynamic_format_types;
2709       n_format_types += TARGET_N_FORMAT_TYPES;
2710     }
2711 #endif
2712
2713   if (!decode_format_attr (args, &info, 0))
2714     {
2715       *no_add_attrs = true;
2716       return NULL_TREE;
2717     }
2718
2719   argument = TYPE_ARG_TYPES (type);
2720   if (argument)
2721     {
2722       if (!check_format_string (argument, info.format_num, flags,
2723                                 no_add_attrs))
2724         return NULL_TREE;
2725
2726       if (info.first_arg_num != 0)
2727         {
2728           unsigned HOST_WIDE_INT arg_num = 1;
2729
2730           /* Verify that first_arg_num points to the last arg,
2731              the ...  */
2732           while (argument)
2733             arg_num++, argument = TREE_CHAIN (argument);
2734
2735           if (arg_num != info.first_arg_num)
2736             {
2737               if (!(flags & (int) ATTR_FLAG_BUILT_IN))
2738                 error ("args to be formatted is not %<...%>");
2739               *no_add_attrs = true;
2740               return NULL_TREE;
2741             }
2742         }
2743     }
2744
2745   if (info.format_type == strftime_format_type && info.first_arg_num != 0)
2746     {
2747       error ("strftime formats cannot format arguments");
2748       *no_add_attrs = true;
2749       return NULL_TREE;
2750     }
2751
2752   /* If this is a custom GCC-internal format type, we have to
2753      initialize certain bits a runtime.  */
2754   if (info.format_type == asm_fprintf_format_type
2755       || info.format_type == gcc_gfc_format_type
2756       || info.format_type == gcc_diag_format_type
2757       || info.format_type == gcc_tdiag_format_type
2758       || info.format_type == gcc_cdiag_format_type
2759       || info.format_type == gcc_cxxdiag_format_type)
2760     {
2761       /* Our first time through, we have to make sure that our
2762          format_type data is allocated dynamically and is modifiable.  */
2763       if (!dynamic_format_types)
2764         format_types = dynamic_format_types = (format_kind_info *)
2765           xmemdup (format_types_orig, sizeof (format_types_orig),
2766                    sizeof (format_types_orig));
2767
2768       /* If this is format __asm_fprintf__, we have to initialize
2769          GCC's notion of HOST_WIDE_INT for checking %wd.  */
2770       if (info.format_type == asm_fprintf_format_type)
2771         init_dynamic_asm_fprintf_info ();
2772       /* If this is format __gcc_gfc__, we have to initialize GCC's
2773          notion of 'locus' at runtime for %L.  */
2774       else if (info.format_type == gcc_gfc_format_type)
2775         init_dynamic_gfc_info ();
2776       /* If this is one of the diagnostic attributes, then we have to
2777          initialize 'location_t' and 'tree' at runtime.  */
2778       else if (info.format_type == gcc_diag_format_type
2779                || info.format_type == gcc_tdiag_format_type
2780                || info.format_type == gcc_cdiag_format_type
2781                || info.format_type == gcc_cxxdiag_format_type)
2782         init_dynamic_diag_info ();
2783       else
2784         gcc_unreachable ();
2785     }
2786
2787   return NULL_TREE;
2788 }