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