OSDN Git Service

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