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

Subversion Repositories openrisc_me

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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