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