OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.2.2/] [gcc/] [c-format.c] - Blame information for rev 307

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.