1 /* Check calls to formatted I/O functions (-Wformat).
2 Copyright (C) 1992-2019 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
22 #include "coretypes.h"
26 #include "alloc-pool.h"
27 #include "stringpool.h"
30 #include "langhooks.h"
32 #include "diagnostic.h"
33 #include "substring-locations.h"
35 #include "selftest-diagnostic.h"
38 #include "gcc-rich-location.h"
40 /* Handle attributes associated with format checking. */
42 /* This must be in the same order as format_types, except for
43 format_type_error. Target-specific format types do not have
44 matching enum values. */
45 enum format_type
{ printf_format_type
, asm_fprintf_format_type
,
46 gcc_diag_format_type
, gcc_tdiag_format_type
,
47 gcc_cdiag_format_type
,
48 gcc_cxxdiag_format_type
, gcc_gfc_format_type
,
49 gcc_dump_printf_format_type
,
50 gcc_objc_string_format_type
,
51 format_type_error
= -1};
53 struct function_format_info
55 enum format_type format_type
; /* type of format (printf, scanf, etc.) */
56 /* IS_RAW is relevant only for GCC diagnostic format functions.
57 It is set for "raw" formatting functions like pp_printf that
58 are not intended to produce complete diagnostics according to
59 GCC guidelines, and clear for others like error and warning
60 whose format string is checked for proper quoting and spelling. */
62 unsigned HOST_WIDE_INT format_num
; /* number of format argument */
63 unsigned HOST_WIDE_INT first_arg_num
; /* number of first arg (zero for varargs) */
66 /* Initialized in init_dynamic_diag_info. */
67 static GTY(()) tree local_tree_type_node
;
68 static GTY(()) tree local_gimple_ptr_node
;
69 static GTY(()) tree local_cgraph_node_ptr_node
;
70 static GTY(()) tree locus
;
72 static bool decode_format_attr (const_tree
, tree
, tree
, function_format_info
*,
74 static format_type
decode_format_type (const char *, bool * = NULL
);
76 static bool check_format_string (const_tree argument
,
77 unsigned HOST_WIDE_INT format_num
,
78 int flags
, bool *no_add_attrs
,
79 int expected_format_type
);
80 static tree
get_constant (const_tree fntype
, const_tree atname
, tree expr
,
81 int argno
, unsigned HOST_WIDE_INT
*value
,
82 int flags
, bool validated_p
);
83 static const char *convert_format_name_to_system_name (const char *attr_name
);
85 static int first_target_format_type
;
86 static const char *format_name (int format_num
);
87 static int format_flags (int format_num
);
89 /* Emit a warning as per format_warning_va, but construct the substring_loc
90 for the character at offset (CHAR_IDX - 1) within a string constant
91 FORMAT_STRING_CST at FMT_STRING_LOC. */
93 ATTRIBUTE_GCC_DIAG (5,6)
95 format_warning_at_char (location_t fmt_string_loc
, tree format_string_cst
,
96 int char_idx
, int opt
, const char *gmsgid
, ...)
99 va_start (ap
, gmsgid
);
100 tree string_type
= TREE_TYPE (format_string_cst
);
102 /* The callers are of the form:
103 format_warning (format_string_loc, format_string_cst,
104 format_chars - orig_format_chars,
105 where format_chars has already been incremented, so that
106 CHAR_IDX is one character beyond where the warning should
107 be emitted. Fix it. */
110 substring_loc
fmt_loc (fmt_string_loc
, string_type
, char_idx
, char_idx
,
112 format_string_diagnostic_t
diag (fmt_loc
, NULL
, UNKNOWN_LOCATION
, NULL
,
114 bool warned
= diag
.emit_warning_va (opt
, gmsgid
, &ap
);
121 /* Emit a warning as per format_warning_va, but construct the substring_loc
122 for the substring at offset (POS1, POS2 - 1) within a string constant
123 FORMAT_STRING_CST at FMT_STRING_LOC. */
125 ATTRIBUTE_GCC_DIAG (6,7)
127 format_warning_substr (location_t fmt_string_loc
, tree format_string_cst
,
128 int pos1
, int pos2
, int opt
, const char *gmsgid
, ...)
131 va_start (ap
, gmsgid
);
132 tree string_type
= TREE_TYPE (format_string_cst
);
136 substring_loc
fmt_loc (fmt_string_loc
, string_type
, pos1
, pos1
, pos2
);
137 format_string_diagnostic_t
diag (fmt_loc
, NULL
, UNKNOWN_LOCATION
, NULL
,
139 bool warned
= diag
.emit_warning_va (opt
, gmsgid
, &ap
);
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.
154 The function returns true if strref points to any string type valid for the
155 language dialect and target. */
158 valid_format_string_type_p (tree strref
)
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
)));
167 /* Handle a "format_arg" attribute; arguments as in
168 struct attribute_spec.handler. */
170 handle_format_arg_attribute (tree
*node
, tree atname
,
171 tree args
, int flags
, bool *no_add_attrs
)
174 /* Note that TREE_VALUE (args) is changed in place below. */
175 tree
*format_num_expr
= &TREE_VALUE (args
);
176 unsigned HOST_WIDE_INT format_num
= 0;
178 if (tree val
= get_constant (type
, atname
, *format_num_expr
, 0, &format_num
,
180 *format_num_expr
= val
;
183 *no_add_attrs
= true;
187 if (prototype_p (type
))
189 /* The format arg can be any string reference valid for the language and
190 target. We cannot be more specific in this case. */
191 if (!check_format_string (type
, format_num
, flags
, no_add_attrs
, -1))
195 if (!valid_format_string_type_p (TREE_TYPE (type
)))
197 if (!(flags
& (int) ATTR_FLAG_BUILT_IN
))
198 error ("function does not return string type");
199 *no_add_attrs
= true;
206 /* Verify that the format_num argument is actually a string reference suitable,
207 for the language dialect and target (in case the format attribute is in
208 error). When we know the specific reference type expected, this is also
211 check_format_string (const_tree fntype
, unsigned HOST_WIDE_INT format_num
,
212 int flags
, bool *no_add_attrs
, int expected_format_type
)
214 unsigned HOST_WIDE_INT i
;
215 bool is_objc_sref
, is_target_sref
, is_char_ref
;
218 function_args_iterator iter
;
221 FOREACH_FUNCTION_ARGS (fntype
, ref
, iter
)
229 || !valid_format_string_type_p (ref
))
231 if (!(flags
& (int) ATTR_FLAG_BUILT_IN
))
232 error ("format string argument is not a string type");
233 *no_add_attrs
= true;
237 /* We only know that we want a suitable string reference. */
238 if (expected_format_type
< 0)
241 /* Now check that the arg matches the expected type. */
243 (TYPE_MAIN_VARIANT (TREE_TYPE (ref
)) == char_type_node
);
245 fmt_flags
= format_flags (expected_format_type
);
246 is_objc_sref
= is_target_sref
= false;
248 is_objc_sref
= objc_string_ref_type_p (ref
);
250 if (!(fmt_flags
& FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL
))
253 return true; /* OK, we expected a char and found one. */
256 /* We expected a char but found an extended string type. */
258 error ("found a %qs reference but the format argument should"
259 " be a string", format_name (gcc_objc_string_format_type
));
261 error ("found a %qT but the format argument should be a string",
263 *no_add_attrs
= true;
268 /* We expect a string object type as the format arg. */
271 error ("format argument should be a %qs reference but"
272 " a string was found", format_name (expected_format_type
));
273 *no_add_attrs
= true;
277 /* We will assert that objective-c will support either its own string type
278 or the target-supplied variant. */
280 is_target_sref
= (*targetcm
.string_object_ref_type_p
) ((const_tree
) ref
);
282 if (expected_format_type
== (int) gcc_objc_string_format_type
283 && (is_objc_sref
|| is_target_sref
))
286 /* We will allow a target string ref to match only itself. */
287 if (first_target_format_type
288 && expected_format_type
>= first_target_format_type
293 error ("format argument should be a %qs reference",
294 format_name (expected_format_type
));
295 *no_add_attrs
= true;
302 /* Under the control of FLAGS, verify EXPR is a valid constant that
303 refers to a positional argument ARGNO having a string type (char*
304 or, for targets like Darwin, a pointer to struct CFString) to
305 a function type FNTYPE declared with attribute ATNAME.
306 If valid, store the constant's integer value in *VALUE and return
308 If VALIDATED_P is true assert the validation is successful.
309 Returns the converted constant value on success, null otherwise. */
312 get_constant (const_tree fntype
, const_tree atname
, tree expr
, int argno
,
313 unsigned HOST_WIDE_INT
*value
, int flags
, bool validated_p
)
315 /* Require the referenced argument to have a string type. For targets
316 like Darwin, also accept pointers to struct CFString. */
317 if (tree val
= positional_argument (fntype
, atname
, expr
, STRING_CST
,
320 *value
= TREE_INT_CST_LOW (val
);
324 gcc_assert (!validated_p
);
328 /* Decode the arguments to a "format" attribute into a
329 function_format_info structure. It is already known that the list
330 is of the right length. If VALIDATED_P is true, then these
331 attributes have already been validated and must not be erroneous;
332 if false, it will give an error message. Returns true if the
333 attributes are successfully decoded, false otherwise. */
336 decode_format_attr (const_tree fntype
, tree atname
, tree args
,
337 function_format_info
*info
, bool validated_p
)
339 tree format_type_id
= TREE_VALUE (args
);
340 /* Note that TREE_VALUE (args) is changed in place below. Ditto
341 for the value of the next element on the list. */
342 tree
*format_num_expr
= &TREE_VALUE (TREE_CHAIN (args
));
343 tree
*first_arg_num_expr
= &TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args
)));
345 if (TREE_CODE (format_type_id
) != IDENTIFIER_NODE
)
347 gcc_assert (!validated_p
);
348 error ("unrecognized format specifier");
353 const char *p
= IDENTIFIER_POINTER (format_type_id
);
355 info
->format_type
= decode_format_type (p
, &info
->is_raw
);
357 if (!c_dialect_objc ()
358 && info
->format_type
== gcc_objc_string_format_type
)
360 gcc_assert (!validated_p
);
361 warning (OPT_Wformat_
, "%qE is only allowed in Objective-C dialects",
363 info
->format_type
= format_type_error
;
367 if (info
->format_type
== format_type_error
)
369 gcc_assert (!validated_p
);
370 warning (OPT_Wformat_
, "%qE is an unrecognized format function type",
376 if (tree val
= get_constant (fntype
, atname
, *format_num_expr
,
377 2, &info
->format_num
, 0, validated_p
))
378 *format_num_expr
= val
;
382 if (tree val
= get_constant (fntype
, atname
, *first_arg_num_expr
,
383 3, &info
->first_arg_num
,
384 (POSARG_ZERO
| POSARG_ELLIPSIS
), validated_p
))
385 *first_arg_num_expr
= val
;
389 if (info
->first_arg_num
!= 0 && info
->first_arg_num
<= info
->format_num
)
391 gcc_assert (!validated_p
);
392 error ("format string argument follows the arguments to be formatted");
399 /* Check a call to a format function against a parameter list. */
401 /* The C standard version C++ is treated as equivalent to
402 or inheriting from, for the purpose of format features supported. */
403 #define CPLUSPLUS_STD_VER (cxx_dialect < cxx11 ? STD_C94 : STD_C99)
404 /* The C standard version we are checking formats against when pedantic. */
405 #define C_STD_VER ((int) (c_dialect_cxx () \
406 ? CPLUSPLUS_STD_VER \
409 : (flag_isoc94 ? STD_C94 : STD_C89))))
410 /* The name to give to the standard version we are warning about when
411 pedantic. FEATURE_VER is the version in which the feature warned out
412 appeared, which is higher than C_STD_VER. */
413 #define C_STD_NAME(FEATURE_VER) (c_dialect_cxx () \
414 ? (cxx_dialect < cxx11 ? "ISO C++98" \
416 : ((FEATURE_VER) == STD_EXT \
419 /* Adjust a C standard version, which may be STD_C9L, to account for
420 -Wno-long-long. Returns other standard versions unchanged. */
421 #define ADJ_STD(VER) ((int) ((VER) == STD_C9L \
422 ? (warn_long_long ? STD_C99 : STD_C89) \
425 /* Enum describing the kind of specifiers present in the format and
426 requiring an argument. */
427 enum format_specifier_kind
{
430 CF_KIND_FIELD_PRECISION
433 static const char *kind_descriptions
[] = {
435 N_("field width specifier"),
436 N_("field precision specifier")
439 /* Structure describing details of a type expected in format checking,
440 and the type to check against it. */
441 struct format_wanted_type
443 /* The type wanted. */
445 /* The name of this type to use in diagnostics. */
446 const char *wanted_type_name
;
447 /* Should be type checked just for scalar width identity. */
448 int scalar_identity_flag
;
449 /* The level of indirection through pointers at which this type occurs. */
451 /* Whether, when pointer_count is 1, to allow any character type when
452 pedantic, rather than just the character or void type specified. */
453 int char_lenient_flag
;
454 /* Whether the argument, dereferenced once, is written into and so the
455 argument must not be a pointer to a const-qualified type. */
457 /* Whether the argument, dereferenced once, is read from and so
458 must not be a NULL pointer. */
459 int reading_from_flag
;
460 /* The kind of specifier that this type is used for. */
461 enum format_specifier_kind kind
;
462 /* The starting character of the specifier. This never includes the
463 initial percent sign. */
464 const char *format_start
;
465 /* The length of the specifier. */
467 /* The actual parameter to check against the wanted type. */
469 /* The argument number of that parameter. */
471 /* The offset location of this argument with respect to the format
473 unsigned int offset_loc
;
474 /* The next type to check for this format conversion, or NULL if none. */
475 struct format_wanted_type
*next
;
478 /* Convenience macro for format_length_info meaning unused. */
479 #define NO_FMT NULL, FMT_LEN_none, STD_C89
481 static const format_length_info printf_length_specs
[] =
483 { "h", FMT_LEN_h
, STD_C89
, "hh", FMT_LEN_hh
, STD_C99
, 0 },
484 { "l", FMT_LEN_l
, STD_C89
, "ll", FMT_LEN_ll
, STD_C9L
, 0 },
485 { "q", FMT_LEN_ll
, STD_EXT
, NO_FMT
, 0 },
486 { "L", FMT_LEN_L
, STD_C89
, NO_FMT
, 0 },
487 { "z", FMT_LEN_z
, STD_C99
, NO_FMT
, 0 },
488 { "Z", FMT_LEN_z
, STD_EXT
, NO_FMT
, 0 },
489 { "t", FMT_LEN_t
, STD_C99
, NO_FMT
, 0 },
490 { "j", FMT_LEN_j
, STD_C99
, NO_FMT
, 0 },
491 { "H", FMT_LEN_H
, STD_EXT
, NO_FMT
, 0 },
492 { "D", FMT_LEN_D
, STD_EXT
, "DD", FMT_LEN_DD
, STD_EXT
, 0 },
493 { NO_FMT
, NO_FMT
, 0 }
496 /* Length specifiers valid for asm_fprintf. */
497 static const format_length_info asm_fprintf_length_specs
[] =
499 { "l", FMT_LEN_l
, STD_C89
, "ll", FMT_LEN_ll
, STD_C89
, 0 },
500 { "w", FMT_LEN_none
, STD_C89
, NO_FMT
, 0 },
501 { NO_FMT
, NO_FMT
, 0 }
504 /* Length specifiers valid for GCC diagnostics. */
505 static const format_length_info gcc_diag_length_specs
[] =
507 { "l", FMT_LEN_l
, STD_C89
, "ll", FMT_LEN_ll
, STD_C89
, 0 },
508 { "w", FMT_LEN_none
, STD_C89
, NO_FMT
, 0 },
509 { NO_FMT
, NO_FMT
, 0 }
512 /* The custom diagnostics all accept the same length specifiers. */
513 #define gcc_tdiag_length_specs gcc_diag_length_specs
514 #define gcc_cdiag_length_specs gcc_diag_length_specs
515 #define gcc_cxxdiag_length_specs gcc_diag_length_specs
516 #define gcc_dump_printf_length_specs gcc_diag_length_specs
518 /* This differs from printf_length_specs only in that "Z" is not accepted. */
519 static const format_length_info scanf_length_specs
[] =
521 { "h", FMT_LEN_h
, STD_C89
, "hh", FMT_LEN_hh
, STD_C99
, 0 },
522 { "l", FMT_LEN_l
, STD_C89
, "ll", FMT_LEN_ll
, STD_C9L
, 0 },
523 { "q", FMT_LEN_ll
, STD_EXT
, NO_FMT
, 0 },
524 { "L", FMT_LEN_L
, STD_C89
, NO_FMT
, 0 },
525 { "z", FMT_LEN_z
, STD_C99
, NO_FMT
, 0 },
526 { "t", FMT_LEN_t
, STD_C99
, NO_FMT
, 0 },
527 { "j", FMT_LEN_j
, STD_C99
, NO_FMT
, 0 },
528 { "H", FMT_LEN_H
, STD_EXT
, NO_FMT
, 0 },
529 { "D", FMT_LEN_D
, STD_EXT
, "DD", FMT_LEN_DD
, STD_EXT
, 0 },
530 { NO_FMT
, NO_FMT
, 0 }
534 /* All tables for strfmon use STD_C89 everywhere, since -pedantic warnings
535 make no sense for a format type not part of any C standard version. */
536 static const format_length_info strfmon_length_specs
[] =
538 /* A GNU extension. */
539 { "L", FMT_LEN_L
, STD_C89
, NO_FMT
, 0 },
540 { NO_FMT
, NO_FMT
, 0 }
544 /* For now, the Fortran front-end routines only use l as length modifier. */
545 static const format_length_info gcc_gfc_length_specs
[] =
547 { "l", FMT_LEN_l
, STD_C89
, NO_FMT
, 0 },
548 { NO_FMT
, NO_FMT
, 0 }
552 static const format_flag_spec printf_flag_specs
[] =
554 { ' ', 0, 0, 0, N_("' ' flag"), N_("the ' ' printf flag"), STD_C89
},
555 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89
},
556 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89
},
557 { '0', 0, 0, 0, N_("'0' flag"), N_("the '0' printf flag"), STD_C89
},
558 { '-', 0, 0, 0, N_("'-' flag"), N_("the '-' printf flag"), STD_C89
},
559 { '\'', 0, 0, 0, N_("''' flag"), N_("the ''' printf flag"), STD_EXT
},
560 { 'I', 0, 0, 0, N_("'I' flag"), N_("the 'I' printf flag"), STD_EXT
},
561 { 'w', 0, 0, 0, N_("field width"), N_("field width in printf format"), STD_C89
},
562 { 'p', 0, 0, 0, N_("precision"), N_("precision in printf format"), STD_C89
},
563 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89
},
564 { 0, 0, 0, 0, NULL
, NULL
, STD_C89
}
568 static const format_flag_pair printf_flag_pairs
[] =
572 { '0', 'p', 1, 'i' },
576 static const format_flag_spec asm_fprintf_flag_specs
[] =
578 { ' ', 0, 0, 0, N_("' ' flag"), N_("the ' ' printf flag"), STD_C89
},
579 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89
},
580 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89
},
581 { '0', 0, 0, 0, N_("'0' flag"), N_("the '0' printf flag"), STD_C89
},
582 { '-', 0, 0, 0, N_("'-' flag"), N_("the '-' printf flag"), STD_C89
},
583 { 'w', 0, 0, 0, N_("field width"), N_("field width in printf format"), STD_C89
},
584 { 'p', 0, 0, 0, N_("precision"), N_("precision in printf format"), STD_C89
},
585 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89
},
586 { 0, 0, 0, 0, NULL
, NULL
, STD_C89
}
589 static const format_flag_pair asm_fprintf_flag_pairs
[] =
593 { '0', 'p', 1, 'i' },
597 static const format_flag_pair gcc_diag_flag_pairs
[] =
602 #define gcc_tdiag_flag_pairs gcc_diag_flag_pairs
603 #define gcc_cdiag_flag_pairs gcc_diag_flag_pairs
604 #define gcc_cxxdiag_flag_pairs gcc_diag_flag_pairs
605 #define gcc_gfc_flag_pairs gcc_diag_flag_pairs
606 #define gcc_dump_printf_flag_pairs gcc_diag_flag_pairs
608 static const format_flag_spec gcc_diag_flag_specs
[] =
610 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89
},
611 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89
},
612 { 'q', 0, 0, 1, N_("'q' flag"), N_("the 'q' diagnostic flag"), STD_C89
},
613 { 'p', 0, 0, 0, N_("precision"), N_("precision in printf format"), STD_C89
},
614 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89
},
615 { 0, 0, 0, 0, NULL
, NULL
, STD_C89
}
618 #define gcc_tdiag_flag_specs gcc_diag_flag_specs
619 #define gcc_cdiag_flag_specs gcc_diag_flag_specs
620 #define gcc_cxxdiag_flag_specs gcc_diag_flag_specs
621 #define gcc_gfc_flag_specs gcc_diag_flag_specs
622 #define gcc_dump_printf_flag_specs gcc_diag_flag_specs
624 static const format_flag_spec scanf_flag_specs
[] =
626 { '*', 0, 0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89
},
627 { 'a', 0, 0, 0, N_("'a' flag"), N_("the 'a' scanf flag"), STD_EXT
},
628 { 'm', 0, 0, 0, N_("'m' flag"), N_("the 'm' scanf flag"), STD_EXT
},
629 { 'w', 0, 0, 0, N_("field width"), N_("field width in scanf format"), STD_C89
},
630 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in scanf format"), STD_C89
},
631 { '\'', 0, 0, 0, N_("''' flag"), N_("the ''' scanf flag"), STD_EXT
},
632 { 'I', 0, 0, 0, N_("'I' flag"), N_("the 'I' scanf flag"), STD_EXT
},
633 { 0, 0, 0, 0, NULL
, NULL
, STD_C89
}
637 static const format_flag_pair scanf_flag_pairs
[] =
645 static const format_flag_spec strftime_flag_specs
[] =
647 { '_', 0, 0, 0, N_("'_' flag"), N_("the '_' strftime flag"), STD_EXT
},
648 { '-', 0, 0, 0, N_("'-' flag"), N_("the '-' strftime flag"), STD_EXT
},
649 { '0', 0, 0, 0, N_("'0' flag"), N_("the '0' strftime flag"), STD_EXT
},
650 { '^', 0, 0, 0, N_("'^' flag"), N_("the '^' strftime flag"), STD_EXT
},
651 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' strftime flag"), STD_EXT
},
652 { 'w', 0, 0, 0, N_("field width"), N_("field width in strftime format"), STD_EXT
},
653 { 'E', 0, 0, 0, N_("'E' modifier"), N_("the 'E' strftime modifier"), STD_C99
},
654 { 'O', 0, 0, 0, N_("'O' modifier"), N_("the 'O' strftime modifier"), STD_C99
},
655 { 'O', 'o', 0, 0, NULL
, N_("the 'O' modifier"), STD_EXT
},
656 { 0, 0, 0, 0, NULL
, NULL
, STD_C89
}
660 static const format_flag_pair strftime_flag_pairs
[] =
671 static const format_flag_spec strfmon_flag_specs
[] =
673 { '=', 0, 1, 0, N_("fill character"), N_("fill character in strfmon format"), STD_C89
},
674 { '^', 0, 0, 0, N_("'^' flag"), N_("the '^' strfmon flag"), STD_C89
},
675 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' strfmon flag"), STD_C89
},
676 { '(', 0, 0, 0, N_("'(' flag"), N_("the '(' strfmon flag"), STD_C89
},
677 { '!', 0, 0, 0, N_("'!' flag"), N_("the '!' strfmon flag"), STD_C89
},
678 { '-', 0, 0, 0, N_("'-' flag"), N_("the '-' strfmon flag"), STD_C89
},
679 { 'w', 0, 0, 0, N_("field width"), N_("field width in strfmon format"), STD_C89
},
680 { '#', 0, 0, 0, N_("left precision"), N_("left precision in strfmon format"), STD_C89
},
681 { 'p', 0, 0, 0, N_("right precision"), N_("right precision in strfmon format"), STD_C89
},
682 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in strfmon format"), STD_C89
},
683 { 0, 0, 0, 0, NULL
, NULL
, STD_C89
}
686 static const format_flag_pair strfmon_flag_pairs
[] =
693 static const format_char_info print_char_table
[] =
695 /* C89 conversion specifiers. */
696 { "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
},
697 { "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
},
698 { "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
},
699 { "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
},
700 { "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
},
701 { "c", 0, STD_C89
, { T89_I
, BADLEN
, BADLEN
, T94_WI
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "-w", "", NULL
},
702 { "s", 1, STD_C89
, { T89_C
, BADLEN
, BADLEN
, T94_W
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "-wp", "cR", NULL
},
703 { "p", 1, STD_C89
, { T89_V
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "-w", "c", NULL
},
704 { "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
},
705 /* C99 conversion specifiers. */
706 { "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
},
707 { "aA", 0, STD_C99
, { T99_D
, BADLEN
, BADLEN
, T99_D
, BADLEN
, T99_LD
, BADLEN
, BADLEN
, BADLEN
, TEX_D32
, TEX_D64
, TEX_D128
}, "-wp0 +#", "", NULL
},
708 /* X/Open conversion specifiers. */
709 { "C", 0, STD_EXT
, { TEX_WI
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "-w", "", NULL
},
710 { "S", 1, STD_EXT
, { TEX_W
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "-wp", "R", NULL
},
711 /* GNU conversion specifiers. */
712 { "m", 0, STD_EXT
, { T89_V
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "-wp", "", NULL
},
713 { NULL
, 0, STD_C89
, NOLENGTHS
, NULL
, NULL
, NULL
}
716 static const format_char_info asm_fprintf_char_table
[] =
718 /* C89 conversion specifiers. */
719 { "di", 0, STD_C89
, { T89_I
, BADLEN
, BADLEN
, T89_L
, T9L_LL
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "-wp0 +", "i", NULL
},
720 { "oxX", 0, STD_C89
, { T89_UI
, BADLEN
, BADLEN
, T89_UL
, T9L_ULL
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "-wp0#", "i", NULL
},
721 { "u", 0, STD_C89
, { T89_UI
, BADLEN
, BADLEN
, T89_UL
, T9L_ULL
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "-wp0", "i", NULL
},
722 { "c", 0, STD_C89
, { T89_I
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "-w", "", NULL
},
723 { "s", 1, STD_C89
, { T89_C
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "-wp", "cR", NULL
},
725 /* asm_fprintf conversion specifiers. */
726 { "O", 0, STD_C89
, NOARGUMENTS
, "", "", NULL
},
727 { "R", 0, STD_C89
, NOARGUMENTS
, "", "", NULL
},
728 { "I", 0, STD_C89
, NOARGUMENTS
, "", "", NULL
},
729 { "L", 0, STD_C89
, NOARGUMENTS
, "", "", NULL
},
730 { "U", 0, STD_C89
, NOARGUMENTS
, "", "", NULL
},
731 { "r", 0, STD_C89
, { T89_I
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "", "", NULL
},
732 { "z", 0, STD_C89
, NOARGUMENTS
, "", "", NULL
},
733 { "@", 0, STD_C89
, NOARGUMENTS
, "", "", NULL
},
734 { NULL
, 0, STD_C89
, NOLENGTHS
, NULL
, NULL
, NULL
}
737 /* GCC-specific format_char_info arrays. */
739 /* The conversion specifiers implemented within pp_format, and thus supported
740 by all pretty_printer instances within GCC. */
742 #define PP_FORMAT_CHAR_TABLE \
743 { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \
744 { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \
745 { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \
746 { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \
747 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL }, \
748 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, \
749 { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "//cR", NULL }, \
750 { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL }, \
751 { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL }, \
752 { "'" , 0, STD_C89, NOARGUMENTS, "", "", NULL }, \
753 { "R", 0, STD_C89, NOARGUMENTS, "", "\\", NULL }, \
754 { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, \
755 { "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_diag_char_table[0] }
757 static const format_char_info gcc_diag_char_table
[] =
759 /* The conversion specifiers implemented within pp_format. */
760 PP_FORMAT_CHAR_TABLE
,
762 { NULL
, 0, STD_C89
, NOLENGTHS
, NULL
, NULL
, NULL
}
765 static const format_char_info gcc_tdiag_char_table
[] =
767 /* The conversion specifiers implemented within pp_format. */
768 PP_FORMAT_CHAR_TABLE
,
770 /* Custom conversion specifiers implemented by default_tree_printer. */
772 /* These will require a "tree" at runtime. */
773 { "DFTV", 1, STD_C89
, { T89_T
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "q+", "'", NULL
},
774 { "E", 1, STD_C89
, { T89_T
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "q+", "", NULL
},
775 { "K", 1, STD_C89
, { T89_T
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "", "\"", NULL
},
777 /* G requires a "gimple*" argument at runtime. */
778 { "G", 1, STD_C89
, { T89_G
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "", "\"", NULL
},
780 { NULL
, 0, STD_C89
, NOLENGTHS
, NULL
, NULL
, NULL
}
783 static const format_char_info gcc_cdiag_char_table
[] =
785 /* The conversion specifiers implemented within pp_format. */
786 PP_FORMAT_CHAR_TABLE
,
788 /* Custom conversion specifiers implemented by c_tree_printer. */
790 /* These will require a "tree" at runtime. */
791 { "DFTV", 1, STD_C89
, { T89_T
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "q+", "'", NULL
},
792 { "E", 1, STD_C89
, { T89_T
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "q+", "", NULL
},
793 { "K", 1, STD_C89
, { T89_T
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "", "\"", NULL
},
795 /* G requires a "gimple*" argument at runtime. */
796 { "G", 1, STD_C89
, { T89_G
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "", "\"", NULL
},
798 { "v", 0, STD_C89
, { T89_I
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "q#", "", NULL
},
800 { NULL
, 0, STD_C89
, NOLENGTHS
, NULL
, NULL
, NULL
}
803 static const format_char_info gcc_cxxdiag_char_table
[] =
805 /* The conversion specifiers implemented within pp_format. */
806 PP_FORMAT_CHAR_TABLE
,
808 /* Custom conversion specifiers implemented by cp_printer. */
810 /* These will require a "tree" at runtime. */
811 { "ADFHISTVX",1,STD_C89
,{ T89_T
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "q+#", "'", NULL
},
812 { "E", 1,STD_C89
,{ T89_T
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "q+#", "", NULL
},
813 { "K", 1, STD_C89
,{ T89_T
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "", "\"", NULL
},
815 /* G requires a "gimple*" argument at runtime. */
816 { "G", 1, STD_C89
,{ T89_G
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "", "\"", NULL
},
818 /* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.) */
819 { "CLOPQ",0,STD_C89
, { T89_I
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "q", "", NULL
},
821 { NULL
, 0, STD_C89
, NOLENGTHS
, NULL
, NULL
, NULL
}
824 static const format_char_info gcc_gfc_char_table
[] =
826 /* C89 conversion specifiers. */
827 { "di", 0, STD_C89
, { T89_I
, BADLEN
, BADLEN
, T89_L
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "q", "", NULL
},
828 { "u", 0, STD_C89
, { T89_UI
, BADLEN
, BADLEN
, T89_UL
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "q", "", NULL
},
829 { "c", 0, STD_C89
, { T89_I
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "q", "", NULL
},
830 { "s", 1, STD_C89
, { T89_C
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "q", "cR", NULL
},
832 /* gfc conversion specifiers. */
834 { "C", 0, STD_C89
, NOARGUMENTS
, "", "", NULL
},
836 /* This will require a "locus" at runtime. */
837 { "L", 0, STD_C89
, { T89_V
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "", "R", NULL
},
839 /* These will require nothing. */
840 { "<>",0, STD_C89
, NOARGUMENTS
, "", "", NULL
},
841 { NULL
, 0, STD_C89
, NOLENGTHS
, NULL
, NULL
, NULL
}
844 static const format_char_info gcc_dump_printf_char_table
[] =
846 /* The conversion specifiers implemented within pp_format. */
847 PP_FORMAT_CHAR_TABLE
,
849 /* Custom conversion specifiers implemented by dump_pretty_printer. */
851 /* E and G require a "gimple *" argument at runtime. */
852 { "EG", 1, STD_C89
, { T89_G
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "", "\"", NULL
},
854 /* C requires a "cgraph_node *" argument at runtime. */
855 { "C", 1, STD_C89
, { T_CGRAPH_NODE
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "", "\"", NULL
},
857 /* T requires a "tree" at runtime. */
858 { "T", 1, STD_C89
, { T89_T
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "", "\"", NULL
},
860 /* %f requires a "double"; it doesn't support modifiers. */
861 { "f", 0, STD_C89
, { T89_D
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "", "\"", NULL
},
863 { NULL
, 0, STD_C89
, NOLENGTHS
, NULL
, NULL
, NULL
}
866 static const format_char_info scan_char_table
[] =
868 /* C89 conversion specifiers. */
869 { "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
},
870 { "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
},
871 { "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
},
872 { "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
},
873 { "c", 1, STD_C89
, { T89_C
, BADLEN
, BADLEN
, T94_W
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "*mw", "cW", NULL
},
874 { "s", 1, STD_C89
, { T89_C
, BADLEN
, BADLEN
, T94_W
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "*amw", "cW", NULL
},
875 { "[", 1, STD_C89
, { T89_C
, BADLEN
, BADLEN
, T94_W
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "*amw", "cW[", NULL
},
876 { "p", 2, STD_C89
, { T89_V
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "*w", "W", NULL
},
877 { "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
},
878 /* C99 conversion specifiers. */
879 { "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
},
880 { "aA", 1, STD_C99
, { T99_F
, BADLEN
, BADLEN
, T99_D
, BADLEN
, T99_LD
, BADLEN
, BADLEN
, BADLEN
, TEX_D32
, TEX_D64
, TEX_D128
}, "*w'", "W", NULL
},
881 /* X/Open conversion specifiers. */
882 { "C", 1, STD_EXT
, { TEX_W
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "*mw", "W", NULL
},
883 { "S", 1, STD_EXT
, { TEX_W
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "*amw", "W", NULL
},
884 { NULL
, 0, STD_C89
, NOLENGTHS
, NULL
, NULL
, NULL
}
887 static const format_char_info time_char_table
[] =
889 /* C89 conversion specifiers. */
890 { "ABZab", 0, STD_C89
, NOLENGTHS
, "^#", "", NULL
},
891 { "cx", 0, STD_C89
, NOLENGTHS
, "E", "3", NULL
},
892 { "HIMSUWdmw", 0, STD_C89
, NOLENGTHS
, "-_0Ow", "", NULL
},
893 { "j", 0, STD_C89
, NOLENGTHS
, "-_0Ow", "o", NULL
},
894 { "p", 0, STD_C89
, NOLENGTHS
, "#", "", NULL
},
895 { "X", 0, STD_C89
, NOLENGTHS
, "E", "", NULL
},
896 { "y", 0, STD_C89
, NOLENGTHS
, "EO-_0w", "4", NULL
},
897 { "Y", 0, STD_C89
, NOLENGTHS
, "-_0EOw", "o", NULL
},
898 { "%", 0, STD_C89
, NOLENGTHS
, "", "", NULL
},
899 /* C99 conversion specifiers. */
900 { "C", 0, STD_C99
, NOLENGTHS
, "-_0EOw", "o", NULL
},
901 { "D", 0, STD_C99
, NOLENGTHS
, "", "2", NULL
},
902 { "eVu", 0, STD_C99
, NOLENGTHS
, "-_0Ow", "", NULL
},
903 { "FRTnrt", 0, STD_C99
, NOLENGTHS
, "", "", NULL
},
904 { "g", 0, STD_C99
, NOLENGTHS
, "O-_0w", "2o", NULL
},
905 { "G", 0, STD_C99
, NOLENGTHS
, "-_0Ow", "o", NULL
},
906 { "h", 0, STD_C99
, NOLENGTHS
, "^#", "", NULL
},
907 { "z", 0, STD_C99
, NOLENGTHS
, "O", "o", NULL
},
908 /* GNU conversion specifiers. */
909 { "kls", 0, STD_EXT
, NOLENGTHS
, "-_0Ow", "", NULL
},
910 { "P", 0, STD_EXT
, NOLENGTHS
, "", "", NULL
},
911 { NULL
, 0, STD_C89
, NOLENGTHS
, NULL
, NULL
, NULL
}
914 static const format_char_info monetary_char_table
[] =
916 { "in", 0, STD_C89
, { T89_D
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, T89_LD
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
, BADLEN
}, "=^+(!-w#p", "", NULL
},
917 { NULL
, 0, STD_C89
, NOLENGTHS
, NULL
, NULL
, NULL
}
920 /* This must be in the same order as enum format_type. */
921 static const format_kind_info format_types_orig
[] =
923 { "gnu_printf", printf_length_specs
, print_char_table
, " +#0-'I", NULL
,
924 printf_flag_specs
, printf_flag_pairs
,
925 FMT_FLAG_ARG_CONVERT
|FMT_FLAG_DOLLAR_MULTIPLE
|FMT_FLAG_USE_DOLLAR
|FMT_FLAG_EMPTY_PREC_OK
,
926 'w', 0, 'p', 0, 'L', 0,
927 &integer_type_node
, &integer_type_node
929 { "asm_fprintf", asm_fprintf_length_specs
, asm_fprintf_char_table
, " +#0-", NULL
,
930 asm_fprintf_flag_specs
, asm_fprintf_flag_pairs
,
931 FMT_FLAG_ARG_CONVERT
|FMT_FLAG_EMPTY_PREC_OK
,
932 'w', 0, 'p', 0, 'L', 0,
935 { "gcc_diag", gcc_diag_length_specs
, gcc_diag_char_table
, "q+#", NULL
,
936 gcc_diag_flag_specs
, gcc_diag_flag_pairs
,
937 FMT_FLAG_ARG_CONVERT
,
938 0, 0, 'p', 0, 'L', 0,
939 NULL
, &integer_type_node
941 { "gcc_tdiag", gcc_tdiag_length_specs
, gcc_tdiag_char_table
, "q+#", NULL
,
942 gcc_tdiag_flag_specs
, gcc_tdiag_flag_pairs
,
943 FMT_FLAG_ARG_CONVERT
,
944 0, 0, 'p', 0, 'L', 0,
945 NULL
, &integer_type_node
947 { "gcc_cdiag", gcc_cdiag_length_specs
, gcc_cdiag_char_table
, "q+#", NULL
,
948 gcc_cdiag_flag_specs
, gcc_cdiag_flag_pairs
,
949 FMT_FLAG_ARG_CONVERT
,
950 0, 0, 'p', 0, 'L', 0,
951 NULL
, &integer_type_node
953 { "gcc_cxxdiag", gcc_cxxdiag_length_specs
, gcc_cxxdiag_char_table
, "q+#", NULL
,
954 gcc_cxxdiag_flag_specs
, gcc_cxxdiag_flag_pairs
,
955 FMT_FLAG_ARG_CONVERT
,
956 0, 0, 'p', 0, 'L', 0,
957 NULL
, &integer_type_node
959 { "gcc_gfc", gcc_gfc_length_specs
, gcc_gfc_char_table
, "q+#", NULL
,
960 gcc_gfc_flag_specs
, gcc_gfc_flag_pairs
,
961 FMT_FLAG_ARG_CONVERT
,
965 { "gcc_dump_printf", gcc_dump_printf_length_specs
,
966 gcc_dump_printf_char_table
, "q+#", NULL
,
967 gcc_dump_printf_flag_specs
, gcc_dump_printf_flag_pairs
,
968 FMT_FLAG_ARG_CONVERT
,
969 0, 0, 'p', 0, 'L', 0,
970 NULL
, &integer_type_node
972 { "NSString", NULL
, NULL
, NULL
, NULL
,
974 FMT_FLAG_ARG_CONVERT
|FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL
, 0, 0, 0, 0, 0, 0,
977 { "gnu_scanf", scanf_length_specs
, scan_char_table
, "*'I", NULL
,
978 scanf_flag_specs
, scanf_flag_pairs
,
979 FMT_FLAG_ARG_CONVERT
|FMT_FLAG_SCANF_A_KLUDGE
|FMT_FLAG_USE_DOLLAR
|FMT_FLAG_ZERO_WIDTH_BAD
|FMT_FLAG_DOLLAR_GAP_POINTER_OK
,
980 'w', 0, 0, '*', 'L', 'm',
983 { "gnu_strftime", NULL
, time_char_table
, "_-0^#", "EO",
984 strftime_flag_specs
, strftime_flag_pairs
,
985 FMT_FLAG_FANCY_PERCENT_OK
, 'w', 0, 0, 0, 0, 0,
988 { "gnu_strfmon", strfmon_length_specs
, monetary_char_table
, "=^+(!-", NULL
,
989 strfmon_flag_specs
, strfmon_flag_pairs
,
990 FMT_FLAG_ARG_CONVERT
, 'w', '#', 'p', 0, 'L', 0,
995 /* This layer of indirection allows GCC to reassign format_types with
996 new data if necessary, while still allowing the original data to be
998 static const format_kind_info
*format_types
= format_types_orig
;
999 /* We can modify this one. We also add target-specific format types
1000 to the end of the array. */
1001 static format_kind_info
*dynamic_format_types
;
1003 static int n_format_types
= ARRAY_SIZE (format_types_orig
);
1005 /* Structure detailing the results of checking a format function call
1006 where the format expression may be a conditional expression with
1007 many leaves resulting from nested conditional expressions. */
1008 struct format_check_results
1010 /* Number of leaves of the format argument that could not be checked
1011 as they were not string literals. */
1012 int number_non_literal
;
1013 /* Number of leaves of the format argument that were null pointers or
1014 string literals, but had extra format arguments. */
1015 int number_extra_args
;
1016 location_t extra_arg_loc
;
1017 /* Number of leaves of the format argument that were null pointers or
1018 string literals, but had extra format arguments and used $ operand
1020 int number_dollar_extra_args
;
1021 /* Number of leaves of the format argument that were wide string
1024 /* Number of leaves of the format argument that are not array of "char". */
1025 int number_non_char
;
1026 /* Number of leaves of the format argument that were empty strings. */
1028 /* Number of leaves of the format argument that were unterminated
1030 int number_unterminated
;
1031 /* Number of leaves of the format argument that were not counted above. */
1033 /* Location of the format string. */
1034 location_t format_string_loc
;
1037 struct format_check_context
1039 format_check_results
*res
;
1040 function_format_info
*info
;
1042 vec
<location_t
> *arglocs
;
1045 /* Return the format name (as specified in the original table) for the format
1046 type indicated by format_num. */
1048 format_name (int format_num
)
1050 if (format_num
>= 0 && format_num
< n_format_types
)
1051 return format_types
[format_num
].name
;
1055 /* Return the format flags (as specified in the original table) for the format
1056 type indicated by format_num. */
1058 format_flags (int format_num
)
1060 if (format_num
>= 0 && format_num
< n_format_types
)
1061 return format_types
[format_num
].flags
;
1065 static void check_format_info (function_format_info
*, tree
,
1067 static void check_format_arg (void *, tree
, unsigned HOST_WIDE_INT
);
1068 static void check_format_info_main (format_check_results
*,
1069 function_format_info
*, const char *,
1072 unsigned HOST_WIDE_INT
,
1073 object_allocator
<format_wanted_type
> &,
1076 static void init_dollar_format_checking (int, tree
);
1077 static int maybe_read_dollar_number (const char **, int,
1078 tree
, tree
*, const format_kind_info
*);
1079 static bool avoid_dollar_number (const char *);
1080 static void finish_dollar_format_checking (format_check_results
*, int);
1082 static const format_flag_spec
*get_flag_spec (const format_flag_spec
*,
1085 static void check_format_types (const substring_loc
&fmt_loc
,
1086 format_wanted_type
*,
1087 const format_kind_info
*fki
,
1088 int offset_to_type_start
,
1089 char conversion_char
,
1090 vec
<location_t
> *arglocs
);
1091 static void format_type_warning (const substring_loc
&fmt_loc
,
1092 location_t param_loc
,
1093 format_wanted_type
*, tree
,
1095 const format_kind_info
*fki
,
1096 int offset_to_type_start
,
1097 char conversion_char
);
1099 /* Decode a format type from a string, returning the type, or
1100 format_type_error if not valid, in which case the caller should
1101 print an error message. On success, when IS_RAW is non-null, set
1102 *IS_RAW when the format type corresponds to a GCC "raw" diagnostic
1103 formatting function and clear it otherwise. */
1105 decode_format_type (const char *s
, bool *is_raw
/* = NULL */)
1110 is_raw
= &is_raw_buf
;
1114 s
= convert_format_name_to_system_name (s
);
1116 size_t slen
= strlen (s
);
1117 for (int i
= 0; i
< n_format_types
; i
++)
1119 /* Check for a match with no underscores. */
1120 if (!strcmp (s
, format_types
[i
].name
))
1121 return static_cast<format_type
> (i
);
1123 /* Check for leading and trailing underscores. */
1124 size_t alen
= strlen (format_types
[i
].name
);
1125 if (slen
== alen
+ 4 && s
[0] == '_' && s
[1] == '_'
1126 && s
[slen
- 1] == '_' && s
[slen
- 2] == '_'
1127 && !strncmp (s
+ 2, format_types
[i
].name
, alen
))
1128 return static_cast<format_type
>(i
);
1130 /* Check for the "_raw" suffix and no leading underscores. */
1131 if (slen
== alen
+ 4
1132 && !strncmp (s
, format_types
[i
].name
, alen
)
1133 && !strcmp (s
+ alen
, "_raw"))
1136 return static_cast<format_type
>(i
);
1139 /* Check for the "_raw__" suffix and leading underscores. */
1140 if (slen
== alen
+ 8 && s
[0] == '_' && s
[1] == '_'
1141 && !strncmp (s
+ 2, format_types
[i
].name
, alen
)
1142 && !strcmp (s
+ 2 + alen
, "_raw__"))
1145 return static_cast<format_type
>(i
);
1149 return format_type_error
;
1153 /* Check the argument list of a call to printf, scanf, etc.
1154 ATTRS are the attributes on the function type. There are NARGS argument
1155 values in the array ARGARRAY.
1156 Also, if -Wsuggest-attribute=format,
1157 warn for calls to vprintf or vscanf in functions with no such format
1158 attribute themselves. */
1161 check_function_format (const_tree fntype
, tree attrs
, int nargs
,
1162 tree
*argarray
, vec
<location_t
> *arglocs
)
1166 tree atname
= get_identifier ("format");
1168 /* See if this function has any format attributes. */
1169 for (a
= attrs
; a
; a
= TREE_CHAIN (a
))
1171 if (is_attribute_p ("format", get_attribute_name (a
)))
1173 /* Yup; check it. */
1174 function_format_info info
;
1175 decode_format_attr (fntype
, atname
, TREE_VALUE (a
), &info
,
1176 /*validated=*/true);
1179 /* FIXME: Rewrite all the internal functions in this file
1180 to use the ARGARRAY directly instead of constructing this
1182 tree params
= NULL_TREE
;
1184 for (i
= nargs
- 1; i
>= 0; i
--)
1185 params
= tree_cons (NULL_TREE
, argarray
[i
], params
);
1186 check_format_info (&info
, params
, arglocs
);
1189 /* Attempt to detect whether the current function might benefit
1190 from the format attribute if the called function is decorated
1191 with it. Avoid using calls with string literal formats for
1192 guidance since those are unlikely to be viable candidates. */
1193 if (warn_suggest_attribute_format
1194 && current_function_decl
!= NULL_TREE
1195 && info
.first_arg_num
== 0
1196 && (format_types
[info
.format_type
].flags
1197 & (int) FMT_FLAG_ARG_CONVERT
)
1198 /* c_strlen will fail for a function parameter but succeed
1199 for a literal or constant array. */
1200 && !c_strlen (argarray
[info
.format_num
- 1], 1))
1203 for (c
= TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl
));
1206 if (is_attribute_p ("format", TREE_PURPOSE (c
))
1207 && (decode_format_type (IDENTIFIER_POINTER
1208 (TREE_VALUE (TREE_VALUE (c
))))
1209 == info
.format_type
))
1213 /* Check if the current function has a parameter to which
1214 the format attribute could be attached; if not, it
1215 can't be a candidate for a format attribute, despite
1216 the vprintf-like or vscanf-like call. */
1218 for (args
= DECL_ARGUMENTS (current_function_decl
);
1220 args
= DECL_CHAIN (args
))
1222 if (TREE_CODE (TREE_TYPE (args
)) == POINTER_TYPE
1223 && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (args
)))
1228 warning (OPT_Wsuggest_attribute_format
, "function %qD "
1229 "might be a candidate for %qs format attribute",
1230 current_function_decl
,
1231 format_types
[info
.format_type
].name
);
1239 /* Variables used by the checking of $ operand number formats. */
1240 static char *dollar_arguments_used
= NULL
;
1241 static char *dollar_arguments_pointer_p
= NULL
;
1242 static int dollar_arguments_alloc
= 0;
1243 static int dollar_arguments_count
;
1244 static int dollar_first_arg_num
;
1245 static int dollar_max_arg_used
;
1246 static int dollar_format_warned
;
1248 /* Initialize the checking for a format string that may contain $
1249 parameter number specifications; we will need to keep track of whether
1250 each parameter has been used. FIRST_ARG_NUM is the number of the first
1251 argument that is a parameter to the format, or 0 for a vprintf-style
1252 function; PARAMS is the list of arguments starting at this argument. */
1255 init_dollar_format_checking (int first_arg_num
, tree params
)
1257 tree oparams
= params
;
1259 dollar_first_arg_num
= first_arg_num
;
1260 dollar_arguments_count
= 0;
1261 dollar_max_arg_used
= 0;
1262 dollar_format_warned
= 0;
1263 if (first_arg_num
> 0)
1267 dollar_arguments_count
++;
1268 params
= TREE_CHAIN (params
);
1271 if (dollar_arguments_alloc
< dollar_arguments_count
)
1273 free (dollar_arguments_used
);
1274 free (dollar_arguments_pointer_p
);
1275 dollar_arguments_alloc
= dollar_arguments_count
;
1276 dollar_arguments_used
= XNEWVEC (char, dollar_arguments_alloc
);
1277 dollar_arguments_pointer_p
= XNEWVEC (char, dollar_arguments_alloc
);
1279 if (dollar_arguments_alloc
)
1281 memset (dollar_arguments_used
, 0, dollar_arguments_alloc
);
1282 if (first_arg_num
> 0)
1288 dollar_arguments_pointer_p
[i
] = (TREE_CODE (TREE_TYPE (TREE_VALUE (params
)))
1290 params
= TREE_CHAIN (params
);
1298 /* Look for a decimal number followed by a $ in *FORMAT. If DOLLAR_NEEDED
1299 is set, it is an error if one is not found; otherwise, it is OK. If
1300 such a number is found, check whether it is within range and mark that
1301 numbered operand as being used for later checking. Returns the operand
1302 number if found and within range, zero if no such number was found and
1303 this is OK, or -1 on error. PARAMS points to the first operand of the
1304 format; PARAM_PTR is made to point to the parameter referred to. If
1305 a $ format is found, *FORMAT is updated to point just after it. */
1308 maybe_read_dollar_number (const char **format
,
1309 int dollar_needed
, tree params
, tree
*param_ptr
,
1310 const format_kind_info
*fki
)
1314 const char *fcp
= *format
;
1315 if (!ISDIGIT (*fcp
))
1319 warning (OPT_Wformat_
, "missing $ operand number in format");
1327 while (ISDIGIT (*fcp
))
1329 HOST_WIDE_INT nargnum
1330 = HOST_WIDE_INT_UC (10) * argnum
+ (*fcp
- '0');
1331 if ((int) nargnum
!= nargnum
)
1340 warning (OPT_Wformat_
, "missing $ operand number in format");
1347 if (pedantic
&& !dollar_format_warned
)
1349 warning (OPT_Wformat_
, "%s does not support %%n$ operand number formats",
1350 C_STD_NAME (STD_EXT
));
1351 dollar_format_warned
= 1;
1353 if (overflow_flag
|| argnum
== 0
1354 || (dollar_first_arg_num
&& argnum
> dollar_arguments_count
))
1356 warning (OPT_Wformat_
, "operand number out of range in format");
1359 if (argnum
> dollar_max_arg_used
)
1360 dollar_max_arg_used
= argnum
;
1361 /* For vprintf-style functions we may need to allocate more memory to
1362 track which arguments are used. */
1363 while (dollar_arguments_alloc
< dollar_max_arg_used
)
1366 nalloc
= 2 * dollar_arguments_alloc
+ 16;
1367 dollar_arguments_used
= XRESIZEVEC (char, dollar_arguments_used
,
1369 dollar_arguments_pointer_p
= XRESIZEVEC (char, dollar_arguments_pointer_p
,
1371 memset (dollar_arguments_used
+ dollar_arguments_alloc
, 0,
1372 nalloc
- dollar_arguments_alloc
);
1373 dollar_arguments_alloc
= nalloc
;
1375 if (!(fki
->flags
& (int) FMT_FLAG_DOLLAR_MULTIPLE
)
1376 && dollar_arguments_used
[argnum
- 1] == 1)
1378 dollar_arguments_used
[argnum
- 1] = 2;
1379 warning (OPT_Wformat_
, "format argument %d used more than once in %s format",
1383 dollar_arguments_used
[argnum
- 1] = 1;
1384 if (dollar_first_arg_num
)
1387 *param_ptr
= params
;
1388 for (i
= 1; i
< argnum
&& *param_ptr
!= 0; i
++)
1389 *param_ptr
= TREE_CHAIN (*param_ptr
);
1391 /* This case shouldn't be caught here. */
1392 gcc_assert (*param_ptr
);
1399 /* Ensure that FORMAT does not start with a decimal number followed by
1400 a $; give a diagnostic and return true if it does, false otherwise. */
1403 avoid_dollar_number (const char *format
)
1405 if (!ISDIGIT (*format
))
1407 while (ISDIGIT (*format
))
1411 warning (OPT_Wformat_
,
1412 "%<$%>operand number used after format without operand number");
1419 /* Finish the checking for a format string that used $ operand number formats
1420 instead of non-$ formats. We check for unused operands before used ones
1421 (a serious error, since the implementation of the format function
1422 can't know what types to pass to va_arg to find the later arguments).
1423 and for unused operands at the end of the format (if we know how many
1424 arguments the format had, so not for vprintf). If there were operand
1425 numbers out of range on a non-vprintf-style format, we won't have reached
1426 here. If POINTER_GAP_OK, unused arguments are OK if all arguments are
1430 finish_dollar_format_checking (format_check_results
*res
, int pointer_gap_ok
)
1433 bool found_pointer_gap
= false;
1434 for (i
= 0; i
< dollar_max_arg_used
; i
++)
1436 if (!dollar_arguments_used
[i
])
1438 if (pointer_gap_ok
&& (dollar_first_arg_num
== 0
1439 || dollar_arguments_pointer_p
[i
]))
1440 found_pointer_gap
= true;
1442 warning_at (res
->format_string_loc
, OPT_Wformat_
,
1443 "format argument %d unused before used argument %d "
1444 "in %<$%>-style format",
1445 i
+ 1, dollar_max_arg_used
);
1448 if (found_pointer_gap
1449 || (dollar_first_arg_num
1450 && dollar_max_arg_used
< dollar_arguments_count
))
1452 res
->number_other
--;
1453 res
->number_dollar_extra_args
++;
1458 /* Retrieve the specification for a format flag. SPEC contains the
1459 specifications for format flags for the applicable kind of format.
1460 FLAG is the flag in question. If PREDICATES is NULL, the basic
1461 spec for that flag must be retrieved and must exist. If
1462 PREDICATES is not NULL, it is a string listing possible predicates
1463 for the spec entry; if an entry predicated on any of these is
1464 found, it is returned, otherwise NULL is returned. */
1466 static const format_flag_spec
*
1467 get_flag_spec (const format_flag_spec
*spec
, int flag
, const char *predicates
)
1470 for (i
= 0; spec
[i
].flag_char
!= 0; i
++)
1472 if (spec
[i
].flag_char
!= flag
)
1474 if (predicates
!= NULL
)
1476 if (spec
[i
].predicate
!= 0
1477 && strchr (predicates
, spec
[i
].predicate
) != 0)
1480 else if (spec
[i
].predicate
== 0)
1483 gcc_assert (predicates
);
1488 /* Check the argument list of a call to printf, scanf, etc.
1489 INFO points to the function_format_info structure.
1490 PARAMS is the list of argument values. */
1493 check_format_info (function_format_info
*info
, tree params
,
1494 vec
<location_t
> *arglocs
)
1496 format_check_context format_ctx
;
1497 unsigned HOST_WIDE_INT arg_num
;
1499 format_check_results res
;
1500 /* Skip to format argument. If the argument isn't available, there's
1501 no work for us to do; prototype checking will catch the problem. */
1502 for (arg_num
= 1; ; ++arg_num
)
1506 if (arg_num
== info
->format_num
)
1508 params
= TREE_CHAIN (params
);
1510 format_tree
= TREE_VALUE (params
);
1511 params
= TREE_CHAIN (params
);
1512 if (format_tree
== 0)
1515 res
.number_non_literal
= 0;
1516 res
.number_extra_args
= 0;
1517 res
.extra_arg_loc
= UNKNOWN_LOCATION
;
1518 res
.number_dollar_extra_args
= 0;
1519 res
.number_wide
= 0;
1520 res
.number_non_char
= 0;
1521 res
.number_empty
= 0;
1522 res
.number_unterminated
= 0;
1523 res
.number_other
= 0;
1524 res
.format_string_loc
= input_location
;
1526 format_ctx
.res
= &res
;
1527 format_ctx
.info
= info
;
1528 format_ctx
.params
= params
;
1529 format_ctx
.arglocs
= arglocs
;
1531 check_function_arguments_recurse (check_format_arg
, &format_ctx
,
1532 format_tree
, arg_num
);
1534 location_t loc
= format_ctx
.res
->format_string_loc
;
1536 if (res
.number_non_literal
> 0)
1538 /* Functions taking a va_list normally pass a non-literal format
1539 string. These functions typically are declared with
1540 first_arg_num == 0, so avoid warning in those cases. */
1541 if (!(format_types
[info
->format_type
].flags
& (int) FMT_FLAG_ARG_CONVERT
))
1543 /* For strftime-like formats, warn for not checking the format
1544 string; but there are no arguments to check. */
1545 warning_at (loc
, OPT_Wformat_nonliteral
,
1546 "format not a string literal, format string not checked");
1548 else if (info
->first_arg_num
!= 0)
1550 /* If there are no arguments for the format at all, we may have
1551 printf (foo) which is likely to be a security hole. */
1552 while (arg_num
+ 1 < info
->first_arg_num
)
1556 params
= TREE_CHAIN (params
);
1559 if (params
== 0 && warn_format_security
)
1560 warning_at (loc
, OPT_Wformat_security
,
1561 "format not a string literal and no format arguments");
1562 else if (params
== 0 && warn_format_nonliteral
)
1563 warning_at (loc
, OPT_Wformat_nonliteral
,
1564 "format not a string literal and no format arguments");
1566 warning_at (loc
, OPT_Wformat_nonliteral
,
1567 "format not a string literal, argument types not checked");
1571 /* If there were extra arguments to the format, normally warn. However,
1572 the standard does say extra arguments are ignored, so in the specific
1573 case where we have multiple leaves (conditional expressions or
1574 ngettext) allow extra arguments if at least one leaf didn't have extra
1575 arguments, but was otherwise OK (either non-literal or checked OK).
1576 If the format is an empty string, this should be counted similarly to the
1577 case of extra format arguments. */
1578 if (res
.number_extra_args
> 0 && res
.number_non_literal
== 0
1579 && res
.number_other
== 0)
1581 if (res
.extra_arg_loc
== UNKNOWN_LOCATION
)
1582 res
.extra_arg_loc
= loc
;
1583 warning_at (res
.extra_arg_loc
, OPT_Wformat_extra_args
,
1584 "too many arguments for format");
1586 if (res
.number_dollar_extra_args
> 0 && res
.number_non_literal
== 0
1587 && res
.number_other
== 0)
1588 warning_at (loc
, OPT_Wformat_extra_args
,
1589 "unused arguments in %<$%>-style format");
1590 if (res
.number_empty
> 0 && res
.number_non_literal
== 0
1591 && res
.number_other
== 0)
1592 warning_at (loc
, OPT_Wformat_zero_length
, "zero-length %s format string",
1593 format_types
[info
->format_type
].name
);
1595 if (res
.number_wide
> 0)
1596 warning_at (loc
, OPT_Wformat_
, "format is a wide character string");
1598 if (res
.number_non_char
> 0)
1599 warning_at (loc
, OPT_Wformat_
,
1600 "format string is not an array of type %qs", "char");
1602 if (res
.number_unterminated
> 0)
1603 warning_at (loc
, OPT_Wformat_
, "unterminated format string");
1606 /* Callback from check_function_arguments_recurse to check a
1607 format string. FORMAT_TREE is the format parameter. ARG_NUM
1608 is the number of the format argument. CTX points to a
1609 format_check_context. */
1612 check_format_arg (void *ctx
, tree format_tree
,
1613 unsigned HOST_WIDE_INT arg_num
)
1615 format_check_context
*format_ctx
= (format_check_context
*) ctx
;
1616 format_check_results
*res
= format_ctx
->res
;
1617 function_format_info
*info
= format_ctx
->info
;
1618 tree params
= format_ctx
->params
;
1619 vec
<location_t
> *arglocs
= format_ctx
->arglocs
;
1622 HOST_WIDE_INT offset
;
1623 const char *format_chars
;
1624 tree array_size
= 0;
1627 location_t fmt_param_loc
= EXPR_LOC_OR_LOC (format_tree
, input_location
);
1629 /* Pull out a constant value if the front end didn't, and handle location
1631 format_tree
= fold_for_warn (format_tree
);
1632 STRIP_NOPS (format_tree
);
1634 if (integer_zerop (format_tree
))
1636 /* Skip to first argument to check, so we can see if this format
1637 has any arguments (it shouldn't). */
1638 while (arg_num
+ 1 < info
->first_arg_num
)
1642 params
= TREE_CHAIN (params
);
1647 res
->number_other
++;
1650 if (res
->number_extra_args
== 0)
1651 res
->extra_arg_loc
= EXPR_LOC_OR_LOC (TREE_VALUE (params
),
1653 res
->number_extra_args
++;
1659 if (TREE_CODE (format_tree
) == POINTER_PLUS_EXPR
)
1663 arg0
= TREE_OPERAND (format_tree
, 0);
1664 arg1
= TREE_OPERAND (format_tree
, 1);
1667 if (TREE_CODE (arg1
) == INTEGER_CST
)
1671 res
->number_non_literal
++;
1674 /* POINTER_PLUS_EXPR offsets are to be interpreted signed. */
1675 if (!cst_and_fits_in_hwi (arg1
))
1677 res
->number_non_literal
++;
1680 offset
= int_cst_value (arg1
);
1682 if (TREE_CODE (format_tree
) != ADDR_EXPR
)
1684 res
->number_non_literal
++;
1687 res
->format_string_loc
= EXPR_LOC_OR_LOC (format_tree
, input_location
);
1688 format_tree
= TREE_OPERAND (format_tree
, 0);
1689 if (format_types
[info
->format_type
].flags
1690 & (int) FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL
)
1692 bool objc_str
= (info
->format_type
== gcc_objc_string_format_type
);
1693 /* We cannot examine this string here - but we can check that it is
1695 if (TREE_CODE (format_tree
) != CONST_DECL
1696 || !((objc_str
&& objc_string_ref_type_p (TREE_TYPE (format_tree
)))
1697 || (*targetcm
.string_object_ref_type_p
)
1698 ((const_tree
) TREE_TYPE (format_tree
))))
1700 res
->number_non_literal
++;
1703 /* Skip to first argument to check. */
1704 while (arg_num
+ 1 < info
->first_arg_num
)
1708 params
= TREE_CHAIN (params
);
1711 /* So, we have a valid literal string object and one or more params.
1712 We need to use an external helper to parse the string into format
1713 info. For Objective-C variants we provide the resource within the
1714 objc tree, for target variants, via a hook. */
1716 objc_check_format_arg (format_tree
, params
);
1717 else if (targetcm
.check_string_object_format_arg
)
1718 (*targetcm
.check_string_object_format_arg
) (format_tree
, params
);
1719 /* Else we can't handle it and retire quietly. */
1722 if (TREE_CODE (format_tree
) == ARRAY_REF
1723 && tree_fits_shwi_p (TREE_OPERAND (format_tree
, 1))
1724 && (offset
+= tree_to_shwi (TREE_OPERAND (format_tree
, 1))) >= 0)
1725 format_tree
= TREE_OPERAND (format_tree
, 0);
1728 res
->number_non_literal
++;
1731 if (VAR_P (format_tree
)
1732 && TREE_CODE (TREE_TYPE (format_tree
)) == ARRAY_TYPE
1733 && (array_init
= decl_constant_value (format_tree
)) != format_tree
1734 && TREE_CODE (array_init
) == STRING_CST
)
1736 /* Extract the string constant initializer. Note that this may include
1737 a trailing NUL character that is not in the array (e.g.
1738 const char a[3] = "foo";). */
1739 array_size
= DECL_SIZE_UNIT (format_tree
);
1740 format_tree
= array_init
;
1742 if (TREE_CODE (format_tree
) != STRING_CST
)
1744 res
->number_non_literal
++;
1747 tree underlying_type
1748 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (format_tree
)));
1749 if (underlying_type
!= char_type_node
)
1751 if (underlying_type
== char16_type_node
1752 || underlying_type
== char32_type_node
1753 || underlying_type
== wchar_type_node
)
1756 res
->number_non_char
++;
1759 format_chars
= TREE_STRING_POINTER (format_tree
);
1760 format_length
= TREE_STRING_LENGTH (format_tree
);
1761 if (array_size
!= 0)
1763 /* Variable length arrays can't be initialized. */
1764 gcc_assert (TREE_CODE (array_size
) == INTEGER_CST
);
1766 if (tree_fits_shwi_p (array_size
))
1768 HOST_WIDE_INT array_size_value
= tree_to_shwi (array_size
);
1769 if (array_size_value
> 0
1770 && array_size_value
== (int) array_size_value
1771 && format_length
> array_size_value
)
1772 format_length
= array_size_value
;
1777 if (offset
>= format_length
)
1779 res
->number_non_literal
++;
1782 format_chars
+= offset
;
1783 format_length
-= offset
;
1785 if (format_length
< 1 || format_chars
[--format_length
] != 0)
1787 res
->number_unterminated
++;
1790 if (format_length
== 0)
1792 res
->number_empty
++;
1796 /* Skip to first argument to check. */
1797 while (arg_num
+ 1 < info
->first_arg_num
)
1801 params
= TREE_CHAIN (params
);
1804 /* Provisionally increment res->number_other; check_format_info_main
1805 will decrement it if it finds there are extra arguments, but this way
1806 need not adjust it for every return. */
1807 res
->number_other
++;
1808 object_allocator
<format_wanted_type
> fwt_pool ("format_wanted_type pool");
1809 check_format_info_main (res
, info
, format_chars
, fmt_param_loc
, format_tree
,
1810 format_length
, params
, arg_num
, fwt_pool
, arglocs
);
1813 /* Support class for argument_parser and check_format_info_main.
1814 Tracks any flag characters that have been applied to the
1815 current argument. */
1821 bool has_char_p (char ch
) const;
1822 void add_char (char ch
);
1823 void validate (const format_kind_info
*fki
,
1824 const format_char_info
*fci
,
1825 const format_flag_spec
*flag_specs
,
1826 const char * const format_chars
,
1827 tree format_string_cst
,
1828 location_t format_string_loc
,
1829 const char * const orig_format_chars
,
1832 int get_alloc_flag (const format_kind_info
*fki
);
1833 int assignment_suppression_p (const format_kind_info
*fki
);
1836 char m_flag_chars
[256];
1839 /* Support struct for argument_parser and check_format_info_main.
1840 Encapsulates any length modifier applied to the current argument. */
1842 class length_modifier
1846 : chars (NULL
), val (FMT_LEN_none
), std (STD_C89
),
1847 scalar_identity_flag (0)
1851 length_modifier (const char *chars_
,
1852 enum format_lengths val_
,
1853 enum format_std_version std_
,
1854 int scalar_identity_flag_
)
1855 : chars (chars_
), val (val_
), std (std_
),
1856 scalar_identity_flag (scalar_identity_flag_
)
1861 enum format_lengths val
;
1862 enum format_std_version std
;
1863 int scalar_identity_flag
;
1866 /* Parsing one argument within a format string. */
1868 class argument_parser
1871 argument_parser (function_format_info
*info
, const char *&format_chars
,
1872 tree format_string_cst
,
1873 const char * const orig_format_chars
,
1874 location_t format_string_loc
, flag_chars_t
&flag_chars
,
1875 int &has_operand_number
, tree first_fillin_param
,
1876 object_allocator
<format_wanted_type
> &fwt_pool_
,
1877 vec
<location_t
> *arglocs
);
1879 bool read_any_dollar ();
1881 bool read_format_flags ();
1884 read_any_format_width (tree
¶ms
,
1885 unsigned HOST_WIDE_INT
&arg_num
);
1888 read_any_format_left_precision ();
1891 read_any_format_precision (tree
¶ms
,
1892 unsigned HOST_WIDE_INT
&arg_num
);
1894 void handle_alloc_chars ();
1896 length_modifier
read_any_length_modifier ();
1898 void read_any_other_modifier ();
1900 const format_char_info
*find_format_char_info (char format_char
);
1903 validate_flag_pairs (const format_char_info
*fci
,
1907 give_y2k_warnings (const format_char_info
*fci
,
1910 void parse_any_scan_set (const format_char_info
*fci
);
1912 bool handle_conversions (const format_char_info
*fci
,
1913 const length_modifier
&len_modifier
,
1915 const char *&wanted_type_name
,
1916 unsigned HOST_WIDE_INT
&arg_num
,
1921 check_argument_type (const format_char_info
*fci
,
1922 const length_modifier
&len_modifier
,
1924 const char *&wanted_type_name
,
1925 const bool suppressed
,
1926 unsigned HOST_WIDE_INT
&arg_num
,
1928 const int alloc_flag
,
1929 const char * const format_start
,
1930 const char * const type_start
,
1931 location_t fmt_param_loc
,
1932 char conversion_char
);
1935 const function_format_info
*const info
;
1936 const format_kind_info
* const fki
;
1937 const format_flag_spec
* const flag_specs
;
1938 const char *start_of_this_format
;
1939 const char *&format_chars
;
1940 const tree format_string_cst
;
1941 const char * const orig_format_chars
;
1942 const location_t format_string_loc
;
1943 object_allocator
<format_wanted_type
> &fwt_pool
;
1944 flag_chars_t
&flag_chars
;
1946 tree main_arg_params
;
1947 int &has_operand_number
;
1948 const tree first_fillin_param
;
1949 format_wanted_type width_wanted_type
;
1950 format_wanted_type precision_wanted_type
;
1952 format_wanted_type main_wanted_type
;
1954 format_wanted_type
*first_wanted_type
;
1955 format_wanted_type
*last_wanted_type
;
1956 vec
<location_t
> *arglocs
;
1959 /* flag_chars_t's constructor. */
1961 flag_chars_t::flag_chars_t ()
1963 m_flag_chars
[0] = 0;
1966 /* Has CH been seen as a flag within the current argument? */
1969 flag_chars_t::has_char_p (char ch
) const
1971 return strchr (m_flag_chars
, ch
) != 0;
1974 /* Add CH to the flags seen within the current argument. */
1977 flag_chars_t::add_char (char ch
)
1979 int i
= strlen (m_flag_chars
);
1980 m_flag_chars
[i
++] = ch
;
1981 m_flag_chars
[i
] = 0;
1984 /* Validate the individual flags used, removing any that are invalid. */
1987 flag_chars_t::validate (const format_kind_info
*fki
,
1988 const format_char_info
*fci
,
1989 const format_flag_spec
*flag_specs
,
1990 const char * const format_chars
,
1991 tree format_string_cst
,
1992 location_t format_string_loc
,
1993 const char * const orig_format_chars
,
1999 bool quotflag
= false;
2001 for (i
= 0; m_flag_chars
[i
] != 0; i
++)
2003 const format_flag_spec
*s
= get_flag_spec (flag_specs
,
2004 m_flag_chars
[i
], NULL
);
2005 m_flag_chars
[i
- d
] = m_flag_chars
[i
];
2006 if (m_flag_chars
[i
] == fki
->length_code_char
)
2009 /* Remember if a quoting flag is seen. */
2010 quotflag
|= s
->quoting
;
2012 if (strchr (fci
->flag_chars
, m_flag_chars
[i
]) == 0)
2014 format_warning_at_char (format_string_loc
, format_string_cst
,
2015 format_chars
- orig_format_chars
,
2017 "%s used with %<%%%c%> %s format",
2018 _(s
->name
), format_char
, fki
->name
);
2024 const format_flag_spec
*t
;
2025 if (ADJ_STD (s
->std
) > C_STD_VER
)
2026 warning_at (format_string_loc
, OPT_Wformat_
,
2027 "%s does not support %s",
2028 C_STD_NAME (s
->std
), _(s
->long_name
));
2029 t
= get_flag_spec (flag_specs
, m_flag_chars
[i
], fci
->flags2
);
2030 if (t
!= NULL
&& ADJ_STD (t
->std
) > ADJ_STD (s
->std
))
2032 const char *long_name
= (t
->long_name
!= NULL
2035 if (ADJ_STD (t
->std
) > C_STD_VER
)
2036 warning_at (format_string_loc
, OPT_Wformat_
,
2037 "%s does not support %s with"
2038 " the %<%%%c%> %s format",
2039 C_STD_NAME (t
->std
), _(long_name
),
2040 format_char
, fki
->name
);
2044 /* Detect quoting directives used within a quoted sequence, such
2045 as GCC's "%<...%qE". */
2046 if (quoted
&& s
->quoting
)
2048 format_warning_at_char (format_string_loc
, format_string_cst
,
2049 format_chars
- orig_format_chars
- 1,
2051 "%s used within a quoted sequence",
2055 m_flag_chars
[i
- d
] = 0;
2059 && strchr (fci
->flags2
, '\''))
2061 format_warning_at_char (format_string_loc
, format_string_cst
,
2062 format_chars
- orig_format_chars
,
2064 "%qc conversion used unquoted",
2069 /* Determine if an assignment-allocation has been set, requiring
2070 an extra char ** for writing back a dynamically-allocated char *.
2071 This is for handling the optional 'm' character in scanf. */
2074 flag_chars_t::get_alloc_flag (const format_kind_info
*fki
)
2076 if ((fki
->flags
& (int) FMT_FLAG_SCANF_A_KLUDGE
)
2077 && has_char_p ('a'))
2079 if (fki
->alloc_char
&& has_char_p (fki
->alloc_char
))
2084 /* Determine if an assignment-suppression character was seen.
2085 ('*' in scanf, for discarding the converted input). */
2088 flag_chars_t::assignment_suppression_p (const format_kind_info
*fki
)
2090 if (fki
->suppression_char
2091 && has_char_p (fki
->suppression_char
))
2096 /* Constructor for argument_parser. Initialize for parsing one
2097 argument within a format string. */
2100 argument_parser (function_format_info
*info_
, const char *&format_chars_
,
2101 tree format_string_cst_
,
2102 const char * const orig_format_chars_
,
2103 location_t format_string_loc_
,
2104 flag_chars_t
&flag_chars_
,
2105 int &has_operand_number_
,
2106 tree first_fillin_param_
,
2107 object_allocator
<format_wanted_type
> &fwt_pool_
,
2108 vec
<location_t
> *arglocs_
)
2110 fki (&format_types
[info
->format_type
]),
2111 flag_specs (fki
->flag_specs
),
2112 start_of_this_format (format_chars_
),
2113 format_chars (format_chars_
),
2114 format_string_cst (format_string_cst_
),
2115 orig_format_chars (orig_format_chars_
),
2116 format_string_loc (format_string_loc_
),
2117 fwt_pool (fwt_pool_
),
2118 flag_chars (flag_chars_
),
2120 main_arg_params (NULL
),
2121 has_operand_number (has_operand_number_
),
2122 first_fillin_param (first_fillin_param_
),
2123 first_wanted_type (NULL
),
2124 last_wanted_type (NULL
),
2129 /* Handle dollars at the start of format arguments, setting up main_arg_params
2132 Return true if format parsing is to continue, false otherwise. */
2135 argument_parser::read_any_dollar ()
2137 if ((fki
->flags
& (int) FMT_FLAG_USE_DOLLAR
) && has_operand_number
!= 0)
2139 /* Possibly read a $ operand number at the start of the format.
2140 If one was previously used, one is required here. If one
2141 is not used here, we can't immediately conclude this is a
2142 format without them, since it could be printf %m or scanf %*. */
2144 opnum
= maybe_read_dollar_number (&format_chars
, 0,
2146 &main_arg_params
, fki
);
2151 has_operand_number
= 1;
2152 main_arg_num
= opnum
+ info
->first_arg_num
- 1;
2155 else if (fki
->flags
& FMT_FLAG_USE_DOLLAR
)
2157 if (avoid_dollar_number (format_chars
))
2163 /* Read any format flags, but do not yet validate them beyond removing
2164 duplicates, since in general validation depends on the rest of
2167 Return true if format parsing is to continue, false otherwise. */
2170 argument_parser::read_format_flags ()
2172 while (*format_chars
!= 0
2173 && strchr (fki
->flag_chars
, *format_chars
) != 0)
2175 const format_flag_spec
*s
= get_flag_spec (flag_specs
,
2176 *format_chars
, NULL
);
2177 if (flag_chars
.has_char_p (*format_chars
))
2179 format_warning_at_char (format_string_loc
, format_string_cst
,
2180 format_chars
+ 1 - orig_format_chars
,
2182 "repeated %s in format", _(s
->name
));
2185 flag_chars
.add_char (*format_chars
);
2187 if (s
->skip_next_char
)
2190 if (*format_chars
== 0)
2192 warning_at (format_string_loc
, OPT_Wformat_
,
2193 "missing fill character at end of strfmon format");
2203 /* Read any format width, possibly * or *m$.
2205 Return true if format parsing is to continue, false otherwise. */
2209 read_any_format_width (tree
¶ms
,
2210 unsigned HOST_WIDE_INT
&arg_num
)
2212 if (!fki
->width_char
)
2215 if (fki
->width_type
!= NULL
&& *format_chars
== '*')
2217 flag_chars
.add_char (fki
->width_char
);
2218 /* "...a field width...may be indicated by an asterisk.
2219 In this case, an int argument supplies the field width..." */
2221 if (has_operand_number
!= 0)
2224 opnum
= maybe_read_dollar_number (&format_chars
,
2225 has_operand_number
== 1,
2232 has_operand_number
= 1;
2233 arg_num
= opnum
+ info
->first_arg_num
- 1;
2236 has_operand_number
= 0;
2240 if (avoid_dollar_number (format_chars
))
2243 if (info
->first_arg_num
!= 0)
2250 cur_param
= TREE_VALUE (params
);
2251 if (has_operand_number
<= 0)
2253 params
= TREE_CHAIN (params
);
2257 width_wanted_type
.wanted_type
= *fki
->width_type
;
2258 width_wanted_type
.wanted_type_name
= NULL
;
2259 width_wanted_type
.pointer_count
= 0;
2260 width_wanted_type
.char_lenient_flag
= 0;
2261 width_wanted_type
.scalar_identity_flag
= 0;
2262 width_wanted_type
.writing_in_flag
= 0;
2263 width_wanted_type
.reading_from_flag
= 0;
2264 width_wanted_type
.kind
= CF_KIND_FIELD_WIDTH
;
2265 width_wanted_type
.format_start
= format_chars
- 1;
2266 width_wanted_type
.format_length
= 1;
2267 width_wanted_type
.param
= cur_param
;
2268 width_wanted_type
.arg_num
= arg_num
;
2269 width_wanted_type
.offset_loc
=
2270 format_chars
- orig_format_chars
;
2271 width_wanted_type
.next
= NULL
;
2272 if (last_wanted_type
!= 0)
2273 last_wanted_type
->next
= &width_wanted_type
;
2274 if (first_wanted_type
== 0)
2275 first_wanted_type
= &width_wanted_type
;
2276 last_wanted_type
= &width_wanted_type
;
2281 /* Possibly read a numeric width. If the width is zero,
2282 we complain if appropriate. */
2283 int non_zero_width_char
= FALSE
;
2284 int found_width
= FALSE
;
2285 while (ISDIGIT (*format_chars
))
2288 if (*format_chars
!= '0')
2289 non_zero_width_char
= TRUE
;
2292 if (found_width
&& !non_zero_width_char
&&
2293 (fki
->flags
& (int) FMT_FLAG_ZERO_WIDTH_BAD
))
2294 warning_at (format_string_loc
, OPT_Wformat_
,
2295 "zero width in %s format", fki
->name
);
2297 flag_chars
.add_char (fki
->width_char
);
2303 /* Read any format left precision (must be a number, not *). */
2305 argument_parser::read_any_format_left_precision ()
2307 if (fki
->left_precision_char
== 0)
2309 if (*format_chars
!= '#')
2313 flag_chars
.add_char (fki
->left_precision_char
);
2314 if (!ISDIGIT (*format_chars
))
2315 format_warning_at_char (format_string_loc
, format_string_cst
,
2316 format_chars
- orig_format_chars
,
2318 "empty left precision in %s format", fki
->name
);
2319 while (ISDIGIT (*format_chars
))
2323 /* Read any format precision, possibly * or *m$.
2325 Return true if format parsing is to continue, false otherwise. */
2329 read_any_format_precision (tree
¶ms
,
2330 unsigned HOST_WIDE_INT
&arg_num
)
2332 if (fki
->precision_char
== 0)
2334 if (*format_chars
!= '.')
2338 flag_chars
.add_char (fki
->precision_char
);
2339 if (fki
->precision_type
!= NULL
&& *format_chars
== '*')
2341 /* "...a...precision...may be indicated by an asterisk.
2342 In this case, an int argument supplies the...precision." */
2344 if (has_operand_number
!= 0)
2347 opnum
= maybe_read_dollar_number (&format_chars
,
2348 has_operand_number
== 1,
2355 has_operand_number
= 1;
2356 arg_num
= opnum
+ info
->first_arg_num
- 1;
2359 has_operand_number
= 0;
2363 if (avoid_dollar_number (format_chars
))
2366 if (info
->first_arg_num
!= 0)
2373 cur_param
= TREE_VALUE (params
);
2374 if (has_operand_number
<= 0)
2376 params
= TREE_CHAIN (params
);
2380 precision_wanted_type
.wanted_type
= *fki
->precision_type
;
2381 precision_wanted_type
.wanted_type_name
= NULL
;
2382 precision_wanted_type
.pointer_count
= 0;
2383 precision_wanted_type
.char_lenient_flag
= 0;
2384 precision_wanted_type
.scalar_identity_flag
= 0;
2385 precision_wanted_type
.writing_in_flag
= 0;
2386 precision_wanted_type
.reading_from_flag
= 0;
2387 precision_wanted_type
.kind
= CF_KIND_FIELD_PRECISION
;
2388 precision_wanted_type
.param
= cur_param
;
2389 precision_wanted_type
.format_start
= format_chars
- 2;
2390 precision_wanted_type
.format_length
= 2;
2391 precision_wanted_type
.arg_num
= arg_num
;
2392 precision_wanted_type
.offset_loc
=
2393 format_chars
- orig_format_chars
;
2394 precision_wanted_type
.next
= NULL
;
2395 if (last_wanted_type
!= 0)
2396 last_wanted_type
->next
= &precision_wanted_type
;
2397 if (first_wanted_type
== 0)
2398 first_wanted_type
= &precision_wanted_type
;
2399 last_wanted_type
= &precision_wanted_type
;
2404 if (!(fki
->flags
& (int) FMT_FLAG_EMPTY_PREC_OK
)
2405 && !ISDIGIT (*format_chars
))
2406 format_warning_at_char (format_string_loc
, format_string_cst
,
2407 format_chars
- orig_format_chars
,
2409 "empty precision in %s format", fki
->name
);
2410 while (ISDIGIT (*format_chars
))
2417 /* Parse any assignment-allocation flags, which request an extra
2418 char ** for writing back a dynamically-allocated char *.
2419 This is for handling the optional 'm' character in scanf,
2420 and, before C99, 'a' (for compatibility with a non-standard
2421 GNU libc extension). */
2424 argument_parser::handle_alloc_chars ()
2426 if (fki
->alloc_char
&& fki
->alloc_char
== *format_chars
)
2428 flag_chars
.add_char (fki
->alloc_char
);
2432 /* Handle the scanf allocation kludge. */
2433 if (fki
->flags
& (int) FMT_FLAG_SCANF_A_KLUDGE
)
2435 if (*format_chars
== 'a' && !flag_isoc99
)
2437 if (format_chars
[1] == 's' || format_chars
[1] == 'S'
2438 || format_chars
[1] == '[')
2440 /* 'a' is used as a flag. */
2441 flag_chars
.add_char ('a');
2448 /* Look for length modifiers within the current format argument,
2449 returning a length_modifier instance describing it (or the
2450 default if one is not found).
2452 Issue warnings about non-standard modifiers. */
2455 argument_parser::read_any_length_modifier ()
2457 length_modifier result
;
2459 const format_length_info
*fli
= fki
->length_char_specs
;
2463 while (fli
->name
!= 0
2464 && strncmp (fli
->name
, format_chars
, strlen (fli
->name
)))
2468 format_chars
+= strlen (fli
->name
);
2469 if (fli
->double_name
!= 0 && fli
->name
[0] == *format_chars
)
2472 result
= length_modifier (fli
->double_name
, fli
->double_index
,
2473 fli
->double_std
, 0);
2477 result
= length_modifier (fli
->name
, fli
->index
, fli
->std
,
2478 fli
->scalar_identity_flag
);
2480 flag_chars
.add_char (fki
->length_code_char
);
2484 /* Warn if the length modifier is non-standard. */
2485 if (ADJ_STD (result
.std
) > C_STD_VER
)
2486 warning_at (format_string_loc
, OPT_Wformat_
,
2487 "%s does not support the %qs %s length modifier",
2488 C_STD_NAME (result
.std
), result
.chars
,
2495 /* Read any other modifier (strftime E/O). */
2498 argument_parser::read_any_other_modifier ()
2500 if (fki
->modifier_chars
== NULL
)
2503 while (*format_chars
!= 0
2504 && strchr (fki
->modifier_chars
, *format_chars
) != 0)
2506 if (flag_chars
.has_char_p (*format_chars
))
2508 const format_flag_spec
*s
= get_flag_spec (flag_specs
,
2509 *format_chars
, NULL
);
2510 format_warning_at_char (format_string_loc
, format_string_cst
,
2511 format_chars
- orig_format_chars
,
2513 "repeated %s in format", _(s
->name
));
2516 flag_chars
.add_char (*format_chars
);
2521 /* Return the format_char_info corresponding to FORMAT_CHAR,
2522 potentially issuing a warning if the format char is
2523 not supported in the C standard version we are checking
2526 Issue a warning and return NULL if it is not found.
2528 Issue warnings about non-standard modifiers. */
2530 const format_char_info
*
2531 argument_parser::find_format_char_info (char format_char
)
2533 const format_char_info
*fci
= fki
->conversion_specs
;
2535 while (fci
->format_chars
!= 0
2536 && strchr (fci
->format_chars
, format_char
) == 0)
2538 if (fci
->format_chars
== 0)
2540 format_warning_at_char (format_string_loc
, format_string_cst
,
2541 format_chars
- orig_format_chars
,
2543 "unknown conversion type character"
2551 if (ADJ_STD (fci
->std
) > C_STD_VER
)
2552 format_warning_at_char (format_string_loc
, format_string_cst
,
2553 format_chars
- orig_format_chars
,
2555 "%s does not support the %<%%%c%> %s format",
2556 C_STD_NAME (fci
->std
), format_char
, fki
->name
);
2562 /* Validate the pairs of flags used.
2563 Issue warnings about incompatible combinations of flags. */
2566 argument_parser::validate_flag_pairs (const format_char_info
*fci
,
2569 const format_flag_pair
* const bad_flag_pairs
= fki
->bad_flag_pairs
;
2571 for (int i
= 0; bad_flag_pairs
[i
].flag_char1
!= 0; i
++)
2573 const format_flag_spec
*s
, *t
;
2574 if (!flag_chars
.has_char_p (bad_flag_pairs
[i
].flag_char1
))
2576 if (!flag_chars
.has_char_p (bad_flag_pairs
[i
].flag_char2
))
2578 if (bad_flag_pairs
[i
].predicate
!= 0
2579 && strchr (fci
->flags2
, bad_flag_pairs
[i
].predicate
) == 0)
2581 s
= get_flag_spec (flag_specs
, bad_flag_pairs
[i
].flag_char1
, NULL
);
2582 t
= get_flag_spec (flag_specs
, bad_flag_pairs
[i
].flag_char2
, NULL
);
2583 if (bad_flag_pairs
[i
].ignored
)
2585 if (bad_flag_pairs
[i
].predicate
!= 0)
2586 warning_at (format_string_loc
, OPT_Wformat_
,
2587 "%s ignored with %s and %<%%%c%> %s format",
2588 _(s
->name
), _(t
->name
), format_char
,
2591 warning_at (format_string_loc
, OPT_Wformat_
,
2592 "%s ignored with %s in %s format",
2593 _(s
->name
), _(t
->name
), fki
->name
);
2597 if (bad_flag_pairs
[i
].predicate
!= 0)
2598 warning_at (format_string_loc
, OPT_Wformat_
,
2599 "use of %s and %s together with %<%%%c%> %s format",
2600 _(s
->name
), _(t
->name
), format_char
,
2603 warning_at (format_string_loc
, OPT_Wformat_
,
2604 "use of %s and %s together in %s format",
2605 _(s
->name
), _(t
->name
), fki
->name
);
2610 /* Give Y2K warnings. */
2613 argument_parser::give_y2k_warnings (const format_char_info
*fci
,
2616 if (!warn_format_y2k
)
2620 if (strchr (fci
->flags2
, '4') != 0)
2621 if (flag_chars
.has_char_p ('E'))
2625 else if (strchr (fci
->flags2
, '3') != 0)
2627 else if (strchr (fci
->flags2
, '2') != 0)
2630 warning_at (format_string_loc
, OPT_Wformat_y2k
,
2631 "%<%%%c%> yields only last 2 digits of "
2632 "year in some locales", format_char
);
2633 else if (y2k_level
== 2)
2634 warning_at (format_string_loc
, OPT_Wformat_y2k
,
2635 "%<%%%c%> yields only last 2 digits of year",
2639 /* Parse any "scan sets" enclosed in square brackets, e.g.
2640 for scanf-style calls. */
2643 argument_parser::parse_any_scan_set (const format_char_info
*fci
)
2645 if (strchr (fci
->flags2
, '[') == NULL
)
2648 /* Skip over scan set, in case it happens to have '%' in it. */
2649 if (*format_chars
== '^')
2651 /* Find closing bracket; if one is hit immediately, then
2652 it's part of the scan set rather than a terminator. */
2653 if (*format_chars
== ']')
2655 while (*format_chars
&& *format_chars
!= ']')
2657 if (*format_chars
!= ']')
2658 /* The end of the format string was reached. */
2659 format_warning_at_char (format_string_loc
, format_string_cst
,
2660 format_chars
- orig_format_chars
,
2662 "no closing %<]%> for %<%%[%> format");
2665 /* Return true if this argument is to be continued to be parsed,
2666 false to skip to next argument. */
2669 argument_parser::handle_conversions (const format_char_info
*fci
,
2670 const length_modifier
&len_modifier
,
2672 const char *&wanted_type_name
,
2673 unsigned HOST_WIDE_INT
&arg_num
,
2677 enum format_std_version wanted_type_std
;
2679 if (!(fki
->flags
& (int) FMT_FLAG_ARG_CONVERT
))
2682 wanted_type
= (fci
->types
[len_modifier
.val
].type
2683 ? *fci
->types
[len_modifier
.val
].type
: 0);
2684 wanted_type_name
= fci
->types
[len_modifier
.val
].name
;
2685 wanted_type_std
= fci
->types
[len_modifier
.val
].std
;
2686 if (wanted_type
== 0)
2688 format_warning_at_char (format_string_loc
, format_string_cst
,
2689 format_chars
- orig_format_chars
,
2691 "use of %qs length modifier with %qc type"
2692 " character has either no effect"
2693 " or undefined behavior",
2694 len_modifier
.chars
, format_char
);
2695 /* Heuristic: skip one argument when an invalid length/type
2696 combination is encountered. */
2699 params
= TREE_CHAIN (params
);
2703 /* Warn if non-standard, provided it is more non-standard
2704 than the length and type characters that may already
2705 have been warned for. */
2706 && ADJ_STD (wanted_type_std
) > ADJ_STD (len_modifier
.std
)
2707 && ADJ_STD (wanted_type_std
) > ADJ_STD (fci
->std
))
2709 if (ADJ_STD (wanted_type_std
) > C_STD_VER
)
2710 format_warning_at_char (format_string_loc
, format_string_cst
,
2711 format_chars
- orig_format_chars
,
2713 "%s does not support the %<%%%s%c%> %s format",
2714 C_STD_NAME (wanted_type_std
),
2716 format_char
, fki
->name
);
2722 /* Check type of argument against desired type.
2724 Return true if format parsing is to continue, false otherwise. */
2728 check_argument_type (const format_char_info
*fci
,
2729 const length_modifier
&len_modifier
,
2731 const char *&wanted_type_name
,
2732 const bool suppressed
,
2733 unsigned HOST_WIDE_INT
&arg_num
,
2735 const int alloc_flag
,
2736 const char * const format_start
,
2737 const char * const type_start
,
2738 location_t fmt_param_loc
,
2739 char conversion_char
)
2741 if (info
->first_arg_num
== 0)
2744 if ((fci
->pointer_count
== 0 && wanted_type
== void_type_node
)
2747 if (main_arg_num
!= 0)
2750 warning_at (format_string_loc
, OPT_Wformat_
,
2751 "operand number specified with "
2752 "suppressed assignment");
2754 warning_at (format_string_loc
, OPT_Wformat_
,
2755 "operand number specified for format "
2756 "taking no argument");
2761 format_wanted_type
*wanted_type_ptr
;
2763 if (main_arg_num
!= 0)
2765 arg_num
= main_arg_num
;
2766 params
= main_arg_params
;
2771 if (has_operand_number
> 0)
2773 warning_at (format_string_loc
, OPT_Wformat_
,
2774 "missing $ operand number in format");
2778 has_operand_number
= 0;
2781 wanted_type_ptr
= &main_wanted_type
;
2789 cur_param
= TREE_VALUE (params
);
2790 params
= TREE_CHAIN (params
);
2793 wanted_type_ptr
->wanted_type
= wanted_type
;
2794 wanted_type_ptr
->wanted_type_name
= wanted_type_name
;
2795 wanted_type_ptr
->pointer_count
= fci
->pointer_count
+ alloc_flag
;
2796 wanted_type_ptr
->char_lenient_flag
= 0;
2797 if (strchr (fci
->flags2
, 'c') != 0)
2798 wanted_type_ptr
->char_lenient_flag
= 1;
2799 wanted_type_ptr
->scalar_identity_flag
= 0;
2800 if (len_modifier
.scalar_identity_flag
)
2801 wanted_type_ptr
->scalar_identity_flag
= 1;
2802 wanted_type_ptr
->writing_in_flag
= 0;
2803 wanted_type_ptr
->reading_from_flag
= 0;
2805 wanted_type_ptr
->writing_in_flag
= 1;
2808 if (strchr (fci
->flags2
, 'W') != 0)
2809 wanted_type_ptr
->writing_in_flag
= 1;
2810 if (strchr (fci
->flags2
, 'R') != 0)
2811 wanted_type_ptr
->reading_from_flag
= 1;
2813 wanted_type_ptr
->kind
= CF_KIND_FORMAT
;
2814 wanted_type_ptr
->param
= cur_param
;
2815 wanted_type_ptr
->arg_num
= arg_num
;
2816 wanted_type_ptr
->format_start
= format_start
;
2817 wanted_type_ptr
->format_length
= format_chars
- format_start
;
2818 wanted_type_ptr
->offset_loc
= format_chars
- orig_format_chars
;
2819 wanted_type_ptr
->next
= NULL
;
2820 if (last_wanted_type
!= 0)
2821 last_wanted_type
->next
= wanted_type_ptr
;
2822 if (first_wanted_type
== 0)
2823 first_wanted_type
= wanted_type_ptr
;
2824 last_wanted_type
= wanted_type_ptr
;
2829 wanted_type_ptr
= fwt_pool
.allocate ();
2831 wanted_type
= *fci
->types
[len_modifier
.val
].type
;
2832 wanted_type_name
= fci
->types
[len_modifier
.val
].name
;
2837 if (first_wanted_type
!= 0)
2839 ptrdiff_t offset_to_format_start
= (start_of_this_format
- 1) - orig_format_chars
;
2840 ptrdiff_t offset_to_format_end
= (format_chars
- 1) - orig_format_chars
;
2841 /* By default, use the end of the range for the caret location. */
2842 substring_loc
fmt_loc (fmt_param_loc
, TREE_TYPE (format_string_cst
),
2843 offset_to_format_end
,
2844 offset_to_format_start
, offset_to_format_end
);
2845 ptrdiff_t offset_to_type_start
= type_start
- orig_format_chars
;
2846 check_format_types (fmt_loc
, first_wanted_type
, fki
,
2847 offset_to_type_start
,
2848 conversion_char
, arglocs
);
2854 /* Describes "paired tokens" within the format string that are
2855 expected to be balanced. */
2860 baltoks_t (): singlequote (), doublequote () { }
2862 typedef auto_vec
<const char *> balanced_tokens_t
;
2863 /* Vectors of pointers to opening brackets ('['), curly brackets ('{'),
2864 quoting directives (like GCC "%<"), parentheses, and angle brackets
2865 ('<'). Used to detect unbalanced tokens. */
2866 balanced_tokens_t brackets
;
2867 balanced_tokens_t curly
;
2868 balanced_tokens_t quotdirs
;
2869 balanced_tokens_t parens
;
2870 balanced_tokens_t pointy
;
2871 /* Pointer to the last opening quote. */
2872 const char *singlequote
;
2873 const char *doublequote
;
2876 /* Describes a keyword, operator, or other name. */
2880 const char *name
; /* Keyword/operator name. */
2881 unsigned char len
; /* Its length. */
2882 const char *alt
; /* Alternate spelling. */
2885 /* Helper for initializing global token_t arrays below. */
2886 #define NAME(name) { name, sizeof name - 1, NULL }
2888 /* C/C++ operators that are expected to be quoted within the format
2891 static const token_t c_opers
[] =
2893 NAME ("!="), NAME ("%="), NAME ("&&"), NAME ("&="), NAME ("*="),
2894 NAME ("++"), NAME ("+="), NAME ("--"), NAME ("-="), NAME ("->"),
2895 NAME ("/="), NAME ("<<"), NAME ("<<="), NAME ("<="), NAME ("=="),
2896 NAME (">="), NAME (">>="), NAME (">>"), NAME ("?:"), NAME ("^="),
2897 NAME ("|="), NAME ("||")
2900 static const token_t cxx_opers
[] =
2902 NAME ("->*"), NAME (".*"), NAME ("::"), NAME ("<=>")
2905 /* Common C/C++ keywords that are expected to be quoted within the format
2906 string. Keywords like auto, inline, or volatile are exccluded because
2907 they are sometimes used in common terms like /auto variables/, /inline
2908 function/, or /volatile access/ where they should not be quoted. */
2910 static const token_t c_keywords
[] =
2913 #define NAME(name, alt) { name, sizeof name - 1, alt }
2915 NAME ("alignas", NULL
),
2916 NAME ("alignof", NULL
),
2918 NAME ("bool", NULL
),
2919 NAME ("char", NULL
),
2920 NAME ("const %", NULL
),
2921 NAME ("const-qualified", "%<const%>-qualified"),
2922 NAME ("float", NULL
),
2923 NAME ("ifunc", NULL
),
2925 NAME ("long double", NULL
),
2926 NAME ("long int", NULL
),
2927 NAME ("long long", NULL
),
2928 NAME ("malloc", NULL
),
2929 NAME ("noclone", NULL
),
2930 NAME ("noinline", NULL
),
2931 NAME ("nonnull", NULL
),
2932 NAME ("noreturn", NULL
),
2933 NAME ("nothrow", NULL
),
2934 NAME ("offsetof", NULL
),
2935 NAME ("readonly", "read-only"),
2936 NAME ("readwrite", "read-write"),
2937 NAME ("restrict %", NULL
),
2938 NAME ("restrict-qualified", "%<restrict%>-qualified"),
2939 NAME ("short int", NULL
),
2940 NAME ("signed char", NULL
),
2941 NAME ("signed int", NULL
),
2942 NAME ("signed long", NULL
),
2943 NAME ("signed short", NULL
),
2944 NAME ("sizeof", NULL
),
2945 NAME ("typeof", NULL
),
2946 NAME ("unsigned char", NULL
),
2947 NAME ("unsigned int", NULL
),
2948 NAME ("unsigned long", NULL
),
2949 NAME ("unsigned short", NULL
),
2950 NAME ("volatile %", NULL
),
2951 NAME ("volatile-qualified", "%<volatile%>-qualified"),
2952 NAME ("weakref", NULL
),
2955 static const token_t cxx_keywords
[] =
2957 /* C++ only keywords and operators. */
2958 NAME ("catch", NULL
),
2959 NAME ("constexpr if", NULL
),
2960 NAME ("constexpr", NULL
),
2961 NAME ("consteval", NULL
),
2962 NAME ("decltype", NULL
),
2963 NAME ("nullptr", NULL
),
2964 NAME ("operator delete", NULL
),
2965 NAME ("operator new", NULL
),
2966 NAME ("typeid", NULL
),
2967 NAME ("typeinfo", NULL
)
2970 /* Blacklisted words such as misspellings that should be avoided in favor
2971 of the specified alternatives. */
2974 const char *name
; /* Bad word. */
2975 unsigned char len
; /* Its length. */
2976 const char *alt
; /* Preferred alternative. */
2979 NAME ("arg", "argument"),
2980 NAME ("bitfield", "bit-field"),
2981 NAME ("builtin function", "built-in function"),
2982 NAME ("can not", "cannot"),
2983 NAME ("commandline option", "command-line option"),
2984 NAME ("commandline", "command line"),
2985 NAME ("command line option", "command-line option"),
2986 NAME ("decl", "declaration"),
2987 NAME ("enumeral", "enumerated"),
2988 NAME ("floating point", "floating-point"),
2989 NAME ("non-zero", "nonzero"),
2990 NAME ("reg", "register"),
2991 NAME ("stmt", "statement"),
2994 /* Common contractions that should be avoided in favor of the specified
2999 const char *name
; /* Contraction. */
3000 unsigned char len
; /* Its length. */
3001 const char *alt
; /* Preferred alternative. */
3004 NAME ("can't", "cannot"),
3005 NAME ("didn't", "did not"),
3006 /* These are commonly abused. Avoid diagnosing them for now.
3007 NAME ("isn't", "is not"),
3008 NAME ("don't", "is not"),
3010 NAME ("mustn't", "must not"),
3011 NAME ("needn't", "need not"),
3012 NAME ("should't", "should not"),
3013 NAME ("that's", "that is"),
3014 NAME ("there's", "there is"),
3015 NAME ("they're", "they are"),
3016 NAME ("what's", "what is"),
3017 NAME ("won't", "will not")
3020 /* Check for unquoted TOKENS. FORMAT_STRING_LOC is the location of
3021 the format string, FORMAT_STRING_CST the format string itself (as
3022 a tree), ORIG_FORMAT_CHARS and FORMAT_CHARS are pointers to
3023 the beginning of the format string and the character currently
3024 being processed, and BALTOKS describes paired "tokens" within
3025 the format string that are expected to be balanced.
3026 Returns a pointer to the last processed character or null when
3027 nothing was done. */
3030 check_tokens (const token_t
*tokens
, unsigned ntoks
,
3031 location_t format_string_loc
, tree format_string_cst
,
3032 const char *orig_format_chars
, const char *format_chars
,
3036 const int opt
= OPT_Wformat_diag
;
3037 /* Zero-based starting position of a problem sequence. */
3038 int fmtchrpos
= format_chars
- orig_format_chars
;
3040 /* For identifier-like "words," set to the word length. */
3042 /* Set for an operator, clear for an identifier/word. */
3043 bool is_oper
= false;
3044 bool underscore
= false;
3046 if (format_chars
[0] == '_' || ISALPHA (format_chars
[0]))
3048 while (format_chars
[wlen
] == '_' || ISALNUM (format_chars
[wlen
]))
3050 underscore
|= format_chars
[wlen
] == '_';
3057 for (unsigned i
= 0; i
!= ntoks
; ++i
)
3059 unsigned toklen
= tokens
[i
].len
;
3062 || strncmp (format_chars
, tokens
[i
].name
, toklen
))
3066 && format_chars
- orig_format_chars
> 0
3067 && (TOUPPER (format_chars
[-1]) == 'C'
3068 || TOUPPER (format_chars
[-1]) == 'G'))
3069 return format_chars
+ toklen
- 1; /* Reference to C++ or G++. */
3071 if (ISPUNCT (format_chars
[toklen
- 1]))
3073 if (format_chars
[toklen
- 1] == format_chars
[toklen
])
3074 return NULL
; /* Operator followed by another punctuator. */
3076 else if (ISALNUM (format_chars
[toklen
]))
3077 return NULL
; /* Keyword prefix for a longer word. */
3080 && format_chars
[0] == '-'
3081 && format_chars
[1] == '-'
3082 && ISALNUM (format_chars
[2]))
3083 return NULL
; /* Probably option like --help. */
3085 /* Allow this ugly warning for the time being. */
3087 && format_chars
- orig_format_chars
> 6
3088 && !strncmp (format_chars
- 7, " count >= width of ", 19))
3089 return format_chars
+ 10;
3091 /* The token is a type if it ends in an alphabetic character. */
3092 bool is_type
= (ISALPHA (tokens
[i
].name
[toklen
- 1])
3093 && strchr (tokens
[i
].name
, ' '));
3095 /* Backtrack to the last alphabetic character (for tokens whose
3096 names end in '%'). */
3098 while (!ISALPHA (tokens
[i
].name
[toklen
- 1]))
3101 if (format_warning_substr (format_string_loc
, format_string_cst
,
3102 fmtchrpos
, fmtchrpos
+ toklen
, opt
,
3104 ? G_("unquoted type name %<%.*s%> in format")
3106 ? G_("unquoted operator %<%.*s%> in format")
3107 : G_("unquoted keyword %<%.*s%> in format"))),
3108 toklen
, format_chars
)
3110 inform (format_string_loc
, "use %qs instead", tokens
[i
].alt
);
3112 return format_chars
+ toklen
- 1;
3115 /* Diagnose unquoted __attribute__. Consider any parenthesized
3116 argument to the attribute to avoid redundant warnings for
3117 the double parentheses that might follow. */
3118 if (!strncmp (format_chars
, "__attribute", sizeof "__attribute" - 1))
3120 unsigned nchars
= sizeof "__attribute" - 1;
3121 while ('_' == format_chars
[nchars
])
3124 for (int i
= nchars
; format_chars
[i
]; ++i
)
3125 if (' ' != format_chars
[i
])
3131 if (format_chars
[nchars
] == '(')
3133 baltoks
.parens
.safe_push (format_chars
+ nchars
);
3137 if (format_chars
[nchars
] == '(')
3139 baltoks
.parens
.safe_push (format_chars
+ nchars
);
3143 for (int i
= nchars
; format_chars
[i
]; ++i
)
3144 if (')' == format_chars
[i
])
3146 if (baltoks
.parens
.length () > 0)
3147 baltoks
.parens
.pop ();
3152 if (close
&& format_chars
[nchars
] == ')')
3154 if (baltoks
.parens
.length () > 0)
3155 baltoks
.parens
.pop ();
3160 format_warning_substr (format_string_loc
, format_string_cst
,
3161 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3162 "unquoted attribute in format");
3163 return format_chars
+ nchars
- 1;
3166 /* Diagnose unquoted built-ins. */
3167 if (format_chars
[0] == '_'
3168 && format_chars
[1] == '_'
3169 && (!strncmp (format_chars
+ 2, "atomic", sizeof "atomic" - 1)
3170 || !strncmp (format_chars
+ 2, "builtin", sizeof "builtin" - 1)
3171 || !strncmp (format_chars
+ 2, "sync", sizeof "sync" - 1)))
3173 format_warning_substr (format_string_loc
, format_string_cst
,
3174 fmtchrpos
, fmtchrpos
+ wlen
, opt
,
3175 "unquoted name of built-in function %<%.*s%> "
3177 wlen
, format_chars
);
3178 return format_chars
+ wlen
- 1;
3181 /* Diagnose unquoted substrings of alphanumeric characters containing
3182 underscores. They most likely refer to identifiers and should be
3185 format_warning_substr (format_string_loc
, format_string_cst
,
3186 format_chars
- orig_format_chars
,
3187 format_chars
+ wlen
- orig_format_chars
,
3189 "unquoted identifier or keyword %<%.*s%> in format",
3190 wlen
, format_chars
);
3193 /* Diagnose some common missspellings. */
3194 for (unsigned i
= 0; i
!= sizeof badwords
/ sizeof *badwords
; ++i
)
3196 unsigned badwlen
= strspn (badwords
[i
].name
, " -");
3198 && (wlen
<= badwords
[i
].len
3199 || (wlen
== badwords
[i
].len
+ 1U
3200 && TOUPPER (format_chars
[wlen
- 1]) == 'S'))
3201 && !strncasecmp (format_chars
, badwords
[i
].name
, badwords
[i
].len
))
3203 /* Handle singular as well as plural forms of all bad words
3204 even though the latter don't necessarily make sense for
3205 all of the former (like "can nots"). */
3206 badwlen
= badwords
[i
].len
;
3207 const char *plural
= "";
3208 if (TOUPPER (format_chars
[badwlen
]) == 'S')
3214 format_warning_substr (format_string_loc
, format_string_cst
,
3215 fmtchrpos
, fmtchrpos
+ badwords
[i
].len
,
3217 "misspelled term %<%.*s%> in format; "
3218 "use %<%s%s%> instead",
3219 badwlen
, format_chars
,
3220 badwords
[i
].alt
, plural
);
3222 return format_chars
+ badwords
[i
].len
- 1;
3227 if (!strncasecmp (format_chars
, "c++", 3)
3228 || !strncasecmp (format_chars
, "g++", 3))
3229 return format_chars
+ 2;
3232 return wlen
? format_chars
+ wlen
- 1 : NULL
;
3235 /* Check plain text in a format string of a GCC diagnostic function
3236 for common quoting, punctuation, and spelling mistakes, and issue
3237 -Wformat-diag warnings if they are found. FORMAT_STRING_LOC is
3238 the location of the format string, FORMAT_STRING_CST the format
3239 string itself (as a tree), ORIG_FORMAT_CHARS and FORMAT_CHARS are
3240 pointers to the beginning of the format string and the character
3241 currently being processed, and BALTOKS describes paired "tokens"
3242 within the format string that are expected to be balanced.
3243 Returns a pointer to the last processed character. */
3246 check_plain (location_t format_string_loc
, tree format_string_cst
,
3247 const char *orig_format_chars
, const char *format_chars
,
3251 const int opt
= OPT_Wformat_diag
;
3252 /* Zero-based starting position of a problem sequence. */
3253 int fmtchrpos
= format_chars
- orig_format_chars
;
3255 if (*format_chars
== '%')
3257 /* Diagnose %<%s%> and suggest using %qs instead. */
3258 if (!strncmp (format_chars
, "%<%s%>", 6))
3259 format_warning_substr (format_string_loc
, format_string_cst
,
3260 fmtchrpos
, fmtchrpos
+ 6, opt
,
3261 "quoted %qs directive in format; "
3262 "use %qs instead", "%s", "%qs");
3263 else if (format_chars
- orig_format_chars
> 2
3264 && !strncasecmp (format_chars
- 3, "can%'t", 5)
3265 && !ISALPHA (format_chars
[1]))
3266 format_warning_substr (format_string_loc
,
3268 fmtchrpos
- 3, fmtchrpos
+ 3, opt
,
3269 "contraction %<%.*s%> in format; "
3271 6, format_chars
- 3, "cannot");
3273 return format_chars
;
3276 if (baltoks
.quotdirs
.length ())
3278 /* Skip over all plain text within a quoting directive until
3279 the next directive. */
3280 while (*format_chars
&& '%' != *format_chars
)
3283 return format_chars
;
3286 /* The length of the problem sequence. */
3289 /* Diagnose any whitespace characters other than <space> but only
3290 leading, trailing, and two or more consecutive <space>s. Do
3291 this before diagnosing control characters because whitespace
3292 is a subset of controls. */
3293 const char *other_than_space
= NULL
;
3294 while (ISSPACE (format_chars
[nchars
]))
3296 if (format_chars
[nchars
] != ' ' && !other_than_space
)
3297 other_than_space
= format_chars
+ nchars
;
3303 /* This is the most common problem: go the extra mile to describe
3304 the problem in as much helpful detail as possible. */
3305 if (other_than_space
)
3307 format_warning_substr (format_string_loc
, format_string_cst
,
3308 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3309 "unquoted whitespace character %qc in format",
3311 return format_chars
+ nchars
- 1;
3315 /* Accept strings of leading spaces with no warning. */
3316 return format_chars
+ nchars
- 1;
3318 if (!format_chars
[nchars
])
3320 format_warning_substr (format_string_loc
, format_string_cst
,
3321 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3322 "spurious trailing space in format");
3323 return format_chars
+ nchars
- 1;
3329 && orig_format_chars
< format_chars
3330 && format_chars
[-1] == '.'
3331 && format_chars
[0] == ' '
3332 && format_chars
[1] == ' ')
3334 /* A period followed by two spaces. */
3335 if (ISUPPER (*orig_format_chars
))
3337 /* If the part before the period is a capitalized
3338 sentence check to make sure that what follows
3339 is also capitalized. */
3340 if (ISLOWER (format_chars
[2]))
3341 format_warning_substr (format_string_loc
, format_string_cst
,
3342 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3343 "inconsistent capitalization in "
3348 format_warning_substr (format_string_loc
, format_string_cst
,
3349 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3350 "unquoted sequence of %i consecutive "
3351 "space characters in format", nchars
);
3352 return format_chars
+ nchars
- 1;
3355 format_chars
+= nchars
;
3359 fmtchrpos
= format_chars
- orig_format_chars
;
3361 /* Diagnose any unquoted control characters other than the terminating
3363 while (format_chars
[nchars
] && ISCNTRL (format_chars
[nchars
]))
3368 format_warning_substr (format_string_loc
, format_string_cst
,
3369 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3370 "unquoted control characters in format");
3371 return format_chars
+ nchars
- 1;
3375 format_warning_substr (format_string_loc
, format_string_cst
,
3376 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3377 "unquoted control character %qc in format",
3379 return format_chars
+ nchars
- 1;
3382 if (ISPUNCT (format_chars
[0]))
3384 size_t nelts
= sizeof c_opers
/ sizeof *c_opers
;
3385 if (const char *ret
= check_tokens (c_opers
, nelts
,
3386 format_string_loc
, format_string_cst
,
3387 orig_format_chars
, format_chars
,
3391 nelts
= c_dialect_cxx () ? sizeof cxx_opers
/ sizeof *cxx_opers
: 0;
3392 if (const char *ret
= check_tokens (cxx_opers
, nelts
,
3393 format_string_loc
, format_string_cst
,
3394 orig_format_chars
, format_chars
,
3399 if (ISALPHA (format_chars
[0]))
3401 size_t nelts
= sizeof c_keywords
/ sizeof *c_keywords
;
3402 if (const char *ret
= check_tokens (c_keywords
, nelts
,
3403 format_string_loc
, format_string_cst
,
3404 orig_format_chars
, format_chars
,
3408 nelts
= c_dialect_cxx () ? sizeof cxx_keywords
/ sizeof *cxx_keywords
: 0;
3409 if (const char *ret
= check_tokens (cxx_keywords
, nelts
,
3410 format_string_loc
, format_string_cst
,
3411 orig_format_chars
, format_chars
,
3418 /* Diagnose unquoted options. */
3419 if ((format_chars
== orig_format_chars
3420 || format_chars
[-1] == ' ')
3421 && format_chars
[0] == '-'
3422 && ((format_chars
[1] == '-'
3423 && ISALPHA (format_chars
[2]))
3424 || ISALPHA (format_chars
[1])))
3427 while (ISALNUM (format_chars
[nchars
])
3428 || '_' == format_chars
[nchars
]
3429 || '-' == format_chars
[nchars
]
3430 || '+' == format_chars
[nchars
])
3433 format_warning_substr (format_string_loc
, format_string_cst
,
3434 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3435 "unquoted option name %<%.*s%> in format",
3436 nchars
, format_chars
);
3437 return format_chars
+ nchars
- 1;
3440 /* Diagnose leading, trailing, and two or more consecutive punctuation
3442 const char *unbalanced
= NULL
;
3443 while ('%' != format_chars
[nchars
]
3444 && ISPUNCT (format_chars
[nchars
])
3447 switch (format_chars
[nchars
])
3450 baltoks
.brackets
.safe_push (format_chars
+ nchars
);
3453 baltoks
.curly
.safe_push (format_chars
+ nchars
);
3456 baltoks
.parens
.safe_push (format_chars
+ nchars
);
3459 baltoks
.pointy
.safe_push (format_chars
+ nchars
);
3463 if (baltoks
.brackets
.length () > 0)
3464 baltoks
.brackets
.pop ();
3466 unbalanced
= format_chars
+ nchars
;
3469 if (baltoks
.curly
.length () > 0)
3470 baltoks
.curly
.pop ();
3472 unbalanced
= format_chars
+ nchars
;
3475 if (baltoks
.parens
.length () > 0)
3476 baltoks
.parens
.pop ();
3478 unbalanced
= format_chars
+ nchars
;
3481 if (baltoks
.pointy
.length () > 0)
3482 baltoks
.pointy
.pop ();
3484 unbalanced
= format_chars
+ nchars
;
3493 format_warning_substr (format_string_loc
, format_string_cst
,
3494 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3495 "unbalanced punctuation character %qc in format",
3497 return format_chars
+ nchars
- 1;
3502 /* Consider any identifier that follows the pound ('#') sign
3503 a preprocessing directive. */
3505 && format_chars
[0] == '#'
3506 && ISALPHA (format_chars
[1]))
3508 while (ISALNUM (format_chars
[nchars
])
3509 || format_chars
[nchars
] == '_')
3512 format_warning_substr (format_string_loc
, format_string_cst
,
3513 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3514 "unquoted preprocessing directive %<%.*s%> "
3515 "in format", nchars
, format_chars
);
3516 return format_chars
+ nchars
- 1;
3519 /* Diagnose a bare single quote. */
3521 && format_chars
[0] == '\''
3522 && format_chars
- orig_format_chars
3523 && ISALPHA (format_chars
[-1])
3524 && ISALPHA (format_chars
[1]))
3526 /* Diagnose a subset of contractions that are best avoided. */
3527 for (unsigned i
= 0; i
!= sizeof contrs
/ sizeof *contrs
; ++i
)
3529 const char *apos
= strchr (contrs
[i
].name
, '\'');
3530 gcc_assert (apos
!= NULL
);
3531 int off
= apos
- contrs
[i
].name
;
3533 if (format_chars
- orig_format_chars
>= off
3534 && !strncmp (format_chars
- off
,
3535 contrs
[i
].name
, contrs
[i
].len
))
3537 format_warning_substr (format_string_loc
,
3539 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3540 "contraction %<%.*s%> in format; "
3542 contrs
[i
].len
, contrs
[i
].name
,
3544 return format_chars
+ nchars
- 1;
3548 if (format_warning_substr (format_string_loc
, format_string_cst
,
3549 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3550 "bare apostrophe %<'%> in format"))
3551 inform (format_string_loc
,
3552 "if avoiding the apostrophe is not feasible, enclose "
3553 "it in a pair of %qs and %qs directives instead",
3555 return format_chars
+ nchars
- 1;
3558 /* Diagnose a backtick (grave accent). */
3560 && format_chars
[0] == '`')
3562 if (format_warning_substr (format_string_loc
, format_string_cst
,
3563 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3564 "grave accent %<`%> in format"))
3565 inform (format_string_loc
,
3566 "use the apostrophe directive %qs instead", "%'");
3567 return format_chars
+ nchars
- 1;
3570 /* Diagnose a punctuation character after a space. */
3572 && format_chars
- orig_format_chars
3573 && format_chars
[-1] == ' '
3574 && strspn (format_chars
, "!?:;.,") == 1)
3576 format_warning_substr (format_string_loc
, format_string_cst
,
3577 fmtchrpos
- 1, fmtchrpos
, opt
,
3578 "space followed by punctuation character "
3579 "%<%c%>", format_chars
[0]);
3580 return format_chars
;
3585 if (!strncmp (format_chars
, "\"%s\"", 4))
3587 if (format_warning_substr (format_string_loc
, format_string_cst
,
3588 fmtchrpos
, fmtchrpos
+ 4, opt
,
3589 "quoted %qs directive in format",
3591 inform (format_string_loc
, "if using %qs is not feasible, "
3592 "use %qs instead", "%qs", "\"%-s\"");
3595 if (format_chars
[0] == '"')
3597 baltoks
.doublequote
= baltoks
.doublequote
? NULL
: format_chars
;
3598 return format_chars
+ nchars
- 1;
3600 if (format_chars
[0] == '\'')
3602 baltoks
.singlequote
= baltoks
.singlequote
? NULL
: format_chars
;
3603 return format_chars
+ nchars
- 1;
3610 && format_chars
[0] == '(')
3611 ; /* Text beginning in an open parenthesis. */
3612 else if (nchars
== 3
3613 && !strncmp (format_chars
, "...", 3)
3615 ; /* Text beginning in an ellipsis. */
3618 format_warning_substr (format_string_loc
, format_string_cst
,
3619 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3620 "spurious leading punctuation sequence "
3621 "%<%.*s%> in format",
3622 nchars
, format_chars
);
3623 return format_chars
+ nchars
- 1;
3626 else if (!format_chars
[nchars
])
3629 && (format_chars
[nchars
- 1] == ':'
3630 || format_chars
[nchars
- 1] == ')'))
3631 ; /* Text ending in a colon or a closing parenthesis. */
3632 else if (nchars
== 1
3633 && ((ISUPPER (*orig_format_chars
)
3634 && format_chars
[nchars
- 1] == '.')
3635 || strspn (format_chars
+ nchars
- 1, "?])") == 1))
3636 ; /* Capitalized sentence terminated by a single period,
3637 or text ending in a question mark, closing bracket,
3639 else if (nchars
== 2
3640 && format_chars
[0] == '?'
3641 && format_chars
[1] == ')')
3642 ; /* A question mark after a closing parenthetical note. */
3643 else if (nchars
== 2
3644 && format_chars
[0] == ')'
3645 && (format_chars
[1] == '?'
3646 || format_chars
[1] == ';'
3647 || format_chars
[1] == ':'
3648 || (ISUPPER (*orig_format_chars
)
3649 && format_chars
[1] == '.')))
3650 ; /* Closing parenthetical note followed by a question mark,
3651 semicolon, or colon at the end of the string, or by
3652 a period at the end of a capitalized sentence. */
3653 else if (nchars
== 3
3654 && format_chars
- orig_format_chars
> 0
3655 && !strncmp (format_chars
, "...", 3))
3656 ; /* Text ending in the ellipsis. */
3658 format_warning_substr (format_string_loc
, format_string_cst
,
3659 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3660 "spurious trailing punctuation sequence "
3661 "%<%.*s%> in format",
3662 nchars
, format_chars
);
3664 return format_chars
+ nchars
- 1;
3666 else if (nchars
== 2
3667 && format_chars
[0] == ')'
3668 && (format_chars
[1] == ':'
3669 || format_chars
[1] == ';'
3670 || format_chars
[1] == ',')
3671 && format_chars
[2] == ' ')
3672 ; /* Closing parenthetical note followed by a colon, semicolon
3673 or a comma followed by a space in the middle of the string. */
3674 else if (nchars
> 1)
3675 format_warning_substr (format_string_loc
, format_string_cst
,
3676 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3677 "unquoted sequence of %i consecutive "
3678 "punctuation characters %q.*s in format",
3679 nchars
, nchars
, format_chars
);
3680 return format_chars
+ nchars
- 1;
3685 /* Finally, diagnose any unquoted non-graph, non-punctuation characters
3686 other than the terminating NUL. */
3687 while (format_chars
[nchars
]
3688 && '%' != format_chars
[nchars
]
3689 && !ISPUNCT (format_chars
[nchars
])
3690 && !ISGRAPH (format_chars
[nchars
]))
3695 format_warning_substr (format_string_loc
, format_string_cst
,
3696 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3697 "unquoted non-graph characters in format");
3698 return format_chars
+ nchars
- 1;
3702 format_warning_substr (format_string_loc
, format_string_cst
,
3703 fmtchrpos
, fmtchrpos
+ nchars
, opt
,
3704 "unquoted non-graph character %qc in format",
3706 return format_chars
+ nchars
- 1;
3709 return format_chars
;
3712 /* Diagnose unbalanced tokens described by BALTOKS in format string
3713 ORIG_FORMAT_CHARS and the corresponding FORMAT_STRING_CST. */
3716 maybe_diag_unbalanced_tokens (location_t format_string_loc
,
3717 const char *orig_format_chars
,
3718 tree format_string_cst
,
3721 const char *unbalanced
= NULL
;
3723 if (baltoks
.brackets
.length ())
3724 unbalanced
= baltoks
.brackets
.pop ();
3725 else if (baltoks
.curly
.length ())
3726 unbalanced
= baltoks
.curly
.pop ();
3727 else if (baltoks
.parens
.length ())
3728 unbalanced
= baltoks
.parens
.pop ();
3729 else if (baltoks
.pointy
.length ())
3730 unbalanced
= baltoks
.pointy
.pop ();
3733 format_warning_at_char (format_string_loc
, format_string_cst
,
3734 unbalanced
- orig_format_chars
+ 1,
3736 "unbalanced punctuation character %<%c%> in format",
3739 if (baltoks
.quotdirs
.length ())
3740 format_warning_at_char (format_string_loc
, format_string_cst
,
3741 baltoks
.quotdirs
.pop () - orig_format_chars
,
3743 "unterminated quoting directive");
3746 = baltoks
.singlequote
? baltoks
.singlequote
: baltoks
.doublequote
;
3749 format_warning_at_char (format_string_loc
, format_string_cst
,
3750 quote
- orig_format_chars
+ 1,
3752 "unterminated quote character %<%c%> in format",
3756 /* Do the main part of checking a call to a format function. FORMAT_CHARS
3757 is the NUL-terminated format string (which at this point may contain
3758 internal NUL characters); FORMAT_LENGTH is its length (excluding the
3759 terminating NUL character). ARG_NUM is one less than the number of
3760 the first format argument to check; PARAMS points to that format
3761 argument in the list of arguments. */
3764 check_format_info_main (format_check_results
*res
,
3765 function_format_info
*info
, const char *format_chars
,
3766 location_t fmt_param_loc
, tree format_string_cst
,
3767 int format_length
, tree params
,
3768 unsigned HOST_WIDE_INT arg_num
,
3769 object_allocator
<format_wanted_type
> &fwt_pool
,
3770 vec
<location_t
> *arglocs
)
3772 const char * const orig_format_chars
= format_chars
;
3773 const tree first_fillin_param
= params
;
3775 const format_kind_info
* const fki
= &format_types
[info
->format_type
];
3776 const format_flag_spec
* const flag_specs
= fki
->flag_specs
;
3777 const location_t format_string_loc
= res
->format_string_loc
;
3779 /* -1 if no conversions taking an operand have been found; 0 if one has
3780 and it didn't use $; 1 if $ formats are in use. */
3781 int has_operand_number
= -1;
3783 /* Vectors of pointers to opening quoting directives (like GCC "%<"),
3784 opening braces, brackets, and parentheses. Used to detect unbalanced
3788 /* Pointers to the most recent color directives (like GCC's "%r or %R").
3789 A starting color directive much be terminated before the end of
3790 the format string. A terminating directive makes no sense without
3791 a prior starting directive. */
3792 const char *color_begin
= NULL
;
3793 const char *color_end
= NULL
;
3795 init_dollar_format_checking (info
->first_arg_num
, first_fillin_param
);
3797 /* In GCC diagnostic functions check plain directives (substrings within
3798 the format string that don't start with %) for quoting and punctuations
3800 bool ck_plain
= (!info
->is_raw
3801 && (info
->format_type
== gcc_diag_format_type
3802 || info
->format_type
== gcc_tdiag_format_type
3803 || info
->format_type
== gcc_cdiag_format_type
3804 || info
->format_type
== gcc_cxxdiag_format_type
));
3806 while (*format_chars
!= 0)
3809 format_chars
= check_plain (format_string_loc
,
3811 orig_format_chars
, format_chars
,
3814 if (*format_chars
== 0 || *format_chars
++ != '%')
3817 if (*format_chars
== 0)
3819 format_warning_at_char (format_string_loc
, format_string_cst
,
3820 format_chars
- orig_format_chars
,
3822 "spurious trailing %<%%%> in format");
3825 if (*format_chars
== '%')
3831 /* ARGUMENT_PARSER ctor takes FORMAT_CHARS by reference and calls
3832 to ARG_PARSER members may modify the variable. */
3833 flag_chars_t flag_chars
;
3834 argument_parser
arg_parser (info
, format_chars
, format_string_cst
,
3835 orig_format_chars
, format_string_loc
,
3836 flag_chars
, has_operand_number
,
3837 first_fillin_param
, fwt_pool
, arglocs
);
3839 if (!arg_parser
.read_any_dollar ())
3842 if (!arg_parser
.read_format_flags ())
3845 /* Read any format width, possibly * or *m$. */
3846 if (!arg_parser
.read_any_format_width (params
, arg_num
))
3849 /* Read any format left precision (must be a number, not *). */
3850 arg_parser
.read_any_format_left_precision ();
3852 /* Read any format precision, possibly * or *m$. */
3853 if (!arg_parser
.read_any_format_precision (params
, arg_num
))
3856 const char *format_start
= format_chars
;
3858 arg_parser
.handle_alloc_chars ();
3860 /* The rest of the conversion specification is the length modifier
3861 (if any), and the conversion specifier, so this is where the
3862 type information starts. If we need to issue a suggestion
3863 about a type mismatch, then we should preserve everything up
3865 const char *type_start
= format_chars
;
3867 /* Read any length modifier, if this kind of format has them. */
3868 const length_modifier len_modifier
3869 = arg_parser
.read_any_length_modifier ();
3871 /* Read any modifier (strftime E/O). */
3872 arg_parser
.read_any_other_modifier ();
3874 char format_char
= *format_chars
;
3875 if (format_char
== 0
3876 || (!(fki
->flags
& (int) FMT_FLAG_FANCY_PERCENT_OK
)
3877 && format_char
== '%'))
3879 format_warning_at_char (format_string_loc
, format_string_cst
,
3880 format_chars
- orig_format_chars
,
3882 "conversion lacks type at end of format");
3887 const format_char_info
* const fci
3888 = arg_parser
.find_format_char_info (format_char
);
3892 flag_chars
.validate (fki
, fci
, flag_specs
, format_chars
,
3894 format_string_loc
, orig_format_chars
, format_char
,
3895 baltoks
.quotdirs
.length () > 0);
3897 const int alloc_flag
= flag_chars
.get_alloc_flag (fki
);
3898 const bool suppressed
= flag_chars
.assignment_suppression_p (fki
);
3900 /* Diagnose nested or unmatched quoting directives such as GCC's
3901 "%<...%<" and "%>...%>". */
3902 bool quot_begin_p
= strchr (fci
->flags2
, '<');
3903 bool quot_end_p
= strchr (fci
->flags2
, '>');
3905 if (quot_begin_p
&& !quot_end_p
)
3907 if (baltoks
.quotdirs
.length ())
3908 format_warning_at_char (format_string_loc
, format_string_cst
,
3909 format_chars
- orig_format_chars
,
3911 "nested quoting directive");
3912 baltoks
.quotdirs
.safe_push (format_chars
);
3914 else if (!quot_begin_p
&& quot_end_p
)
3916 if (baltoks
.quotdirs
.length ())
3917 baltoks
.quotdirs
.pop ();
3919 format_warning_at_char (format_string_loc
, format_string_cst
,
3920 format_chars
- orig_format_chars
,
3922 "unmatched quoting directive");
3925 bool color_begin_p
= strchr (fci
->flags2
, '/');
3928 color_begin
= format_chars
;
3931 else if (strchr (fci
->flags2
, '\\'))
3934 format_warning_at_char (format_string_loc
, format_string_cst
,
3935 format_chars
- orig_format_chars
,
3937 "%qc directive redundant after prior "
3938 "occurence of the same", format_char
);
3939 else if (!color_begin
)
3940 format_warning_at_char (format_string_loc
, format_string_cst
,
3941 format_chars
- orig_format_chars
,
3943 "unmatched color reset directive");
3944 color_end
= format_chars
;
3947 /* Diagnose directives that shouldn't appear in a quoted sequence.
3948 (They are denoted by a double quote in FLAGS2.) */
3949 if (baltoks
.quotdirs
.length ())
3951 if (strchr (fci
->flags2
, '"'))
3952 format_warning_at_char (format_string_loc
, format_string_cst
,
3953 format_chars
- orig_format_chars
,
3955 "%qc conversion used within a quoted "
3960 /* Validate the pairs of flags used. */
3961 arg_parser
.validate_flag_pairs (fci
, format_char
);
3963 arg_parser
.give_y2k_warnings (fci
, format_char
);
3965 arg_parser
.parse_any_scan_set (fci
);
3967 tree wanted_type
= NULL
;
3968 const char *wanted_type_name
= NULL
;
3970 if (!arg_parser
.handle_conversions (fci
, len_modifier
,
3971 wanted_type
, wanted_type_name
,
3977 arg_parser
.main_wanted_type
.next
= NULL
;
3979 /* Finally. . .check type of argument against desired type! */
3980 if (!arg_parser
.check_argument_type (fci
, len_modifier
,
3981 wanted_type
, wanted_type_name
,
3985 format_start
, type_start
,
3991 if (format_chars
- orig_format_chars
!= format_length
)
3992 format_warning_at_char (format_string_loc
, format_string_cst
,
3993 format_chars
+ 1 - orig_format_chars
,
3994 OPT_Wformat_contains_nul
,
3995 "embedded %<\\0%> in format");
3996 if (info
->first_arg_num
!= 0 && params
!= 0
3997 && has_operand_number
<= 0)
3999 res
->number_other
--;
4000 res
->number_extra_args
++;
4002 if (has_operand_number
> 0)
4003 finish_dollar_format_checking (res
, fki
->flags
& (int) FMT_FLAG_DOLLAR_GAP_POINTER_OK
);
4005 maybe_diag_unbalanced_tokens (format_string_loc
, orig_format_chars
,
4006 format_string_cst
, baltoks
);
4008 if (color_begin
&& !color_end
)
4009 format_warning_at_char (format_string_loc
, format_string_cst
,
4010 color_begin
- orig_format_chars
,
4011 OPT_Wformat_
, "unterminated color directive");
4014 /* Check the argument types from a single format conversion (possibly
4015 including width and precision arguments).
4017 FMT_LOC is the location of the format conversion.
4019 TYPES is a singly-linked list expressing the parts of the format
4020 conversion that expect argument types, and the arguments they
4023 OFFSET_TO_TYPE_START is the offset within the execution-charset encoded
4024 format string to where type information begins for the conversion
4025 (the length modifier and conversion specifier).
4027 CONVERSION_CHAR is the user-provided conversion specifier.
4031 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
4033 then FMT_LOC covers this range:
4035 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
4038 and TYPES in this case is a three-entry singly-linked list consisting of:
4039 (1) the check for the field width here:
4040 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
4043 (2) the check for the field precision here:
4044 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
4047 (3) the check for the length modifier and conversion char here:
4048 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
4052 OFFSET_TO_TYPE_START is 13, the offset to the "lld" within the
4055 0000000000111111111122
4056 0123456789012345678901
4057 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
4059 | ` CONVERSION_CHAR: 'd'
4060 type starts here. */
4063 check_format_types (const substring_loc
&fmt_loc
,
4064 format_wanted_type
*types
, const format_kind_info
*fki
,
4065 int offset_to_type_start
,
4066 char conversion_char
,
4067 vec
<location_t
> *arglocs
)
4069 for (; types
!= 0; types
= types
->next
)
4079 wanted_type
= types
->wanted_type
;
4080 arg_num
= types
->arg_num
;
4082 /* The following should not occur here. */
4083 gcc_assert (wanted_type
);
4084 gcc_assert (wanted_type
!= void_type_node
|| types
->pointer_count
);
4086 if (types
->pointer_count
== 0)
4087 wanted_type
= lang_hooks
.types
.type_promotes_to (wanted_type
);
4089 wanted_type
= TYPE_MAIN_VARIANT (wanted_type
);
4091 cur_param
= types
->param
;
4094 format_type_warning (fmt_loc
, UNKNOWN_LOCATION
, types
, wanted_type
,
4095 NULL
, fki
, offset_to_type_start
,
4100 cur_type
= TREE_TYPE (cur_param
);
4101 if (cur_type
== error_mark_node
)
4103 orig_cur_type
= cur_type
;
4106 location_t param_loc
= UNKNOWN_LOCATION
;
4107 if (EXPR_HAS_LOCATION (cur_param
))
4108 param_loc
= EXPR_LOCATION (cur_param
);
4111 /* arg_num is 1-based. */
4112 gcc_assert (types
->arg_num
> 0);
4113 param_loc
= (*arglocs
)[types
->arg_num
- 1];
4116 STRIP_NOPS (cur_param
);
4118 /* Check the types of any additional pointer arguments
4119 that precede the "real" argument. */
4120 for (i
= 0; i
< types
->pointer_count
; ++i
)
4122 if (TREE_CODE (cur_type
) == POINTER_TYPE
)
4124 cur_type
= TREE_TYPE (cur_type
);
4125 if (cur_type
== error_mark_node
)
4128 /* Check for writing through a NULL pointer. */
4129 if (types
->writing_in_flag
4132 && integer_zerop (cur_param
))
4133 warning (OPT_Wformat_
, "writing through null pointer "
4134 "(argument %d)", arg_num
);
4136 /* Check for reading through a NULL pointer. Ignore
4137 printf-family of functions as they are checked for
4138 null arguments by the middle-end. */
4139 if (fki
->conversion_specs
!= print_char_table
4140 && types
->reading_from_flag
4143 && integer_zerop (cur_param
))
4144 warning (OPT_Wformat_
, "reading through null pointer "
4145 "(argument %d)", arg_num
);
4147 if (cur_param
!= 0 && TREE_CODE (cur_param
) == ADDR_EXPR
)
4148 cur_param
= TREE_OPERAND (cur_param
, 0);
4152 /* See if this is an attempt to write into a const type with
4153 scanf or with printf "%n". Note: the writing in happens
4154 at the first indirection only, if for example
4155 void * const * is passed to scanf %p; passing
4156 const void ** is simply passing an incompatible type. */
4157 if (types
->writing_in_flag
4159 && (TYPE_READONLY (cur_type
)
4161 && (CONSTANT_CLASS_P (cur_param
)
4162 || (DECL_P (cur_param
)
4163 && TREE_READONLY (cur_param
))))))
4164 warning (OPT_Wformat_
, "writing into constant object "
4165 "(argument %d)", arg_num
);
4167 /* If there are extra type qualifiers beyond the first
4168 indirection, then this makes the types technically
4172 && (TYPE_READONLY (cur_type
)
4173 || TYPE_VOLATILE (cur_type
)
4174 || TYPE_ATOMIC (cur_type
)
4175 || TYPE_RESTRICT (cur_type
)))
4176 warning (OPT_Wformat_
, "extra type qualifiers in format "
4177 "argument (argument %d)",
4183 format_type_warning (fmt_loc
, param_loc
,
4184 types
, wanted_type
, orig_cur_type
, fki
,
4185 offset_to_type_start
, conversion_char
);
4190 if (i
< types
->pointer_count
)
4193 cur_type
= TYPE_MAIN_VARIANT (cur_type
);
4195 /* Check whether the argument type is a character type. This leniency
4196 only applies to certain formats, flagged with 'c'. */
4197 if (types
->char_lenient_flag
)
4198 char_type_flag
= (cur_type
== char_type_node
4199 || cur_type
== signed_char_type_node
4200 || cur_type
== unsigned_char_type_node
);
4202 /* Check the type of the "real" argument, if there's a type we want. */
4203 if (lang_hooks
.types_compatible_p (wanted_type
, cur_type
))
4205 /* If we want 'void *', allow any pointer type.
4206 (Anything else would already have got a warning.)
4207 With -Wpedantic, only allow pointers to void and to character
4209 if (wanted_type
== void_type_node
4210 && (!pedantic
|| (i
== 1 && char_type_flag
)))
4212 /* Don't warn about differences merely in signedness, unless
4213 -Wpedantic. With -Wpedantic, warn if the type is a pointer
4214 target and not a character type, and for character types at
4215 a second level of indirection. */
4216 if (TREE_CODE (wanted_type
) == INTEGER_TYPE
4217 && TREE_CODE (cur_type
) == INTEGER_TYPE
4218 && ((!pedantic
&& !warn_format_signedness
)
4219 || (i
== 0 && !warn_format_signedness
)
4220 || (i
== 1 && char_type_flag
))
4221 && (TYPE_UNSIGNED (wanted_type
)
4222 ? wanted_type
== c_common_unsigned_type (cur_type
)
4223 : wanted_type
== c_common_signed_type (cur_type
)))
4225 /* Don't warn about differences merely in signedness if we know
4226 that the current type is integer-promoted and its original type
4227 was unsigned such as that it is in the range of WANTED_TYPE. */
4228 if (TREE_CODE (wanted_type
) == INTEGER_TYPE
4229 && TREE_CODE (cur_type
) == INTEGER_TYPE
4230 && warn_format_signedness
4231 && TYPE_UNSIGNED (wanted_type
)
4232 && cur_param
!= NULL_TREE
4233 && TREE_CODE (cur_param
) == NOP_EXPR
)
4235 tree t
= TREE_TYPE (TREE_OPERAND (cur_param
, 0));
4236 if (TYPE_UNSIGNED (t
)
4237 && cur_type
== lang_hooks
.types
.type_promotes_to (t
))
4240 /* Likewise, "signed char", "unsigned char" and "char" are
4241 equivalent but the above test won't consider them equivalent. */
4242 if (wanted_type
== char_type_node
4243 && (!pedantic
|| i
< 2)
4246 if (types
->scalar_identity_flag
4247 && (TREE_CODE (cur_type
) == TREE_CODE (wanted_type
)
4248 || (INTEGRAL_TYPE_P (cur_type
)
4249 && INTEGRAL_TYPE_P (wanted_type
)))
4250 && TYPE_PRECISION (cur_type
) == TYPE_PRECISION (wanted_type
))
4252 /* Now we have a type mismatch. */
4253 format_type_warning (fmt_loc
, param_loc
, types
,
4254 wanted_type
, orig_cur_type
, fki
,
4255 offset_to_type_start
, conversion_char
);
4259 /* Given type TYPE, attempt to dereference the type N times
4260 (e.g. from ("int ***", 2) to "int *")
4262 Return the derefenced type, with any qualifiers
4263 such as "const" stripped from the result, or
4264 NULL if unsuccessful (e.g. TYPE is not a pointer type). */
4267 deref_n_times (tree type
, int n
)
4271 for (int i
= n
; i
> 0; i
--)
4273 if (TREE_CODE (type
) != POINTER_TYPE
)
4275 type
= TREE_TYPE (type
);
4277 /* Strip off any "const" etc. */
4278 return build_qualified_type (type
, 0);
4281 /* Lookup the format code for FORMAT_LEN within FLI,
4282 returning the string code for expressing it, or NULL
4283 if it is not found. */
4286 get_modifier_for_format_len (const format_length_info
*fli
,
4287 enum format_lengths format_len
)
4289 for (; fli
->name
; fli
++)
4291 if (fli
->index
== format_len
)
4293 if (fli
->double_index
== format_len
)
4294 return fli
->double_name
;
4301 namespace selftest
{
4304 test_get_modifier_for_format_len ()
4307 get_modifier_for_format_len (printf_length_specs
, FMT_LEN_h
));
4309 get_modifier_for_format_len (printf_length_specs
, FMT_LEN_hh
));
4311 get_modifier_for_format_len (printf_length_specs
, FMT_LEN_L
));
4313 get_modifier_for_format_len (printf_length_specs
, FMT_LEN_none
));
4316 } // namespace selftest
4318 #endif /* CHECKING_P */
4320 /* Determine if SPEC_TYPE and ARG_TYPE are sufficiently similar for a
4321 format_type_detail using SPEC_TYPE to be offered as a suggestion for
4322 Wformat type errors where the argument has type ARG_TYPE. */
4325 matching_type_p (tree spec_type
, tree arg_type
)
4327 gcc_assert (spec_type
);
4328 gcc_assert (arg_type
);
4330 /* If any of the types requires structural equality, we can't compare
4331 their canonical types. */
4332 if (TYPE_STRUCTURAL_EQUALITY_P (spec_type
)
4333 || TYPE_STRUCTURAL_EQUALITY_P (arg_type
))
4336 spec_type
= TYPE_CANONICAL (spec_type
);
4337 arg_type
= TYPE_CANONICAL (arg_type
);
4339 if (TREE_CODE (spec_type
) == INTEGER_TYPE
4340 && TREE_CODE (arg_type
) == INTEGER_TYPE
4341 && (TYPE_UNSIGNED (spec_type
)
4342 ? spec_type
== c_common_unsigned_type (arg_type
)
4343 : spec_type
== c_common_signed_type (arg_type
)))
4346 return spec_type
== arg_type
;
4349 /* Subroutine of get_format_for_type.
4351 Generate a string containing the length modifier and conversion specifier
4352 that should be used to format arguments of type ARG_TYPE within FKI
4353 (effectively the inverse of the checking code).
4355 If CONVERSION_CHAR is not zero (the first pass), the resulting suggestion
4356 is required to use it, for correcting bogus length modifiers.
4357 If CONVERSION_CHAR is zero (the second pass), then allow any suggestion
4358 that matches ARG_TYPE.
4360 If successful, returns a non-NULL string which should be freed
4362 Otherwise, returns NULL. */
4365 get_format_for_type_1 (const format_kind_info
*fki
, tree arg_type
,
4366 char conversion_char
)
4368 gcc_assert (arg_type
);
4370 const format_char_info
*spec
;
4371 for (spec
= &fki
->conversion_specs
[0];
4375 if (conversion_char
)
4376 if (!strchr (spec
->format_chars
, conversion_char
))
4379 tree effective_arg_type
= deref_n_times (arg_type
,
4380 spec
->pointer_count
);
4381 if (!effective_arg_type
)
4383 for (int i
= 0; i
< FMT_LEN_MAX
; i
++)
4385 const format_type_detail
*ftd
= &spec
->types
[i
];
4388 if (matching_type_p (*ftd
->type
, effective_arg_type
))
4390 const char *len_modifier
4391 = get_modifier_for_format_len (fki
->length_char_specs
,
4392 (enum format_lengths
)i
);
4396 if (conversion_char
)
4397 /* We found a match, using the given conversion char - the
4398 length modifier was incorrect (or absent).
4399 Provide a suggestion using the conversion char with the
4400 correct length modifier for the type. */
4401 return xasprintf ("%s%c", len_modifier
, conversion_char
);
4403 /* 2nd pass: no match was possible using the user-provided
4404 conversion char, but we do have a match without using it.
4405 Provide a suggestion using the first conversion char
4406 listed for the given type. */
4407 return xasprintf ("%s%c", len_modifier
, spec
->format_chars
[0]);
4415 /* Generate a string containing the length modifier and conversion specifier
4416 that should be used to format arguments of type ARG_TYPE within FKI
4417 (effectively the inverse of the checking code).
4419 If successful, returns a non-NULL string which should be freed
4421 Otherwise, returns NULL. */
4424 get_format_for_type (const format_kind_info
*fki
, tree arg_type
,
4425 char conversion_char
)
4427 gcc_assert (arg_type
);
4428 gcc_assert (conversion_char
);
4430 /* First pass: look for a format_char_info containing CONVERSION_CHAR
4431 If we find one, then presumably the length modifier was incorrect
4433 char *result
= get_format_for_type_1 (fki
, arg_type
, conversion_char
);
4437 /* Second pass: we didn't find a match for CONVERSION_CHAR, so try
4438 matching just on the type. */
4439 return get_format_for_type_1 (fki
, arg_type
, '\0');
4442 /* Attempt to get a string for use as a replacement fix-it hint for the
4443 source range in FMT_LOC.
4445 Preserve all of the text within the range of FMT_LOC up to
4446 OFFSET_TO_TYPE_START, replacing the rest with an appropriate
4447 length modifier and conversion specifier for ARG_TYPE, attempting
4448 to keep the user-provided CONVERSION_CHAR if possible.
4450 For example, given a long vs long long mismatch for arg5 here:
4452 000000000111111111122222222223333333333|
4453 123456789012345678901234567890123456789` column numbers
4454 0000000000111111111122|
4455 0123456789012345678901` string offsets
4456 V~~~~~~~~ : range of FMT_LOC, from cols 23-31
4457 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
4459 | ` CONVERSION_CHAR: 'd'
4462 where OFFSET_TO_TYPE_START is 13 (the offset to the "lld" within the
4463 STRING_CST), where the user provided:
4465 the result (assuming "long" argument 5) should be:
4468 If successful, returns a non-NULL string which should be freed
4470 Otherwise, returns NULL. */
4473 get_corrected_substring (const substring_loc
&fmt_loc
,
4474 format_wanted_type
*type
, tree arg_type
,
4475 const format_kind_info
*fki
,
4476 int offset_to_type_start
, char conversion_char
)
4478 /* Attempt to provide hints for argument types, but not for field widths
4482 if (type
->kind
!= CF_KIND_FORMAT
)
4485 /* Locate the current code within the source range, rejecting
4486 any awkward cases where the format string occupies more than
4488 Lookup the place where the type starts (including any length
4489 modifiers), getting it as the caret location. */
4490 substring_loc
type_loc (fmt_loc
);
4491 type_loc
.set_caret_index (offset_to_type_start
);
4493 location_t fmt_substring_loc
;
4494 const char *err
= type_loc
.get_location (&fmt_substring_loc
);
4498 source_range fmt_substring_range
4499 = get_range_from_loc (line_table
, fmt_substring_loc
);
4501 expanded_location caret
4502 = expand_location_to_spelling_point (fmt_substring_loc
);
4503 expanded_location start
4504 = expand_location_to_spelling_point (fmt_substring_range
.m_start
);
4505 expanded_location finish
4506 = expand_location_to_spelling_point (fmt_substring_range
.m_finish
);
4507 if (caret
.file
!= start
.file
)
4509 if (start
.file
!= finish
.file
)
4511 if (caret
.line
!= start
.line
)
4513 if (start
.line
!= finish
.line
)
4515 if (start
.column
> caret
.column
)
4517 if (start
.column
> finish
.column
)
4519 if (caret
.column
> finish
.column
)
4522 char_span line
= location_get_source_line (start
.file
, start
.line
);
4526 /* If we got this far, then we have the line containing the
4527 existing conversion specification.
4529 Generate a trimmed copy, containing the prefix part of the conversion
4530 specification, up to the (but not including) the length modifier.
4531 In the above example, this would be "%-+*.*". */
4532 int length_up_to_type
= caret
.column
- start
.column
;
4533 char_span prefix_span
= line
.subspan (start
.column
- 1, length_up_to_type
);
4534 char *prefix
= prefix_span
.xstrdup ();
4536 /* Now attempt to generate a suggestion for the rest of the specification
4537 (length modifier and conversion char), based on ARG_TYPE and
4539 In the above example, this would be "ld". */
4540 char *format_for_type
= get_format_for_type (fki
, arg_type
, conversion_char
);
4541 if (!format_for_type
)
4547 /* Success. Generate the resulting suggestion for the whole range of
4548 FMT_LOC by concatenating the two strings.
4549 In the above example, this would be "%-+*.*ld". */
4550 char *result
= concat (prefix
, format_for_type
, NULL
);
4551 free (format_for_type
);
4556 /* Helper class for adding zero or more trailing '*' to types.
4558 The format type and name exclude any '*' for pointers, so those
4559 must be formatted manually. For all the types we currently have,
4560 this is adequate, but formats taking pointers to functions or
4561 arrays would require the full type to be built up in order to
4562 print it with %T. */
4564 class indirection_suffix
4567 indirection_suffix (int pointer_count
) : m_pointer_count (pointer_count
) {}
4569 /* Determine the size of the buffer (including NUL-terminator). */
4571 size_t get_buffer_size () const
4573 return m_pointer_count
+ 2;
4576 /* Write the '*' to DST and add a NUL-terminator. */
4578 void fill_buffer (char *dst
) const
4580 if (m_pointer_count
== 0)
4582 else if (c_dialect_cxx ())
4584 memset (dst
, '*', m_pointer_count
);
4585 dst
[m_pointer_count
] = 0;
4590 memset (dst
+ 1, '*', m_pointer_count
);
4591 dst
[m_pointer_count
+ 1] = 0;
4596 int m_pointer_count
;
4599 /* Subclass of range_label for labelling the range in the format string
4600 with the type in question, adding trailing '*' for pointer_count. */
4602 class range_label_for_format_type_mismatch
4603 : public range_label_for_type_mismatch
4606 range_label_for_format_type_mismatch (tree labelled_type
, tree other_type
,
4608 : range_label_for_type_mismatch (labelled_type
, other_type
),
4609 m_pointer_count (pointer_count
)
4613 label_text
get_text (unsigned range_idx
) const FINAL OVERRIDE
4615 label_text text
= range_label_for_type_mismatch::get_text (range_idx
);
4616 if (text
.m_buffer
== NULL
)
4619 indirection_suffix
suffix (m_pointer_count
);
4620 char *p
= (char *) alloca (suffix
.get_buffer_size ());
4621 suffix
.fill_buffer (p
);
4623 char *result
= concat (text
.m_buffer
, p
, NULL
);
4625 return label_text (result
, true);
4629 int m_pointer_count
;
4632 /* Give a warning about a format argument of different type from that expected.
4633 The range of the diagnostic is taken from WHOLE_FMT_LOC; the caret location
4634 is based on the location of the char at TYPE->offset_loc.
4635 PARAM_LOC is the location of the relevant argument, or UNKNOWN_LOCATION
4636 if this is unavailable.
4637 WANTED_TYPE is the type the argument should have,
4638 possibly stripped of pointer dereferences. The description (such as "field
4639 precision"), the placement in the format string, a possibly more
4640 friendly name of WANTED_TYPE, and the number of pointer dereferences
4641 are taken from TYPE. ARG_TYPE is the type of the actual argument,
4642 or NULL if it is missing.
4644 OFFSET_TO_TYPE_START is the offset within the execution-charset encoded
4645 format string to where type information begins for the conversion
4646 (the length modifier and conversion specifier).
4647 CONVERSION_CHAR is the user-provided conversion specifier.
4649 For example, given a type mismatch for argument 5 here:
4651 00000000011111111112222222222333333333344444444445555555555|
4652 12345678901234567890123456789012345678901234567890123456789` column numbers
4653 0000000000111111111122|
4654 0123456789012345678901` offsets within STRING_CST
4655 V~~~~~~~~ : range of WHOLE_FMT_LOC, from cols 23-31
4656 sprintf (d, "before %-+*.*lld after", int_expr, int_expr, long_expr);
4658 | ` CONVERSION_CHAR: 'd' PARAM_LOC
4661 OFFSET_TO_TYPE_START is 13, the offset to the "lld" within the
4665 format_type_warning (const substring_loc
&whole_fmt_loc
,
4666 location_t param_loc
,
4667 format_wanted_type
*type
,
4668 tree wanted_type
, tree arg_type
,
4669 const format_kind_info
*fki
,
4670 int offset_to_type_start
,
4671 char conversion_char
)
4673 enum format_specifier_kind kind
= type
->kind
;
4674 const char *wanted_type_name
= type
->wanted_type_name
;
4675 const char *format_start
= type
->format_start
;
4676 int format_length
= type
->format_length
;
4677 int pointer_count
= type
->pointer_count
;
4678 int arg_num
= type
->arg_num
;
4680 /* If ARG_TYPE is a typedef with a misleading name (for example,
4681 size_t but not the standard size_t expected by printf %zu), avoid
4682 printing the typedef name. */
4683 if (wanted_type_name
4685 && TYPE_NAME (arg_type
)
4686 && TREE_CODE (TYPE_NAME (arg_type
)) == TYPE_DECL
4687 && DECL_NAME (TYPE_NAME (arg_type
))
4688 && !strcmp (wanted_type_name
,
4689 lang_hooks
.decl_printable_name (TYPE_NAME (arg_type
), 2)))
4690 arg_type
= TYPE_MAIN_VARIANT (arg_type
);
4692 indirection_suffix
suffix (pointer_count
);
4693 char *p
= (char *) alloca (suffix
.get_buffer_size ());
4694 suffix
.fill_buffer (p
);
4696 /* WHOLE_FMT_LOC has the caret at the end of the range.
4697 Set the caret to be at the offset from TYPE. Subtract one
4698 from the offset for the same reason as in format_warning_at_char. */
4699 substring_loc
fmt_loc (whole_fmt_loc
);
4700 fmt_loc
.set_caret_index (type
->offset_loc
- 1);
4702 range_label_for_format_type_mismatch
fmt_label (wanted_type
, arg_type
,
4704 range_label_for_type_mismatch
param_label (arg_type
, wanted_type
);
4706 /* Get a string for use as a replacement fix-it hint for the range in
4707 fmt_loc, or NULL. */
4708 char *corrected_substring
4709 = get_corrected_substring (fmt_loc
, type
, arg_type
, fki
,
4710 offset_to_type_start
, conversion_char
);
4711 format_string_diagnostic_t
diag (fmt_loc
, &fmt_label
, param_loc
, ¶m_label
,
4712 corrected_substring
);
4713 if (wanted_type_name
)
4718 "%s %<%s%.*s%> expects argument of type %<%s%s%>, "
4719 "but argument %d has type %qT",
4720 gettext (kind_descriptions
[kind
]),
4721 (kind
== CF_KIND_FORMAT
? "%" : ""),
4722 format_length
, format_start
,
4723 wanted_type_name
, p
, arg_num
, arg_type
);
4727 "%s %<%s%.*s%> expects a matching %<%s%s%> argument",
4728 gettext (kind_descriptions
[kind
]),
4729 (kind
== CF_KIND_FORMAT
? "%" : ""),
4730 format_length
, format_start
, wanted_type_name
, p
);
4737 "%s %<%s%.*s%> expects argument of type %<%T%s%>, "
4738 "but argument %d has type %qT",
4739 gettext (kind_descriptions
[kind
]),
4740 (kind
== CF_KIND_FORMAT
? "%" : ""),
4741 format_length
, format_start
,
4742 wanted_type
, p
, arg_num
, arg_type
);
4746 "%s %<%s%.*s%> expects a matching %<%T%s%> argument",
4747 gettext (kind_descriptions
[kind
]),
4748 (kind
== CF_KIND_FORMAT
? "%" : ""),
4749 format_length
, format_start
, wanted_type
, p
);
4752 free (corrected_substring
);
4756 /* Given a format_char_info array FCI, and a character C, this function
4757 returns the index into the conversion_specs where that specifier's
4758 data is located. The character must exist. */
4760 find_char_info_specifier_index (const format_char_info
*fci
, int c
)
4764 for (i
= 0; fci
->format_chars
; i
++, fci
++)
4765 if (strchr (fci
->format_chars
, c
))
4768 /* We shouldn't be looking for a non-existent specifier. */
4772 /* Given a format_length_info array FLI, and a character C, this
4773 function returns the index into the conversion_specs where that
4774 modifier's data is located. The character must exist. */
4776 find_length_info_modifier_index (const format_length_info
*fli
, int c
)
4780 for (i
= 0; fli
->name
; i
++, fli
++)
4781 if (strchr (fli
->name
, c
))
4784 /* We shouldn't be looking for a non-existent modifier. */
4788 /* Determine the type of HOST_WIDE_INT in the code being compiled for
4789 use in GCC's __asm_fprintf__ custom format attribute. You must
4790 have set dynamic_format_types before calling this function. */
4792 init_dynamic_asm_fprintf_info (void)
4798 format_length_info
*new_asm_fprintf_length_specs
;
4801 /* Find the underlying type for HOST_WIDE_INT. For the %w
4802 length modifier to work, one must have issued: "typedef
4803 HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code
4804 prior to using that modifier. */
4805 hwi
= maybe_get_identifier ("__gcc_host_wide_int__");
4808 error ("%<__gcc_host_wide_int__%> is not defined as a type");
4811 hwi
= identifier_global_value (hwi
);
4812 if (!hwi
|| TREE_CODE (hwi
) != TYPE_DECL
)
4814 error ("%<__gcc_host_wide_int__%> is not defined as a type");
4817 hwi
= DECL_ORIGINAL_TYPE (hwi
);
4819 if (hwi
!= long_integer_type_node
&& hwi
!= long_long_integer_type_node
)
4821 error ("%<__gcc_host_wide_int__%> is not defined as %<long%>"
4822 " or %<long long%>");
4826 /* Create a new (writable) copy of asm_fprintf_length_specs. */
4827 new_asm_fprintf_length_specs
= (format_length_info
*)
4828 xmemdup (asm_fprintf_length_specs
,
4829 sizeof (asm_fprintf_length_specs
),
4830 sizeof (asm_fprintf_length_specs
));
4832 /* HOST_WIDE_INT must be one of 'long' or 'long long'. */
4833 i
= find_length_info_modifier_index (new_asm_fprintf_length_specs
, 'w');
4834 if (hwi
== long_integer_type_node
)
4835 new_asm_fprintf_length_specs
[i
].index
= FMT_LEN_l
;
4836 else if (hwi
== long_long_integer_type_node
)
4837 new_asm_fprintf_length_specs
[i
].index
= FMT_LEN_ll
;
4841 /* Assign the new data for use. */
4842 dynamic_format_types
[asm_fprintf_format_type
].length_char_specs
=
4843 new_asm_fprintf_length_specs
;
4847 /* Determine the type of a "locus" in the code being compiled for use
4848 in GCC's __gcc_gfc__ custom format attribute. You must have set
4849 dynamic_format_types before calling this function. */
4851 init_dynamic_gfc_info (void)
4855 static format_char_info
*gfc_fci
;
4857 /* For the GCC __gcc_gfc__ custom format specifier to work, one
4858 must have declared 'locus' prior to using this attribute. If
4859 we haven't seen this declarations then you shouldn't use the
4860 specifier requiring that type. */
4861 if ((locus
= maybe_get_identifier ("locus")))
4863 locus
= identifier_global_value (locus
);
4866 if (TREE_CODE (locus
) != TYPE_DECL
4867 || TREE_TYPE (locus
) == error_mark_node
)
4869 error ("%<locus%> is not defined as a type");
4873 locus
= TREE_TYPE (locus
);
4877 /* Assign the new data for use. */
4879 /* Handle the __gcc_gfc__ format specifics. */
4881 dynamic_format_types
[gcc_gfc_format_type
].conversion_specs
=
4882 gfc_fci
= (format_char_info
*)
4883 xmemdup (gcc_gfc_char_table
,
4884 sizeof (gcc_gfc_char_table
),
4885 sizeof (gcc_gfc_char_table
));
4888 const unsigned i
= find_char_info_specifier_index (gfc_fci
, 'L');
4889 gfc_fci
[i
].types
[0].type
= &locus
;
4890 gfc_fci
[i
].pointer_count
= 1;
4895 /* Lookup the type named NAME and return a pointer-to-NAME type if found.
4896 Otherwise, return void_type_node if NAME has not been used yet, or NULL_TREE if
4897 NAME is not a type (issuing an error). */
4900 get_pointer_to_named_type (const char *name
)
4903 if ((result
= maybe_get_identifier (name
)))
4905 result
= identifier_global_value (result
);
4908 if (TREE_CODE (result
) != TYPE_DECL
)
4910 error ("%qs is not defined as a type", name
);
4914 result
= TREE_TYPE (result
);
4918 result
= void_type_node
;
4922 /* Determine the types of "tree" and "location_t" in the code being
4923 compiled for use in GCC's diagnostic custom format attributes. You
4924 must have set dynamic_format_types before calling this function. */
4926 init_dynamic_diag_info (void)
4928 /* For the GCC-diagnostics custom format specifiers to work, one
4929 must have declared 'tree' and 'location_t' prior to using those
4930 attributes. If we haven't seen these declarations then
4931 the specifiers requiring these types shouldn't be used.
4932 However we don't force a hard ICE because we may see only one
4933 or the other type. */
4934 if (tree loc
= maybe_get_identifier ("location_t"))
4936 loc
= identifier_global_value (loc
);
4937 if (loc
&& TREE_CODE (loc
) != TYPE_DECL
)
4938 error ("%<location_t%> is not defined as a type");
4941 /* Initialize the global tree node type local to this file. */
4942 if (!local_tree_type_node
4943 || local_tree_type_node
== void_type_node
)
4945 /* We need to grab the underlying 'union tree_node' so peek into
4946 an extra type level. */
4947 if ((local_tree_type_node
= maybe_get_identifier ("tree")))
4949 local_tree_type_node
= identifier_global_value (local_tree_type_node
);
4950 if (local_tree_type_node
)
4952 if (TREE_CODE (local_tree_type_node
) != TYPE_DECL
)
4954 error ("%<tree%> is not defined as a type");
4955 local_tree_type_node
= 0;
4957 else if (TREE_CODE (TREE_TYPE (local_tree_type_node
))
4960 error ("%<tree%> is not defined as a pointer type");
4961 local_tree_type_node
= 0;
4964 local_tree_type_node
=
4965 TREE_TYPE (TREE_TYPE (local_tree_type_node
));
4969 local_tree_type_node
= void_type_node
;
4972 /* Similar to the above but for gimple*. */
4973 if (!local_gimple_ptr_node
4974 || local_gimple_ptr_node
== void_type_node
)
4975 local_gimple_ptr_node
= get_pointer_to_named_type ("gimple");
4977 /* Similar to the above but for cgraph_node*. */
4978 if (!local_cgraph_node_ptr_node
4979 || local_cgraph_node_ptr_node
== void_type_node
)
4980 local_cgraph_node_ptr_node
= get_pointer_to_named_type ("cgraph_node");
4986 static format_length_info
*diag_ls
;
4989 /* Find the underlying type for HOST_WIDE_INT. For the 'w'
4990 length modifier to work, one must have issued: "typedef
4991 HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code
4992 prior to using that modifier. */
4993 if ((hwi
= maybe_get_identifier ("__gcc_host_wide_int__")))
4995 hwi
= identifier_global_value (hwi
);
4998 if (TREE_CODE (hwi
) != TYPE_DECL
)
5000 error ("%<__gcc_host_wide_int__%> is not defined as a type");
5005 hwi
= DECL_ORIGINAL_TYPE (hwi
);
5007 if (hwi
!= long_integer_type_node
5008 && hwi
!= long_long_integer_type_node
)
5010 error ("%<__gcc_host_wide_int__%> is not defined"
5011 " as %<long%> or %<long long%>");
5018 /* Assign the new data for use. */
5020 /* All the GCC diag formats use the same length specs. */
5022 dynamic_format_types
[gcc_diag_format_type
].length_char_specs
=
5023 dynamic_format_types
[gcc_tdiag_format_type
].length_char_specs
=
5024 dynamic_format_types
[gcc_cdiag_format_type
].length_char_specs
=
5025 dynamic_format_types
[gcc_cxxdiag_format_type
].length_char_specs
=
5026 dynamic_format_types
[gcc_dump_printf_format_type
].length_char_specs
=
5027 diag_ls
= (format_length_info
*)
5028 xmemdup (gcc_diag_length_specs
,
5029 sizeof (gcc_diag_length_specs
),
5030 sizeof (gcc_diag_length_specs
));
5033 /* HOST_WIDE_INT must be one of 'long' or 'long long'. */
5034 i
= find_length_info_modifier_index (diag_ls
, 'w');
5035 if (hwi
== long_integer_type_node
)
5036 diag_ls
[i
].index
= FMT_LEN_l
;
5037 else if (hwi
== long_long_integer_type_node
)
5038 diag_ls
[i
].index
= FMT_LEN_ll
;
5044 /* It's safe to "re-initialize these to the same values. */
5045 dynamic_format_types
[gcc_diag_format_type
].conversion_specs
=
5046 gcc_diag_char_table
;
5047 dynamic_format_types
[gcc_tdiag_format_type
].conversion_specs
=
5048 gcc_tdiag_char_table
;
5049 dynamic_format_types
[gcc_cdiag_format_type
].conversion_specs
=
5050 gcc_cdiag_char_table
;
5051 dynamic_format_types
[gcc_cxxdiag_format_type
].conversion_specs
=
5052 gcc_cxxdiag_char_table
;
5053 dynamic_format_types
[gcc_dump_printf_format_type
].conversion_specs
=
5054 gcc_dump_printf_char_table
;
5057 #ifdef TARGET_FORMAT_TYPES
5058 extern const format_kind_info TARGET_FORMAT_TYPES
[];
5061 #ifdef TARGET_OVERRIDES_FORMAT_ATTRIBUTES
5062 extern const target_ovr_attr TARGET_OVERRIDES_FORMAT_ATTRIBUTES
[];
5064 #ifdef TARGET_OVERRIDES_FORMAT_INIT
5065 extern void TARGET_OVERRIDES_FORMAT_INIT (void);
5068 /* Attributes such as "printf" are equivalent to those such as
5069 "gnu_printf" unless this is overridden by a target. */
5070 static const target_ovr_attr gnu_target_overrides_format_attributes
[] =
5072 { "gnu_printf", "printf" },
5073 { "gnu_scanf", "scanf" },
5074 { "gnu_strftime", "strftime" },
5075 { "gnu_strfmon", "strfmon" },
5079 /* Translate to unified attribute name. This is used in decode_format_type and
5080 decode_format_attr. In attr_name the user specified argument is passed. It
5081 returns the unified format name from TARGET_OVERRIDES_FORMAT_ATTRIBUTES
5082 or the attr_name passed to this function, if there is no matching entry. */
5084 convert_format_name_to_system_name (const char *attr_name
)
5088 if (attr_name
== NULL
|| *attr_name
== 0
5089 || strncmp (attr_name
, "gcc_", 4) == 0)
5091 #ifdef TARGET_OVERRIDES_FORMAT_INIT
5092 TARGET_OVERRIDES_FORMAT_INIT ();
5095 #ifdef TARGET_OVERRIDES_FORMAT_ATTRIBUTES
5096 /* Check if format attribute is overridden by target. */
5097 if (TARGET_OVERRIDES_FORMAT_ATTRIBUTES
!= NULL
5098 && TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT
> 0)
5100 for (i
= 0; i
< TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT
; ++i
)
5102 if (cmp_attribs (TARGET_OVERRIDES_FORMAT_ATTRIBUTES
[i
].named_attr_src
,
5105 if (cmp_attribs (TARGET_OVERRIDES_FORMAT_ATTRIBUTES
[i
].named_attr_dst
,
5107 return TARGET_OVERRIDES_FORMAT_ATTRIBUTES
[i
].named_attr_src
;
5111 /* Otherwise default to gnu format. */
5113 gnu_target_overrides_format_attributes
[i
].named_attr_src
!= NULL
;
5116 if (cmp_attribs (gnu_target_overrides_format_attributes
[i
].named_attr_src
,
5119 if (cmp_attribs (gnu_target_overrides_format_attributes
[i
].named_attr_dst
,
5121 return gnu_target_overrides_format_attributes
[i
].named_attr_src
;
5127 /* Handle a "format" attribute; arguments as in
5128 struct attribute_spec.handler. */
5130 handle_format_attribute (tree
*node
, tree atname
, tree args
,
5131 int flags
, bool *no_add_attrs
)
5133 const_tree type
= *node
;
5134 function_format_info info
;
5136 #ifdef TARGET_FORMAT_TYPES
5137 /* If the target provides additional format types, we need to
5138 add them to FORMAT_TYPES at first use. */
5139 if (TARGET_FORMAT_TYPES
!= NULL
&& !dynamic_format_types
)
5141 dynamic_format_types
= XNEWVEC (format_kind_info
,
5142 n_format_types
+ TARGET_N_FORMAT_TYPES
);
5143 memcpy (dynamic_format_types
, format_types_orig
,
5144 sizeof (format_types_orig
));
5145 memcpy (&dynamic_format_types
[n_format_types
], TARGET_FORMAT_TYPES
,
5146 TARGET_N_FORMAT_TYPES
* sizeof (dynamic_format_types
[0]));
5148 format_types
= dynamic_format_types
;
5149 /* Provide a reference for the first potential external type. */
5150 first_target_format_type
= n_format_types
;
5151 n_format_types
+= TARGET_N_FORMAT_TYPES
;
5155 /* Canonicalize name of format function. */
5156 if (TREE_CODE (TREE_VALUE (args
)) == IDENTIFIER_NODE
)
5157 TREE_VALUE (args
) = canonicalize_attr_name (TREE_VALUE (args
));
5159 if (!decode_format_attr (type
, atname
, args
, &info
, /* validated_p = */false))
5161 *no_add_attrs
= true;
5165 if (prototype_p (type
))
5167 if (!check_format_string (type
, info
.format_num
, flags
,
5168 no_add_attrs
, info
.format_type
))
5171 if (info
.first_arg_num
!= 0)
5173 unsigned HOST_WIDE_INT arg_num
= 1;
5174 function_args_iterator iter
;
5177 /* Verify that first_arg_num points to the last arg,
5179 FOREACH_FUNCTION_ARGS (type
, arg_type
, iter
)
5182 if (arg_num
!= info
.first_arg_num
)
5184 if (!(flags
& (int) ATTR_FLAG_BUILT_IN
))
5185 error ("argument to be formatted is not %<...%>");
5186 *no_add_attrs
= true;
5192 /* Check if this is a strftime variant. Just for this variant
5193 FMT_FLAG_ARG_CONVERT is not set. */
5194 if ((format_types
[info
.format_type
].flags
& (int) FMT_FLAG_ARG_CONVERT
) == 0
5195 && info
.first_arg_num
!= 0)
5197 error ("strftime formats cannot format arguments");
5198 *no_add_attrs
= true;
5202 /* If this is a custom GCC-internal format type, we have to
5203 initialize certain bits at runtime. */
5204 if (info
.format_type
== asm_fprintf_format_type
5205 || info
.format_type
== gcc_gfc_format_type
5206 || info
.format_type
== gcc_diag_format_type
5207 || info
.format_type
== gcc_tdiag_format_type
5208 || info
.format_type
== gcc_cdiag_format_type
5209 || info
.format_type
== gcc_cxxdiag_format_type
5210 || info
.format_type
== gcc_dump_printf_format_type
)
5212 /* Our first time through, we have to make sure that our
5213 format_type data is allocated dynamically and is modifiable. */
5214 if (!dynamic_format_types
)
5215 format_types
= dynamic_format_types
= (format_kind_info
*)
5216 xmemdup (format_types_orig
, sizeof (format_types_orig
),
5217 sizeof (format_types_orig
));
5219 /* If this is format __asm_fprintf__, we have to initialize
5220 GCC's notion of HOST_WIDE_INT for checking %wd. */
5221 if (info
.format_type
== asm_fprintf_format_type
)
5222 init_dynamic_asm_fprintf_info ();
5223 /* If this is format __gcc_gfc__, we have to initialize GCC's
5224 notion of 'locus' at runtime for %L. */
5225 else if (info
.format_type
== gcc_gfc_format_type
)
5226 init_dynamic_gfc_info ();
5227 /* If this is one of the diagnostic attributes, then we have to
5228 initialize 'location_t' and 'tree' at runtime. */
5229 else if (info
.format_type
== gcc_diag_format_type
5230 || info
.format_type
== gcc_tdiag_format_type
5231 || info
.format_type
== gcc_cdiag_format_type
5232 || info
.format_type
== gcc_cxxdiag_format_type
5233 || info
.format_type
== gcc_dump_printf_format_type
)
5234 init_dynamic_diag_info ();
5244 namespace selftest
{
5246 /* Selftests of location handling. */
5248 /* Get the format_kind_info with the given name. */
5250 static const format_kind_info
*
5251 get_info (const char *name
)
5253 int idx
= decode_format_type (name
);
5254 const format_kind_info
*fki
= &format_types
[idx
];
5255 ASSERT_STREQ (fki
->name
, name
);
5259 /* Verify that get_format_for_type (FKI, TYPE, CONVERSION_CHAR)
5260 is EXPECTED_FORMAT. */
5263 assert_format_for_type_streq (const location
&loc
, const format_kind_info
*fki
,
5264 const char *expected_format
, tree type
,
5265 char conversion_char
)
5268 gcc_assert (expected_format
);
5271 char *actual_format
= get_format_for_type (fki
, type
, conversion_char
);
5272 ASSERT_STREQ_AT (loc
, expected_format
, actual_format
);
5273 free (actual_format
);
5276 /* Selftests for get_format_for_type. */
5278 #define ASSERT_FORMAT_FOR_TYPE_STREQ(EXPECTED_FORMAT, TYPE, CONVERSION_CHAR) \
5279 assert_format_for_type_streq (SELFTEST_LOCATION, (fki), (EXPECTED_FORMAT), \
5280 (TYPE), (CONVERSION_CHAR))
5282 /* Selftest for get_format_for_type for "printf"-style functions. */
5285 test_get_format_for_type_printf ()
5287 const format_kind_info
*fki
= get_info ("gnu_printf");
5288 ASSERT_NE (fki
, NULL
);
5290 ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node
, 'i');
5291 ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node
, 'i');
5292 ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node
, 'o');
5293 ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node
, 'o');
5294 ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node
, 'x');
5295 ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node
, 'x');
5296 ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node
, 'X');
5297 ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node
, 'X');
5298 ASSERT_FORMAT_FOR_TYPE_STREQ ("d", integer_type_node
, 'd');
5299 ASSERT_FORMAT_FOR_TYPE_STREQ ("i", integer_type_node
, 'i');
5300 ASSERT_FORMAT_FOR_TYPE_STREQ ("o", integer_type_node
, 'o');
5301 ASSERT_FORMAT_FOR_TYPE_STREQ ("x", integer_type_node
, 'x');
5302 ASSERT_FORMAT_FOR_TYPE_STREQ ("X", integer_type_node
, 'X');
5303 ASSERT_FORMAT_FOR_TYPE_STREQ ("d", unsigned_type_node
, 'd');
5304 ASSERT_FORMAT_FOR_TYPE_STREQ ("i", unsigned_type_node
, 'i');
5305 ASSERT_FORMAT_FOR_TYPE_STREQ ("o", unsigned_type_node
, 'o');
5306 ASSERT_FORMAT_FOR_TYPE_STREQ ("x", unsigned_type_node
, 'x');
5307 ASSERT_FORMAT_FOR_TYPE_STREQ ("X", unsigned_type_node
, 'X');
5308 ASSERT_FORMAT_FOR_TYPE_STREQ ("ld", long_integer_type_node
, 'd');
5309 ASSERT_FORMAT_FOR_TYPE_STREQ ("li", long_integer_type_node
, 'i');
5310 ASSERT_FORMAT_FOR_TYPE_STREQ ("lx", long_integer_type_node
, 'x');
5311 ASSERT_FORMAT_FOR_TYPE_STREQ ("lo", long_unsigned_type_node
, 'o');
5312 ASSERT_FORMAT_FOR_TYPE_STREQ ("lx", long_unsigned_type_node
, 'x');
5313 ASSERT_FORMAT_FOR_TYPE_STREQ ("lld", long_long_integer_type_node
, 'd');
5314 ASSERT_FORMAT_FOR_TYPE_STREQ ("lli", long_long_integer_type_node
, 'i');
5315 ASSERT_FORMAT_FOR_TYPE_STREQ ("llo", long_long_unsigned_type_node
, 'o');
5316 ASSERT_FORMAT_FOR_TYPE_STREQ ("llx", long_long_unsigned_type_node
, 'x');
5317 ASSERT_FORMAT_FOR_TYPE_STREQ ("s", build_pointer_type (char_type_node
), 'i');
5320 /* Selftest for get_format_for_type for "scanf"-style functions. */
5323 test_get_format_for_type_scanf ()
5325 const format_kind_info
*fki
= get_info ("gnu_scanf");
5326 ASSERT_NE (fki
, NULL
);
5327 ASSERT_FORMAT_FOR_TYPE_STREQ ("d", build_pointer_type (integer_type_node
), 'd');
5328 ASSERT_FORMAT_FOR_TYPE_STREQ ("u", build_pointer_type (unsigned_type_node
), 'u');
5329 ASSERT_FORMAT_FOR_TYPE_STREQ ("ld",
5330 build_pointer_type (long_integer_type_node
), 'd');
5331 ASSERT_FORMAT_FOR_TYPE_STREQ ("lu",
5332 build_pointer_type (long_unsigned_type_node
), 'u');
5333 ASSERT_FORMAT_FOR_TYPE_STREQ
5334 ("lld", build_pointer_type (long_long_integer_type_node
), 'd');
5335 ASSERT_FORMAT_FOR_TYPE_STREQ
5336 ("llu", build_pointer_type (long_long_unsigned_type_node
), 'u');
5337 ASSERT_FORMAT_FOR_TYPE_STREQ ("e", build_pointer_type (float_type_node
), 'e');
5338 ASSERT_FORMAT_FOR_TYPE_STREQ ("le", build_pointer_type (double_type_node
), 'e');
5341 #undef ASSERT_FORMAT_FOR_TYPE_STREQ
5343 /* Exercise the type-printing label code, to give some coverage
5344 under "make selftest-valgrind" (in particular, to ensure that
5345 the label-printing machinery doesn't leak). */
5348 test_type_mismatch_range_labels ()
5350 /* Create a tempfile and write some text to it.
5351 ....................0000000001 11111111 12 22222222
5352 ....................1234567890 12345678 90 12345678. */
5353 const char *content
= " printf (\"msg: %i\\n\", msg);\n";
5354 temp_source_file
tmp (SELFTEST_LOCATION
, ".c", content
);
5355 line_table_test ltt
;
5357 linemap_add (line_table
, LC_ENTER
, false, tmp
.get_filename (), 1);
5359 location_t c17
= linemap_position_for_column (line_table
, 17);
5360 ASSERT_EQ (LOCATION_COLUMN (c17
), 17);
5361 location_t c18
= linemap_position_for_column (line_table
, 18);
5362 location_t c24
= linemap_position_for_column (line_table
, 24);
5363 location_t c26
= linemap_position_for_column (line_table
, 26);
5365 /* Don't attempt to run the tests if column data might be unavailable. */
5366 if (c26
> LINE_MAP_MAX_LOCATION_WITH_COLS
)
5369 location_t fmt
= make_location (c18
, c17
, c18
);
5370 ASSERT_EQ (LOCATION_COLUMN (fmt
), 18);
5372 location_t param
= make_location (c24
, c24
, c26
);
5373 ASSERT_EQ (LOCATION_COLUMN (param
), 24);
5375 range_label_for_format_type_mismatch
fmt_label (char_type_node
,
5376 integer_type_node
, 1);
5377 range_label_for_type_mismatch
param_label (integer_type_node
,
5379 gcc_rich_location
richloc (fmt
, &fmt_label
);
5380 richloc
.add_range (param
, SHOW_RANGE_WITHOUT_CARET
, ¶m_label
);
5382 test_diagnostic_context dc
;
5383 diagnostic_show_locus (&dc
, &richloc
, DK_ERROR
);
5384 if (c_dialect_cxx ())
5385 /* "char*", without a space. */
5387 " printf (\"msg: %i\\n\", msg);\n"
5391 pp_formatted_text (dc
.printer
));
5393 /* "char *", with a space. */
5395 " printf (\"msg: %i\\n\", msg);\n"
5400 pp_formatted_text (dc
.printer
));
5403 /* Run all of the selftests within this file. */
5408 test_get_modifier_for_format_len ();
5409 test_get_format_for_type_printf ();
5410 test_get_format_for_type_scanf ();
5411 test_type_mismatch_range_labels ();
5414 } // namespace selftest
5416 #endif /* CHECKING_P */
5418 #include "gt-c-family-c-format.h"