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