PR rtl-optimization/88470
[official-gcc.git] / gcc / c-family / c-format.c
blob8b17f5399744163e5fe116236814e86e234ee26c
1 /* Check calls to formatted I/O functions (-Wformat).
2 Copyright (C) 1992-2018 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
9 version.
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
14 for more details.
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/>. */
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "c-target.h"
25 #include "c-common.h"
26 #include "alloc-pool.h"
27 #include "stringpool.h"
28 #include "c-objc.h"
29 #include "intl.h"
30 #include "langhooks.h"
31 #include "c-format.h"
32 #include "diagnostic.h"
33 #include "substring-locations.h"
34 #include "selftest.h"
35 #include "selftest-diagnostic.h"
36 #include "builtins.h"
37 #include "attribs.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 int format_type; /* type of format (printf, scanf, etc.) */
56 unsigned HOST_WIDE_INT format_num; /* number of format argument */
57 unsigned HOST_WIDE_INT first_arg_num; /* number of first arg (zero for varargs) */
60 /* Initialized in init_dynamic_diag_info. */
61 static GTY(()) tree local_tree_type_node;
62 static GTY(()) tree local_gimple_ptr_node;
63 static GTY(()) tree local_cgraph_node_ptr_node;
64 static GTY(()) tree locus;
66 static bool decode_format_attr (const_tree, tree, tree, function_format_info *,
67 bool);
68 static int decode_format_type (const char *);
70 static bool check_format_string (const_tree argument,
71 unsigned HOST_WIDE_INT format_num,
72 int flags, bool *no_add_attrs,
73 int expected_format_type);
74 static tree get_constant (const_tree fntype, const_tree atname, tree expr,
75 int argno, unsigned HOST_WIDE_INT *value,
76 int flags, bool validated_p);
77 static const char *convert_format_name_to_system_name (const char *attr_name);
79 static int first_target_format_type;
80 static const char *format_name (int format_num);
81 static int format_flags (int format_num);
83 /* Emit a warning as per format_warning_va, but construct the substring_loc
84 for the character at offset (CHAR_IDX - 1) within a string constant
85 FORMAT_STRING_CST at FMT_STRING_LOC. */
87 ATTRIBUTE_GCC_DIAG (5,6)
88 static bool
89 format_warning_at_char (location_t fmt_string_loc, tree format_string_cst,
90 int char_idx, int opt, const char *gmsgid, ...)
92 va_list ap;
93 va_start (ap, gmsgid);
94 tree string_type = TREE_TYPE (format_string_cst);
96 /* The callers are of the form:
97 format_warning (format_string_loc, format_string_cst,
98 format_chars - orig_format_chars,
99 where format_chars has already been incremented, so that
100 CHAR_IDX is one character beyond where the warning should
101 be emitted. Fix it. */
102 char_idx -= 1;
104 substring_loc fmt_loc (fmt_string_loc, string_type, char_idx, char_idx,
105 char_idx);
106 format_string_diagnostic_t diag (fmt_loc, NULL, UNKNOWN_LOCATION, NULL,
107 NULL);
108 bool warned = diag.emit_warning_va (opt, gmsgid, &ap);
109 va_end (ap);
111 return warned;
114 /* Check that we have a pointer to a string suitable for use as a format.
115 The default is to check for a char type.
116 For objective-c dialects, this is extended to include references to string
117 objects validated by objc_string_ref_type_p ().
118 Targets may also provide a string object type that can be used within c and
119 c++ and shared with their respective objective-c dialects. In this case the
120 reference to a format string is checked for validity via a hook.
122 The function returns true if strref points to any string type valid for the
123 language dialect and target. */
125 static bool
126 valid_stringptr_type_p (tree strref)
128 return (strref != NULL
129 && TREE_CODE (strref) == POINTER_TYPE
130 && (TYPE_MAIN_VARIANT (TREE_TYPE (strref)) == char_type_node
131 || objc_string_ref_type_p (strref)
132 || (*targetcm.string_object_ref_type_p) ((const_tree) strref)));
135 /* Handle a "format_arg" attribute; arguments as in
136 struct attribute_spec.handler. */
137 tree
138 handle_format_arg_attribute (tree *node, tree atname,
139 tree args, int flags, bool *no_add_attrs)
141 tree type = *node;
142 /* Note that TREE_VALUE (args) is changed in place below. */
143 tree *format_num_expr = &TREE_VALUE (args);
144 unsigned HOST_WIDE_INT format_num = 0;
146 if (tree val = get_constant (type, atname, *format_num_expr, 0, &format_num,
147 0, false))
148 *format_num_expr = val;
149 else
151 *no_add_attrs = true;
152 return NULL_TREE;
155 if (prototype_p (type))
157 /* The format arg can be any string reference valid for the language and
158 target. We cannot be more specific in this case. */
159 if (!check_format_string (type, format_num, flags, no_add_attrs, -1))
160 return NULL_TREE;
163 if (!valid_stringptr_type_p (TREE_TYPE (type)))
165 if (!(flags & (int) ATTR_FLAG_BUILT_IN))
166 error ("function does not return string type");
167 *no_add_attrs = true;
168 return NULL_TREE;
171 return NULL_TREE;
174 /* Verify that the format_num argument is actually a string reference suitable,
175 for the language dialect and target (in case the format attribute is in
176 error). When we know the specific reference type expected, this is also
177 checked. */
178 static bool
179 check_format_string (const_tree fntype, unsigned HOST_WIDE_INT format_num,
180 int flags, bool *no_add_attrs, int expected_format_type)
182 unsigned HOST_WIDE_INT i;
183 bool is_objc_sref, is_target_sref, is_char_ref;
184 tree ref;
185 int fmt_flags;
186 function_args_iterator iter;
188 i = 1;
189 FOREACH_FUNCTION_ARGS (fntype, ref, iter)
191 if (i == format_num)
192 break;
193 i++;
196 if (!ref
197 || !valid_stringptr_type_p (ref))
199 if (!(flags & (int) ATTR_FLAG_BUILT_IN))
200 error ("format string argument is not a string type");
201 *no_add_attrs = true;
202 return false;
205 /* We only know that we want a suitable string reference. */
206 if (expected_format_type < 0)
207 return true;
209 /* Now check that the arg matches the expected type. */
210 is_char_ref =
211 (TYPE_MAIN_VARIANT (TREE_TYPE (ref)) == char_type_node);
213 fmt_flags = format_flags (expected_format_type);
214 is_objc_sref = is_target_sref = false;
215 if (!is_char_ref)
216 is_objc_sref = objc_string_ref_type_p (ref);
218 if (!(fmt_flags & FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL))
220 if (is_char_ref)
221 return true; /* OK, we expected a char and found one. */
222 else
224 /* We expected a char but found an extended string type. */
225 if (is_objc_sref)
226 error ("found a %qs reference but the format argument should"
227 " be a string", format_name (gcc_objc_string_format_type));
228 else
229 error ("found a %qT but the format argument should be a string",
230 ref);
231 *no_add_attrs = true;
232 return false;
236 /* We expect a string object type as the format arg. */
237 if (is_char_ref)
239 error ("format argument should be a %qs reference but"
240 " a string was found", format_name (expected_format_type));
241 *no_add_attrs = true;
242 return false;
245 /* We will assert that objective-c will support either its own string type
246 or the target-supplied variant. */
247 if (!is_objc_sref)
248 is_target_sref = (*targetcm.string_object_ref_type_p) ((const_tree) ref);
250 if (expected_format_type == (int) gcc_objc_string_format_type
251 && (is_objc_sref || is_target_sref))
252 return true;
254 /* We will allow a target string ref to match only itself. */
255 if (first_target_format_type
256 && expected_format_type >= first_target_format_type
257 && is_target_sref)
258 return true;
259 else
261 error ("format argument should be a %qs reference",
262 format_name (expected_format_type));
263 *no_add_attrs = true;
264 return false;
267 gcc_unreachable ();
270 /* Verify EXPR is a constant, and store its value.
271 If validated_p is true there should be no errors.
272 Returns the converted constant value on success, null otherwise. */
273 static tree
274 get_constant (const_tree fntype, const_tree atname, tree expr, int argno,
275 unsigned HOST_WIDE_INT *value, int flags, bool validated_p)
277 if (tree val = positional_argument (fntype, atname, expr, STRING_CST,
278 argno, flags))
280 *value = TREE_INT_CST_LOW (val);
281 return val;
284 gcc_assert (!validated_p);
285 return NULL_TREE;
288 /* Decode the arguments to a "format" attribute into a
289 function_format_info structure. It is already known that the list
290 is of the right length. If VALIDATED_P is true, then these
291 attributes have already been validated and must not be erroneous;
292 if false, it will give an error message. Returns true if the
293 attributes are successfully decoded, false otherwise. */
295 static bool
296 decode_format_attr (const_tree fntype, tree atname, tree args,
297 function_format_info *info, bool validated_p)
299 tree format_type_id = TREE_VALUE (args);
300 /* Note that TREE_VALUE (args) is changed in place below. Ditto
301 for the value of the next element on the list. */
302 tree *format_num_expr = &TREE_VALUE (TREE_CHAIN (args));
303 tree *first_arg_num_expr = &TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
305 if (TREE_CODE (format_type_id) != IDENTIFIER_NODE)
307 gcc_assert (!validated_p);
308 error ("unrecognized format specifier");
309 return false;
311 else
313 const char *p = IDENTIFIER_POINTER (format_type_id);
315 p = convert_format_name_to_system_name (p);
317 info->format_type = decode_format_type (p);
319 if (!c_dialect_objc ()
320 && info->format_type == gcc_objc_string_format_type)
322 gcc_assert (!validated_p);
323 warning (OPT_Wformat_, "%qE is only allowed in Objective-C dialects",
324 format_type_id);
325 info->format_type = format_type_error;
326 return false;
329 if (info->format_type == format_type_error)
331 gcc_assert (!validated_p);
332 warning (OPT_Wformat_, "%qE is an unrecognized format function type",
333 format_type_id);
334 return false;
338 if (tree val = get_constant (fntype, atname, *format_num_expr,
339 2, &info->format_num, 0, validated_p))
340 *format_num_expr = val;
341 else
342 return false;
344 if (tree val = get_constant (fntype, atname, *first_arg_num_expr,
345 3, &info->first_arg_num,
346 (POSARG_ZERO | POSARG_ELLIPSIS), validated_p))
347 *first_arg_num_expr = val;
348 else
349 return false;
351 if (info->first_arg_num != 0 && info->first_arg_num <= info->format_num)
353 gcc_assert (!validated_p);
354 error ("format string argument follows the args to be formatted");
355 return false;
358 return true;
361 /* Check a call to a format function against a parameter list. */
363 /* The C standard version C++ is treated as equivalent to
364 or inheriting from, for the purpose of format features supported. */
365 #define CPLUSPLUS_STD_VER (cxx_dialect < cxx11 ? STD_C94 : STD_C99)
366 /* The C standard version we are checking formats against when pedantic. */
367 #define C_STD_VER ((int) (c_dialect_cxx () \
368 ? CPLUSPLUS_STD_VER \
369 : (flag_isoc99 \
370 ? STD_C99 \
371 : (flag_isoc94 ? STD_C94 : STD_C89))))
372 /* The name to give to the standard version we are warning about when
373 pedantic. FEATURE_VER is the version in which the feature warned out
374 appeared, which is higher than C_STD_VER. */
375 #define C_STD_NAME(FEATURE_VER) (c_dialect_cxx () \
376 ? (cxx_dialect < cxx11 ? "ISO C++98" \
377 : "ISO C++11") \
378 : ((FEATURE_VER) == STD_EXT \
379 ? "ISO C" \
380 : "ISO C90"))
381 /* Adjust a C standard version, which may be STD_C9L, to account for
382 -Wno-long-long. Returns other standard versions unchanged. */
383 #define ADJ_STD(VER) ((int) ((VER) == STD_C9L \
384 ? (warn_long_long ? STD_C99 : STD_C89) \
385 : (VER)))
387 /* Enum describing the kind of specifiers present in the format and
388 requiring an argument. */
389 enum format_specifier_kind {
390 CF_KIND_FORMAT,
391 CF_KIND_FIELD_WIDTH,
392 CF_KIND_FIELD_PRECISION
395 static const char *kind_descriptions[] = {
396 N_("format"),
397 N_("field width specifier"),
398 N_("field precision specifier")
401 /* Structure describing details of a type expected in format checking,
402 and the type to check against it. */
403 struct format_wanted_type
405 /* The type wanted. */
406 tree wanted_type;
407 /* The name of this type to use in diagnostics. */
408 const char *wanted_type_name;
409 /* Should be type checked just for scalar width identity. */
410 int scalar_identity_flag;
411 /* The level of indirection through pointers at which this type occurs. */
412 int pointer_count;
413 /* Whether, when pointer_count is 1, to allow any character type when
414 pedantic, rather than just the character or void type specified. */
415 int char_lenient_flag;
416 /* Whether the argument, dereferenced once, is written into and so the
417 argument must not be a pointer to a const-qualified type. */
418 int writing_in_flag;
419 /* Whether the argument, dereferenced once, is read from and so
420 must not be a NULL pointer. */
421 int reading_from_flag;
422 /* The kind of specifier that this type is used for. */
423 enum format_specifier_kind kind;
424 /* The starting character of the specifier. This never includes the
425 initial percent sign. */
426 const char *format_start;
427 /* The length of the specifier. */
428 int format_length;
429 /* The actual parameter to check against the wanted type. */
430 tree param;
431 /* The argument number of that parameter. */
432 int arg_num;
433 /* The offset location of this argument with respect to the format
434 string location. */
435 unsigned int offset_loc;
436 /* The next type to check for this format conversion, or NULL if none. */
437 struct format_wanted_type *next;
440 /* Convenience macro for format_length_info meaning unused. */
441 #define NO_FMT NULL, FMT_LEN_none, STD_C89
443 static const format_length_info printf_length_specs[] =
445 { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99, 0 },
446 { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L, 0 },
447 { "q", FMT_LEN_ll, STD_EXT, NO_FMT, 0 },
448 { "L", FMT_LEN_L, STD_C89, NO_FMT, 0 },
449 { "z", FMT_LEN_z, STD_C99, NO_FMT, 0 },
450 { "Z", FMT_LEN_z, STD_EXT, NO_FMT, 0 },
451 { "t", FMT_LEN_t, STD_C99, NO_FMT, 0 },
452 { "j", FMT_LEN_j, STD_C99, NO_FMT, 0 },
453 { "H", FMT_LEN_H, STD_EXT, NO_FMT, 0 },
454 { "D", FMT_LEN_D, STD_EXT, "DD", FMT_LEN_DD, STD_EXT, 0 },
455 { NO_FMT, NO_FMT, 0 }
458 /* Length specifiers valid for asm_fprintf. */
459 static const format_length_info asm_fprintf_length_specs[] =
461 { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89, 0 },
462 { "w", FMT_LEN_none, STD_C89, NO_FMT, 0 },
463 { NO_FMT, NO_FMT, 0 }
466 /* Length specifiers valid for GCC diagnostics. */
467 static const format_length_info gcc_diag_length_specs[] =
469 { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89, 0 },
470 { "w", FMT_LEN_none, STD_C89, NO_FMT, 0 },
471 { NO_FMT, NO_FMT, 0 }
474 /* The custom diagnostics all accept the same length specifiers. */
475 #define gcc_tdiag_length_specs gcc_diag_length_specs
476 #define gcc_cdiag_length_specs gcc_diag_length_specs
477 #define gcc_cxxdiag_length_specs gcc_diag_length_specs
478 #define gcc_dump_printf_length_specs gcc_diag_length_specs
480 /* This differs from printf_length_specs only in that "Z" is not accepted. */
481 static const format_length_info scanf_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 { "t", FMT_LEN_t, STD_C99, NO_FMT, 0 },
489 { "j", FMT_LEN_j, STD_C99, NO_FMT, 0 },
490 { "H", FMT_LEN_H, STD_EXT, NO_FMT, 0 },
491 { "D", FMT_LEN_D, STD_EXT, "DD", FMT_LEN_DD, STD_EXT, 0 },
492 { NO_FMT, NO_FMT, 0 }
496 /* All tables for strfmon use STD_C89 everywhere, since -pedantic warnings
497 make no sense for a format type not part of any C standard version. */
498 static const format_length_info strfmon_length_specs[] =
500 /* A GNU extension. */
501 { "L", FMT_LEN_L, STD_C89, NO_FMT, 0 },
502 { NO_FMT, NO_FMT, 0 }
506 /* For now, the Fortran front-end routines only use l as length modifier. */
507 static const format_length_info gcc_gfc_length_specs[] =
509 { "l", FMT_LEN_l, STD_C89, NO_FMT, 0 },
510 { NO_FMT, NO_FMT, 0 }
514 static const format_flag_spec printf_flag_specs[] =
516 { ' ', 0, 0, 0, N_("' ' flag"), N_("the ' ' printf flag"), STD_C89 },
517 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89 },
518 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89 },
519 { '0', 0, 0, 0, N_("'0' flag"), N_("the '0' printf flag"), STD_C89 },
520 { '-', 0, 0, 0, N_("'-' flag"), N_("the '-' printf flag"), STD_C89 },
521 { '\'', 0, 0, 0, N_("''' flag"), N_("the ''' printf flag"), STD_EXT },
522 { 'I', 0, 0, 0, N_("'I' flag"), N_("the 'I' printf flag"), STD_EXT },
523 { 'w', 0, 0, 0, N_("field width"), N_("field width in printf format"), STD_C89 },
524 { 'p', 0, 0, 0, N_("precision"), N_("precision in printf format"), STD_C89 },
525 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
526 { 0, 0, 0, 0, NULL, NULL, STD_C89 }
530 static const format_flag_pair printf_flag_pairs[] =
532 { ' ', '+', 1, 0 },
533 { '0', '-', 1, 0 },
534 { '0', 'p', 1, 'i' },
535 { 0, 0, 0, 0 }
538 static const format_flag_spec asm_fprintf_flag_specs[] =
540 { ' ', 0, 0, 0, N_("' ' flag"), N_("the ' ' printf flag"), STD_C89 },
541 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89 },
542 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89 },
543 { '0', 0, 0, 0, N_("'0' flag"), N_("the '0' printf flag"), STD_C89 },
544 { '-', 0, 0, 0, N_("'-' flag"), N_("the '-' printf flag"), STD_C89 },
545 { 'w', 0, 0, 0, N_("field width"), N_("field width in printf format"), STD_C89 },
546 { 'p', 0, 0, 0, N_("precision"), N_("precision in printf format"), STD_C89 },
547 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
548 { 0, 0, 0, 0, NULL, NULL, STD_C89 }
551 static const format_flag_pair asm_fprintf_flag_pairs[] =
553 { ' ', '+', 1, 0 },
554 { '0', '-', 1, 0 },
555 { '0', 'p', 1, 'i' },
556 { 0, 0, 0, 0 }
559 static const format_flag_pair gcc_diag_flag_pairs[] =
561 { 0, 0, 0, 0 }
564 #define gcc_tdiag_flag_pairs gcc_diag_flag_pairs
565 #define gcc_cdiag_flag_pairs gcc_diag_flag_pairs
566 #define gcc_cxxdiag_flag_pairs gcc_diag_flag_pairs
567 #define gcc_gfc_flag_pairs gcc_diag_flag_pairs
568 #define gcc_dump_printf_flag_pairs gcc_diag_flag_pairs
570 static const format_flag_spec gcc_diag_flag_specs[] =
572 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89 },
573 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89 },
574 { 'q', 0, 0, 1, N_("'q' flag"), N_("the 'q' diagnostic flag"), STD_C89 },
575 { 'p', 0, 0, 0, N_("precision"), N_("precision in printf format"), STD_C89 },
576 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
577 { 0, 0, 0, 0, NULL, NULL, STD_C89 }
580 #define gcc_tdiag_flag_specs gcc_diag_flag_specs
581 #define gcc_cdiag_flag_specs gcc_diag_flag_specs
582 #define gcc_cxxdiag_flag_specs gcc_diag_flag_specs
583 #define gcc_gfc_flag_specs gcc_diag_flag_specs
584 #define gcc_dump_printf_flag_specs gcc_diag_flag_specs
586 static const format_flag_spec scanf_flag_specs[] =
588 { '*', 0, 0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89 },
589 { 'a', 0, 0, 0, N_("'a' flag"), N_("the 'a' scanf flag"), STD_EXT },
590 { 'm', 0, 0, 0, N_("'m' flag"), N_("the 'm' scanf flag"), STD_EXT },
591 { 'w', 0, 0, 0, N_("field width"), N_("field width in scanf format"), STD_C89 },
592 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in scanf format"), STD_C89 },
593 { '\'', 0, 0, 0, N_("''' flag"), N_("the ''' scanf flag"), STD_EXT },
594 { 'I', 0, 0, 0, N_("'I' flag"), N_("the 'I' scanf flag"), STD_EXT },
595 { 0, 0, 0, 0, NULL, NULL, STD_C89 }
599 static const format_flag_pair scanf_flag_pairs[] =
601 { '*', 'L', 0, 0 },
602 { 'a', 'm', 0, 0 },
603 { 0, 0, 0, 0 }
607 static const format_flag_spec strftime_flag_specs[] =
609 { '_', 0, 0, 0, N_("'_' flag"), N_("the '_' strftime flag"), STD_EXT },
610 { '-', 0, 0, 0, N_("'-' flag"), N_("the '-' strftime flag"), STD_EXT },
611 { '0', 0, 0, 0, N_("'0' flag"), N_("the '0' strftime flag"), STD_EXT },
612 { '^', 0, 0, 0, N_("'^' flag"), N_("the '^' strftime flag"), STD_EXT },
613 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' strftime flag"), STD_EXT },
614 { 'w', 0, 0, 0, N_("field width"), N_("field width in strftime format"), STD_EXT },
615 { 'E', 0, 0, 0, N_("'E' modifier"), N_("the 'E' strftime modifier"), STD_C99 },
616 { 'O', 0, 0, 0, N_("'O' modifier"), N_("the 'O' strftime modifier"), STD_C99 },
617 { 'O', 'o', 0, 0, NULL, N_("the 'O' modifier"), STD_EXT },
618 { 0, 0, 0, 0, NULL, NULL, STD_C89 }
622 static const format_flag_pair strftime_flag_pairs[] =
624 { 'E', 'O', 0, 0 },
625 { '_', '-', 0, 0 },
626 { '_', '0', 0, 0 },
627 { '-', '0', 0, 0 },
628 { '^', '#', 0, 0 },
629 { 0, 0, 0, 0 }
633 static const format_flag_spec strfmon_flag_specs[] =
635 { '=', 0, 1, 0, N_("fill character"), N_("fill character in strfmon format"), STD_C89 },
636 { '^', 0, 0, 0, N_("'^' flag"), N_("the '^' strfmon flag"), STD_C89 },
637 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' strfmon flag"), STD_C89 },
638 { '(', 0, 0, 0, N_("'(' flag"), N_("the '(' strfmon flag"), STD_C89 },
639 { '!', 0, 0, 0, N_("'!' flag"), N_("the '!' strfmon flag"), STD_C89 },
640 { '-', 0, 0, 0, N_("'-' flag"), N_("the '-' strfmon flag"), STD_C89 },
641 { 'w', 0, 0, 0, N_("field width"), N_("field width in strfmon format"), STD_C89 },
642 { '#', 0, 0, 0, N_("left precision"), N_("left precision in strfmon format"), STD_C89 },
643 { 'p', 0, 0, 0, N_("right precision"), N_("right precision in strfmon format"), STD_C89 },
644 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in strfmon format"), STD_C89 },
645 { 0, 0, 0, 0, NULL, NULL, STD_C89 }
648 static const format_flag_pair strfmon_flag_pairs[] =
650 { '+', '(', 0, 0 },
651 { 0, 0, 0, 0 }
655 static const format_char_info print_char_table[] =
657 /* C89 conversion specifiers. */
658 { "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 },
659 { "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 },
660 { "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 },
661 { "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 },
662 { "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 },
663 { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, T94_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL },
664 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "cR", NULL },
665 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "c", NULL },
666 { "n", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, T99_PD, T99_IM, BADLEN, BADLEN, BADLEN }, "", "W", NULL },
667 /* C99 conversion specifiers. */
668 { "F", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "-wp0 +#'I", "", NULL },
669 { "aA", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +#", "", NULL },
670 /* X/Open conversion specifiers. */
671 { "C", 0, STD_EXT, { TEX_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL },
672 { "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "R", NULL },
673 /* GNU conversion specifiers. */
674 { "m", 0, STD_EXT, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "", NULL },
675 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
678 static const format_char_info asm_fprintf_char_table[] =
680 /* C89 conversion specifiers. */
681 { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +", "i", NULL },
682 { "oxX", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0#", "i", NULL },
683 { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0", "i", NULL },
684 { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL },
685 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "cR", NULL },
687 /* asm_fprintf conversion specifiers. */
688 { "O", 0, STD_C89, NOARGUMENTS, "", "", NULL },
689 { "R", 0, STD_C89, NOARGUMENTS, "", "", NULL },
690 { "I", 0, STD_C89, NOARGUMENTS, "", "", NULL },
691 { "L", 0, STD_C89, NOARGUMENTS, "", "", NULL },
692 { "U", 0, STD_C89, NOARGUMENTS, "", "", NULL },
693 { "r", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", NULL },
694 { "z", 0, STD_C89, NOARGUMENTS, "", "", NULL },
695 { "@", 0, STD_C89, NOARGUMENTS, "", "", NULL },
696 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
699 /* GCC-specific format_char_info arrays. */
701 /* The conversion specifiers implemented within pp_format, and thus supported
702 by all pretty_printer instances within GCC. */
704 #define PP_FORMAT_CHAR_TABLE \
705 { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \
706 { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \
707 { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \
708 { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \
709 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL }, \
710 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, \
711 { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "//cR", NULL }, \
712 { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL }, \
713 { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL }, \
714 { "'" , 0, STD_C89, NOARGUMENTS, "", "", NULL }, \
715 { "R", 0, STD_C89, NOARGUMENTS, "", "\\", NULL }, \
716 { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, \
717 { "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_diag_char_table[0] }
719 static const format_char_info gcc_diag_char_table[] =
721 /* The conversion specifiers implemented within pp_format. */
722 PP_FORMAT_CHAR_TABLE,
724 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
727 static const format_char_info gcc_tdiag_char_table[] =
729 /* The conversion specifiers implemented within pp_format. */
730 PP_FORMAT_CHAR_TABLE,
732 /* Custom conversion specifiers implemented by default_tree_printer. */
734 /* These will require a "tree" at runtime. */
735 { "DFTV", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "'", NULL },
736 { "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL },
737 { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
739 /* G requires a "gimple*" argument at runtime. */
740 { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
742 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
745 static const format_char_info gcc_cdiag_char_table[] =
747 /* The conversion specifiers implemented within pp_format. */
748 PP_FORMAT_CHAR_TABLE,
750 /* Custom conversion specifiers implemented by c_tree_printer. */
752 /* These will require a "tree" at runtime. */
753 { "DFTV", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "'", NULL },
754 { "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL },
755 { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
757 /* G requires a "gimple*" argument at runtime. */
758 { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
760 { "v", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL },
762 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
765 static const format_char_info gcc_cxxdiag_char_table[] =
767 /* The conversion specifiers implemented within pp_format. */
768 PP_FORMAT_CHAR_TABLE,
770 /* Custom conversion specifiers implemented by cp_printer. */
772 /* These will require a "tree" at runtime. */
773 { "ADFHISTVX",1,STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, 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, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL },
775 { "K", 1, STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, 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, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
780 /* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.) */
781 { "CLOPQ",0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
783 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
786 static const format_char_info gcc_gfc_char_table[] =
788 /* C89 conversion specifiers. */
789 { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
790 { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
791 { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
792 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "cR", NULL },
794 /* gfc conversion specifiers. */
796 { "C", 0, STD_C89, NOARGUMENTS, "", "", NULL },
798 /* This will require a "locus" at runtime. */
799 { "L", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "R", NULL },
801 /* These will require nothing. */
802 { "<>",0, STD_C89, NOARGUMENTS, "", "", NULL },
803 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
806 static const format_char_info gcc_dump_printf_char_table[] =
808 /* The conversion specifiers implemented within pp_format. */
809 PP_FORMAT_CHAR_TABLE,
811 /* Custom conversion specifiers implemented by dump_pretty_printer. */
813 /* E and G require a "gimple *" argument at runtime. */
814 { "EG", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
816 /* C requires a "cgraph_node *" argument at runtime. */
817 { "C", 1, STD_C89, { T_CGRAPH_NODE, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
819 /* T requires a "tree" at runtime. */
820 { "T", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
822 /* %f requires a "double"; it doesn't support modifiers. */
823 { "f", 0, STD_C89, { T89_D, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
825 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
828 static const format_char_info scan_char_table[] =
830 /* C89 conversion specifiers. */
831 { "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 },
832 { "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 },
833 { "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 },
834 { "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 },
835 { "c", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*mw", "cW", NULL },
836 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*amw", "cW", NULL },
837 { "[", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*amw", "cW[", NULL },
838 { "p", 2, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL },
839 { "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 },
840 /* C99 conversion specifiers. */
841 { "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 },
842 { "aA", 1, STD_C99, { T99_F, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w'", "W", NULL },
843 /* X/Open conversion specifiers. */
844 { "C", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*mw", "W", NULL },
845 { "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*amw", "W", NULL },
846 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
849 static const format_char_info time_char_table[] =
851 /* C89 conversion specifiers. */
852 { "ABZab", 0, STD_C89, NOLENGTHS, "^#", "", NULL },
853 { "cx", 0, STD_C89, NOLENGTHS, "E", "3", NULL },
854 { "HIMSUWdmw", 0, STD_C89, NOLENGTHS, "-_0Ow", "", NULL },
855 { "j", 0, STD_C89, NOLENGTHS, "-_0Ow", "o", NULL },
856 { "p", 0, STD_C89, NOLENGTHS, "#", "", NULL },
857 { "X", 0, STD_C89, NOLENGTHS, "E", "", NULL },
858 { "y", 0, STD_C89, NOLENGTHS, "EO-_0w", "4", NULL },
859 { "Y", 0, STD_C89, NOLENGTHS, "-_0EOw", "o", NULL },
860 { "%", 0, STD_C89, NOLENGTHS, "", "", NULL },
861 /* C99 conversion specifiers. */
862 { "C", 0, STD_C99, NOLENGTHS, "-_0EOw", "o", NULL },
863 { "D", 0, STD_C99, NOLENGTHS, "", "2", NULL },
864 { "eVu", 0, STD_C99, NOLENGTHS, "-_0Ow", "", NULL },
865 { "FRTnrt", 0, STD_C99, NOLENGTHS, "", "", NULL },
866 { "g", 0, STD_C99, NOLENGTHS, "O-_0w", "2o", NULL },
867 { "G", 0, STD_C99, NOLENGTHS, "-_0Ow", "o", NULL },
868 { "h", 0, STD_C99, NOLENGTHS, "^#", "", NULL },
869 { "z", 0, STD_C99, NOLENGTHS, "O", "o", NULL },
870 /* GNU conversion specifiers. */
871 { "kls", 0, STD_EXT, NOLENGTHS, "-_0Ow", "", NULL },
872 { "P", 0, STD_EXT, NOLENGTHS, "", "", NULL },
873 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
876 static const format_char_info monetary_char_table[] =
878 { "in", 0, STD_C89, { T89_D, BADLEN, BADLEN, BADLEN, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "=^+(!-w#p", "", NULL },
879 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
882 /* This must be in the same order as enum format_type. */
883 static const format_kind_info format_types_orig[] =
885 { "gnu_printf", printf_length_specs, print_char_table, " +#0-'I", NULL,
886 printf_flag_specs, printf_flag_pairs,
887 FMT_FLAG_ARG_CONVERT|FMT_FLAG_DOLLAR_MULTIPLE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_EMPTY_PREC_OK,
888 'w', 0, 'p', 0, 'L', 0,
889 &integer_type_node, &integer_type_node
891 { "asm_fprintf", asm_fprintf_length_specs, asm_fprintf_char_table, " +#0-", NULL,
892 asm_fprintf_flag_specs, asm_fprintf_flag_pairs,
893 FMT_FLAG_ARG_CONVERT|FMT_FLAG_EMPTY_PREC_OK,
894 'w', 0, 'p', 0, 'L', 0,
895 NULL, NULL
897 { "gcc_diag", gcc_diag_length_specs, gcc_diag_char_table, "q+#", NULL,
898 gcc_diag_flag_specs, gcc_diag_flag_pairs,
899 FMT_FLAG_ARG_CONVERT,
900 0, 0, 'p', 0, 'L', 0,
901 NULL, &integer_type_node
903 { "gcc_tdiag", gcc_tdiag_length_specs, gcc_tdiag_char_table, "q+#", NULL,
904 gcc_tdiag_flag_specs, gcc_tdiag_flag_pairs,
905 FMT_FLAG_ARG_CONVERT,
906 0, 0, 'p', 0, 'L', 0,
907 NULL, &integer_type_node
909 { "gcc_cdiag", gcc_cdiag_length_specs, gcc_cdiag_char_table, "q+#", NULL,
910 gcc_cdiag_flag_specs, gcc_cdiag_flag_pairs,
911 FMT_FLAG_ARG_CONVERT,
912 0, 0, 'p', 0, 'L', 0,
913 NULL, &integer_type_node
915 { "gcc_cxxdiag", gcc_cxxdiag_length_specs, gcc_cxxdiag_char_table, "q+#", NULL,
916 gcc_cxxdiag_flag_specs, gcc_cxxdiag_flag_pairs,
917 FMT_FLAG_ARG_CONVERT,
918 0, 0, 'p', 0, 'L', 0,
919 NULL, &integer_type_node
921 { "gcc_gfc", gcc_gfc_length_specs, gcc_gfc_char_table, "q+#", NULL,
922 gcc_gfc_flag_specs, gcc_gfc_flag_pairs,
923 FMT_FLAG_ARG_CONVERT,
924 0, 0, 0, 0, 0, 0,
925 NULL, NULL
927 { "gcc_dump_printf", gcc_dump_printf_length_specs,
928 gcc_dump_printf_char_table, "q+#", NULL,
929 gcc_dump_printf_flag_specs, gcc_dump_printf_flag_pairs,
930 FMT_FLAG_ARG_CONVERT,
931 0, 0, 'p', 0, 'L', 0,
932 NULL, &integer_type_node
934 { "NSString", NULL, NULL, NULL, NULL,
935 NULL, NULL,
936 FMT_FLAG_ARG_CONVERT|FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL, 0, 0, 0, 0, 0, 0,
937 NULL, NULL
939 { "gnu_scanf", scanf_length_specs, scan_char_table, "*'I", NULL,
940 scanf_flag_specs, scanf_flag_pairs,
941 FMT_FLAG_ARG_CONVERT|FMT_FLAG_SCANF_A_KLUDGE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_ZERO_WIDTH_BAD|FMT_FLAG_DOLLAR_GAP_POINTER_OK,
942 'w', 0, 0, '*', 'L', 'm',
943 NULL, NULL
945 { "gnu_strftime", NULL, time_char_table, "_-0^#", "EO",
946 strftime_flag_specs, strftime_flag_pairs,
947 FMT_FLAG_FANCY_PERCENT_OK, 'w', 0, 0, 0, 0, 0,
948 NULL, NULL
950 { "gnu_strfmon", strfmon_length_specs, monetary_char_table, "=^+(!-", NULL,
951 strfmon_flag_specs, strfmon_flag_pairs,
952 FMT_FLAG_ARG_CONVERT, 'w', '#', 'p', 0, 'L', 0,
953 NULL, NULL
957 /* This layer of indirection allows GCC to reassign format_types with
958 new data if necessary, while still allowing the original data to be
959 const. */
960 static const format_kind_info *format_types = format_types_orig;
961 /* We can modify this one. We also add target-specific format types
962 to the end of the array. */
963 static format_kind_info *dynamic_format_types;
965 static int n_format_types = ARRAY_SIZE (format_types_orig);
967 /* Structure detailing the results of checking a format function call
968 where the format expression may be a conditional expression with
969 many leaves resulting from nested conditional expressions. */
970 struct format_check_results
972 /* Number of leaves of the format argument that could not be checked
973 as they were not string literals. */
974 int number_non_literal;
975 /* Number of leaves of the format argument that were null pointers or
976 string literals, but had extra format arguments. */
977 int number_extra_args;
978 location_t extra_arg_loc;
979 /* Number of leaves of the format argument that were null pointers or
980 string literals, but had extra format arguments and used $ operand
981 numbers. */
982 int number_dollar_extra_args;
983 /* Number of leaves of the format argument that were wide string
984 literals. */
985 int number_wide;
986 /* Number of leaves of the format argument that are not array of "char". */
987 int number_non_char;
988 /* Number of leaves of the format argument that were empty strings. */
989 int number_empty;
990 /* Number of leaves of the format argument that were unterminated
991 strings. */
992 int number_unterminated;
993 /* Number of leaves of the format argument that were not counted above. */
994 int number_other;
995 /* Location of the format string. */
996 location_t format_string_loc;
999 struct format_check_context
1001 format_check_results *res;
1002 function_format_info *info;
1003 tree params;
1004 vec<location_t> *arglocs;
1007 /* Return the format name (as specified in the original table) for the format
1008 type indicated by format_num. */
1009 static const char *
1010 format_name (int format_num)
1012 if (format_num >= 0 && format_num < n_format_types)
1013 return format_types[format_num].name;
1014 gcc_unreachable ();
1017 /* Return the format flags (as specified in the original table) for the format
1018 type indicated by format_num. */
1019 static int
1020 format_flags (int format_num)
1022 if (format_num >= 0 && format_num < n_format_types)
1023 return format_types[format_num].flags;
1024 gcc_unreachable ();
1027 static void check_format_info (function_format_info *, tree,
1028 vec<location_t> *);
1029 static void check_format_arg (void *, tree, unsigned HOST_WIDE_INT);
1030 static void check_format_info_main (format_check_results *,
1031 function_format_info *, const char *,
1032 location_t, tree,
1033 int, tree,
1034 unsigned HOST_WIDE_INT,
1035 object_allocator<format_wanted_type> &,
1036 vec<location_t> *);
1038 static void init_dollar_format_checking (int, tree);
1039 static int maybe_read_dollar_number (const char **, int,
1040 tree, tree *, const format_kind_info *);
1041 static bool avoid_dollar_number (const char *);
1042 static void finish_dollar_format_checking (format_check_results *, int);
1044 static const format_flag_spec *get_flag_spec (const format_flag_spec *,
1045 int, const char *);
1047 static void check_format_types (const substring_loc &fmt_loc,
1048 format_wanted_type *,
1049 const format_kind_info *fki,
1050 int offset_to_type_start,
1051 char conversion_char,
1052 vec<location_t> *arglocs);
1053 static void format_type_warning (const substring_loc &fmt_loc,
1054 location_t param_loc,
1055 format_wanted_type *, tree,
1056 tree,
1057 const format_kind_info *fki,
1058 int offset_to_type_start,
1059 char conversion_char);
1061 /* Decode a format type from a string, returning the type, or
1062 format_type_error if not valid, in which case the caller should print an
1063 error message. */
1064 static int
1065 decode_format_type (const char *s)
1067 int i;
1068 int slen;
1070 s = convert_format_name_to_system_name (s);
1071 slen = strlen (s);
1072 for (i = 0; i < n_format_types; i++)
1074 int alen;
1075 if (!strcmp (s, format_types[i].name))
1076 return i;
1077 alen = strlen (format_types[i].name);
1078 if (slen == alen + 4 && s[0] == '_' && s[1] == '_'
1079 && s[slen - 1] == '_' && s[slen - 2] == '_'
1080 && !strncmp (s + 2, format_types[i].name, alen))
1081 return i;
1083 return format_type_error;
1087 /* Check the argument list of a call to printf, scanf, etc.
1088 ATTRS are the attributes on the function type. There are NARGS argument
1089 values in the array ARGARRAY.
1090 Also, if -Wsuggest-attribute=format,
1091 warn for calls to vprintf or vscanf in functions with no such format
1092 attribute themselves. */
1094 void
1095 check_function_format (const_tree fntype, tree attrs, int nargs,
1096 tree *argarray, vec<location_t> *arglocs)
1098 tree a;
1100 tree atname = get_identifier ("format");
1102 /* See if this function has any format attributes. */
1103 for (a = attrs; a; a = TREE_CHAIN (a))
1105 if (is_attribute_p ("format", TREE_PURPOSE (a)))
1107 /* Yup; check it. */
1108 function_format_info info;
1109 decode_format_attr (fntype, atname, TREE_VALUE (a), &info,
1110 /*validated=*/true);
1111 if (warn_format)
1113 /* FIXME: Rewrite all the internal functions in this file
1114 to use the ARGARRAY directly instead of constructing this
1115 temporary list. */
1116 tree params = NULL_TREE;
1117 int i;
1118 for (i = nargs - 1; i >= 0; i--)
1119 params = tree_cons (NULL_TREE, argarray[i], params);
1120 check_format_info (&info, params, arglocs);
1123 /* Attempt to detect whether the current function might benefit
1124 from the format attribute if the called function is decorated
1125 with it. Avoid using calls with string literal formats for
1126 guidance since those are unlikely to be viable candidates. */
1127 if (warn_suggest_attribute_format
1128 && current_function_decl != NULL_TREE
1129 && info.first_arg_num == 0
1130 && (format_types[info.format_type].flags
1131 & (int) FMT_FLAG_ARG_CONVERT)
1132 /* c_strlen will fail for a function parameter but succeed
1133 for a literal or constant array. */
1134 && !c_strlen (argarray[info.format_num - 1], 1))
1136 tree c;
1137 for (c = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1139 c = TREE_CHAIN (c))
1140 if (is_attribute_p ("format", TREE_PURPOSE (c))
1141 && (decode_format_type (IDENTIFIER_POINTER
1142 (TREE_VALUE (TREE_VALUE (c))))
1143 == info.format_type))
1144 break;
1145 if (c == NULL_TREE)
1147 /* Check if the current function has a parameter to which
1148 the format attribute could be attached; if not, it
1149 can't be a candidate for a format attribute, despite
1150 the vprintf-like or vscanf-like call. */
1151 tree args;
1152 for (args = DECL_ARGUMENTS (current_function_decl);
1153 args != 0;
1154 args = DECL_CHAIN (args))
1156 if (TREE_CODE (TREE_TYPE (args)) == POINTER_TYPE
1157 && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (args)))
1158 == char_type_node))
1159 break;
1161 if (args != 0)
1162 warning (OPT_Wsuggest_attribute_format, "function %qD "
1163 "might be a candidate for %qs format attribute",
1164 current_function_decl,
1165 format_types[info.format_type].name);
1173 /* Variables used by the checking of $ operand number formats. */
1174 static char *dollar_arguments_used = NULL;
1175 static char *dollar_arguments_pointer_p = NULL;
1176 static int dollar_arguments_alloc = 0;
1177 static int dollar_arguments_count;
1178 static int dollar_first_arg_num;
1179 static int dollar_max_arg_used;
1180 static int dollar_format_warned;
1182 /* Initialize the checking for a format string that may contain $
1183 parameter number specifications; we will need to keep track of whether
1184 each parameter has been used. FIRST_ARG_NUM is the number of the first
1185 argument that is a parameter to the format, or 0 for a vprintf-style
1186 function; PARAMS is the list of arguments starting at this argument. */
1188 static void
1189 init_dollar_format_checking (int first_arg_num, tree params)
1191 tree oparams = params;
1193 dollar_first_arg_num = first_arg_num;
1194 dollar_arguments_count = 0;
1195 dollar_max_arg_used = 0;
1196 dollar_format_warned = 0;
1197 if (first_arg_num > 0)
1199 while (params)
1201 dollar_arguments_count++;
1202 params = TREE_CHAIN (params);
1205 if (dollar_arguments_alloc < dollar_arguments_count)
1207 free (dollar_arguments_used);
1208 free (dollar_arguments_pointer_p);
1209 dollar_arguments_alloc = dollar_arguments_count;
1210 dollar_arguments_used = XNEWVEC (char, dollar_arguments_alloc);
1211 dollar_arguments_pointer_p = XNEWVEC (char, dollar_arguments_alloc);
1213 if (dollar_arguments_alloc)
1215 memset (dollar_arguments_used, 0, dollar_arguments_alloc);
1216 if (first_arg_num > 0)
1218 int i = 0;
1219 params = oparams;
1220 while (params)
1222 dollar_arguments_pointer_p[i] = (TREE_CODE (TREE_TYPE (TREE_VALUE (params)))
1223 == POINTER_TYPE);
1224 params = TREE_CHAIN (params);
1225 i++;
1232 /* Look for a decimal number followed by a $ in *FORMAT. If DOLLAR_NEEDED
1233 is set, it is an error if one is not found; otherwise, it is OK. If
1234 such a number is found, check whether it is within range and mark that
1235 numbered operand as being used for later checking. Returns the operand
1236 number if found and within range, zero if no such number was found and
1237 this is OK, or -1 on error. PARAMS points to the first operand of the
1238 format; PARAM_PTR is made to point to the parameter referred to. If
1239 a $ format is found, *FORMAT is updated to point just after it. */
1241 static int
1242 maybe_read_dollar_number (const char **format,
1243 int dollar_needed, tree params, tree *param_ptr,
1244 const format_kind_info *fki)
1246 int argnum;
1247 int overflow_flag;
1248 const char *fcp = *format;
1249 if (!ISDIGIT (*fcp))
1251 if (dollar_needed)
1253 warning (OPT_Wformat_, "missing $ operand number in format");
1254 return -1;
1256 else
1257 return 0;
1259 argnum = 0;
1260 overflow_flag = 0;
1261 while (ISDIGIT (*fcp))
1263 int nargnum;
1264 nargnum = 10 * argnum + (*fcp - '0');
1265 if (nargnum < 0 || nargnum / 10 != argnum)
1266 overflow_flag = 1;
1267 argnum = nargnum;
1268 fcp++;
1270 if (*fcp != '$')
1272 if (dollar_needed)
1274 warning (OPT_Wformat_, "missing $ operand number in format");
1275 return -1;
1277 else
1278 return 0;
1280 *format = fcp + 1;
1281 if (pedantic && !dollar_format_warned)
1283 warning (OPT_Wformat_, "%s does not support %%n$ operand number formats",
1284 C_STD_NAME (STD_EXT));
1285 dollar_format_warned = 1;
1287 if (overflow_flag || argnum == 0
1288 || (dollar_first_arg_num && argnum > dollar_arguments_count))
1290 warning (OPT_Wformat_, "operand number out of range in format");
1291 return -1;
1293 if (argnum > dollar_max_arg_used)
1294 dollar_max_arg_used = argnum;
1295 /* For vprintf-style functions we may need to allocate more memory to
1296 track which arguments are used. */
1297 while (dollar_arguments_alloc < dollar_max_arg_used)
1299 int nalloc;
1300 nalloc = 2 * dollar_arguments_alloc + 16;
1301 dollar_arguments_used = XRESIZEVEC (char, dollar_arguments_used,
1302 nalloc);
1303 dollar_arguments_pointer_p = XRESIZEVEC (char, dollar_arguments_pointer_p,
1304 nalloc);
1305 memset (dollar_arguments_used + dollar_arguments_alloc, 0,
1306 nalloc - dollar_arguments_alloc);
1307 dollar_arguments_alloc = nalloc;
1309 if (!(fki->flags & (int) FMT_FLAG_DOLLAR_MULTIPLE)
1310 && dollar_arguments_used[argnum - 1] == 1)
1312 dollar_arguments_used[argnum - 1] = 2;
1313 warning (OPT_Wformat_, "format argument %d used more than once in %s format",
1314 argnum, fki->name);
1316 else
1317 dollar_arguments_used[argnum - 1] = 1;
1318 if (dollar_first_arg_num)
1320 int i;
1321 *param_ptr = params;
1322 for (i = 1; i < argnum && *param_ptr != 0; i++)
1323 *param_ptr = TREE_CHAIN (*param_ptr);
1325 /* This case shouldn't be caught here. */
1326 gcc_assert (*param_ptr);
1328 else
1329 *param_ptr = 0;
1330 return argnum;
1333 /* Ensure that FORMAT does not start with a decimal number followed by
1334 a $; give a diagnostic and return true if it does, false otherwise. */
1336 static bool
1337 avoid_dollar_number (const char *format)
1339 if (!ISDIGIT (*format))
1340 return false;
1341 while (ISDIGIT (*format))
1342 format++;
1343 if (*format == '$')
1345 warning (OPT_Wformat_, "$ operand number used after format without operand number");
1346 return true;
1348 return false;
1352 /* Finish the checking for a format string that used $ operand number formats
1353 instead of non-$ formats. We check for unused operands before used ones
1354 (a serious error, since the implementation of the format function
1355 can't know what types to pass to va_arg to find the later arguments).
1356 and for unused operands at the end of the format (if we know how many
1357 arguments the format had, so not for vprintf). If there were operand
1358 numbers out of range on a non-vprintf-style format, we won't have reached
1359 here. If POINTER_GAP_OK, unused arguments are OK if all arguments are
1360 pointers. */
1362 static void
1363 finish_dollar_format_checking (format_check_results *res, int pointer_gap_ok)
1365 int i;
1366 bool found_pointer_gap = false;
1367 for (i = 0; i < dollar_max_arg_used; i++)
1369 if (!dollar_arguments_used[i])
1371 if (pointer_gap_ok && (dollar_first_arg_num == 0
1372 || dollar_arguments_pointer_p[i]))
1373 found_pointer_gap = true;
1374 else
1375 warning_at (res->format_string_loc, OPT_Wformat_,
1376 "format argument %d unused before used argument %d in $-style format",
1377 i + 1, dollar_max_arg_used);
1380 if (found_pointer_gap
1381 || (dollar_first_arg_num
1382 && dollar_max_arg_used < dollar_arguments_count))
1384 res->number_other--;
1385 res->number_dollar_extra_args++;
1390 /* Retrieve the specification for a format flag. SPEC contains the
1391 specifications for format flags for the applicable kind of format.
1392 FLAG is the flag in question. If PREDICATES is NULL, the basic
1393 spec for that flag must be retrieved and must exist. If
1394 PREDICATES is not NULL, it is a string listing possible predicates
1395 for the spec entry; if an entry predicated on any of these is
1396 found, it is returned, otherwise NULL is returned. */
1398 static const format_flag_spec *
1399 get_flag_spec (const format_flag_spec *spec, int flag, const char *predicates)
1401 int i;
1402 for (i = 0; spec[i].flag_char != 0; i++)
1404 if (spec[i].flag_char != flag)
1405 continue;
1406 if (predicates != NULL)
1408 if (spec[i].predicate != 0
1409 && strchr (predicates, spec[i].predicate) != 0)
1410 return &spec[i];
1412 else if (spec[i].predicate == 0)
1413 return &spec[i];
1415 gcc_assert (predicates);
1416 return NULL;
1420 /* Check the argument list of a call to printf, scanf, etc.
1421 INFO points to the function_format_info structure.
1422 PARAMS is the list of argument values. */
1424 static void
1425 check_format_info (function_format_info *info, tree params,
1426 vec<location_t> *arglocs)
1428 format_check_context format_ctx;
1429 unsigned HOST_WIDE_INT arg_num;
1430 tree format_tree;
1431 format_check_results res;
1432 /* Skip to format argument. If the argument isn't available, there's
1433 no work for us to do; prototype checking will catch the problem. */
1434 for (arg_num = 1; ; ++arg_num)
1436 if (params == 0)
1437 return;
1438 if (arg_num == info->format_num)
1439 break;
1440 params = TREE_CHAIN (params);
1442 format_tree = TREE_VALUE (params);
1443 params = TREE_CHAIN (params);
1444 if (format_tree == 0)
1445 return;
1447 res.number_non_literal = 0;
1448 res.number_extra_args = 0;
1449 res.extra_arg_loc = UNKNOWN_LOCATION;
1450 res.number_dollar_extra_args = 0;
1451 res.number_wide = 0;
1452 res.number_non_char = 0;
1453 res.number_empty = 0;
1454 res.number_unterminated = 0;
1455 res.number_other = 0;
1456 res.format_string_loc = input_location;
1458 format_ctx.res = &res;
1459 format_ctx.info = info;
1460 format_ctx.params = params;
1461 format_ctx.arglocs = arglocs;
1463 check_function_arguments_recurse (check_format_arg, &format_ctx,
1464 format_tree, arg_num);
1466 location_t loc = format_ctx.res->format_string_loc;
1468 if (res.number_non_literal > 0)
1470 /* Functions taking a va_list normally pass a non-literal format
1471 string. These functions typically are declared with
1472 first_arg_num == 0, so avoid warning in those cases. */
1473 if (!(format_types[info->format_type].flags & (int) FMT_FLAG_ARG_CONVERT))
1475 /* For strftime-like formats, warn for not checking the format
1476 string; but there are no arguments to check. */
1477 warning_at (loc, OPT_Wformat_nonliteral,
1478 "format not a string literal, format string not checked");
1480 else if (info->first_arg_num != 0)
1482 /* If there are no arguments for the format at all, we may have
1483 printf (foo) which is likely to be a security hole. */
1484 while (arg_num + 1 < info->first_arg_num)
1486 if (params == 0)
1487 break;
1488 params = TREE_CHAIN (params);
1489 ++arg_num;
1491 if (params == 0 && warn_format_security)
1492 warning_at (loc, OPT_Wformat_security,
1493 "format not a string literal and no format arguments");
1494 else if (params == 0 && warn_format_nonliteral)
1495 warning_at (loc, OPT_Wformat_nonliteral,
1496 "format not a string literal and no format arguments");
1497 else
1498 warning_at (loc, OPT_Wformat_nonliteral,
1499 "format not a string literal, argument types not checked");
1503 /* If there were extra arguments to the format, normally warn. However,
1504 the standard does say extra arguments are ignored, so in the specific
1505 case where we have multiple leaves (conditional expressions or
1506 ngettext) allow extra arguments if at least one leaf didn't have extra
1507 arguments, but was otherwise OK (either non-literal or checked OK).
1508 If the format is an empty string, this should be counted similarly to the
1509 case of extra format arguments. */
1510 if (res.number_extra_args > 0 && res.number_non_literal == 0
1511 && res.number_other == 0)
1513 if (res.extra_arg_loc == UNKNOWN_LOCATION)
1514 res.extra_arg_loc = loc;
1515 warning_at (res.extra_arg_loc, OPT_Wformat_extra_args,
1516 "too many arguments for format");
1518 if (res.number_dollar_extra_args > 0 && res.number_non_literal == 0
1519 && res.number_other == 0)
1520 warning_at (loc, OPT_Wformat_extra_args, "unused arguments in $-style format");
1521 if (res.number_empty > 0 && res.number_non_literal == 0
1522 && res.number_other == 0)
1523 warning_at (loc, OPT_Wformat_zero_length, "zero-length %s format string",
1524 format_types[info->format_type].name);
1526 if (res.number_wide > 0)
1527 warning_at (loc, OPT_Wformat_, "format is a wide character string");
1529 if (res.number_non_char > 0)
1530 warning_at (loc, OPT_Wformat_,
1531 "format string is not an array of type %qs", "char");
1533 if (res.number_unterminated > 0)
1534 warning_at (loc, OPT_Wformat_, "unterminated format string");
1537 /* Callback from check_function_arguments_recurse to check a
1538 format string. FORMAT_TREE is the format parameter. ARG_NUM
1539 is the number of the format argument. CTX points to a
1540 format_check_context. */
1542 static void
1543 check_format_arg (void *ctx, tree format_tree,
1544 unsigned HOST_WIDE_INT arg_num)
1546 format_check_context *format_ctx = (format_check_context *) ctx;
1547 format_check_results *res = format_ctx->res;
1548 function_format_info *info = format_ctx->info;
1549 tree params = format_ctx->params;
1550 vec<location_t> *arglocs = format_ctx->arglocs;
1552 int format_length;
1553 HOST_WIDE_INT offset;
1554 const char *format_chars;
1555 tree array_size = 0;
1556 tree array_init;
1558 location_t fmt_param_loc = EXPR_LOC_OR_LOC (format_tree, input_location);
1560 /* Pull out a constant value if the front end didn't, and handle location
1561 wrappers. */
1562 format_tree = fold_for_warn (format_tree);
1563 STRIP_NOPS (format_tree);
1565 if (integer_zerop (format_tree))
1567 /* Skip to first argument to check, so we can see if this format
1568 has any arguments (it shouldn't). */
1569 while (arg_num + 1 < info->first_arg_num)
1571 if (params == 0)
1572 return;
1573 params = TREE_CHAIN (params);
1574 ++arg_num;
1577 if (params == 0)
1578 res->number_other++;
1579 else
1581 if (res->number_extra_args == 0)
1582 res->extra_arg_loc = EXPR_LOC_OR_LOC (TREE_VALUE (params),
1583 input_location);
1584 res->number_extra_args++;
1586 return;
1589 offset = 0;
1590 if (TREE_CODE (format_tree) == POINTER_PLUS_EXPR)
1592 tree arg0, arg1;
1594 arg0 = TREE_OPERAND (format_tree, 0);
1595 arg1 = TREE_OPERAND (format_tree, 1);
1596 STRIP_NOPS (arg0);
1597 STRIP_NOPS (arg1);
1598 if (TREE_CODE (arg1) == INTEGER_CST)
1599 format_tree = arg0;
1600 else
1602 res->number_non_literal++;
1603 return;
1605 /* POINTER_PLUS_EXPR offsets are to be interpreted signed. */
1606 if (!cst_and_fits_in_hwi (arg1))
1608 res->number_non_literal++;
1609 return;
1611 offset = int_cst_value (arg1);
1613 if (TREE_CODE (format_tree) != ADDR_EXPR)
1615 res->number_non_literal++;
1616 return;
1618 res->format_string_loc = EXPR_LOC_OR_LOC (format_tree, input_location);
1619 format_tree = TREE_OPERAND (format_tree, 0);
1620 if (format_types[info->format_type].flags
1621 & (int) FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL)
1623 bool objc_str = (info->format_type == gcc_objc_string_format_type);
1624 /* We cannot examine this string here - but we can check that it is
1625 a valid type. */
1626 if (TREE_CODE (format_tree) != CONST_DECL
1627 || !((objc_str && objc_string_ref_type_p (TREE_TYPE (format_tree)))
1628 || (*targetcm.string_object_ref_type_p)
1629 ((const_tree) TREE_TYPE (format_tree))))
1631 res->number_non_literal++;
1632 return;
1634 /* Skip to first argument to check. */
1635 while (arg_num + 1 < info->first_arg_num)
1637 if (params == 0)
1638 return;
1639 params = TREE_CHAIN (params);
1640 ++arg_num;
1642 /* So, we have a valid literal string object and one or more params.
1643 We need to use an external helper to parse the string into format
1644 info. For Objective-C variants we provide the resource within the
1645 objc tree, for target variants, via a hook. */
1646 if (objc_str)
1647 objc_check_format_arg (format_tree, params);
1648 else if (targetcm.check_string_object_format_arg)
1649 (*targetcm.check_string_object_format_arg) (format_tree, params);
1650 /* Else we can't handle it and retire quietly. */
1651 return;
1653 if (TREE_CODE (format_tree) == ARRAY_REF
1654 && tree_fits_shwi_p (TREE_OPERAND (format_tree, 1))
1655 && (offset += tree_to_shwi (TREE_OPERAND (format_tree, 1))) >= 0)
1656 format_tree = TREE_OPERAND (format_tree, 0);
1657 if (offset < 0)
1659 res->number_non_literal++;
1660 return;
1662 if (VAR_P (format_tree)
1663 && TREE_CODE (TREE_TYPE (format_tree)) == ARRAY_TYPE
1664 && (array_init = decl_constant_value (format_tree)) != format_tree
1665 && TREE_CODE (array_init) == STRING_CST)
1667 /* Extract the string constant initializer. Note that this may include
1668 a trailing NUL character that is not in the array (e.g.
1669 const char a[3] = "foo";). */
1670 array_size = DECL_SIZE_UNIT (format_tree);
1671 format_tree = array_init;
1673 if (TREE_CODE (format_tree) != STRING_CST)
1675 res->number_non_literal++;
1676 return;
1678 tree underlying_type
1679 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (format_tree)));
1680 if (underlying_type != char_type_node)
1682 if (underlying_type == char16_type_node
1683 || underlying_type == char32_type_node
1684 || underlying_type == wchar_type_node)
1685 res->number_wide++;
1686 else
1687 res->number_non_char++;
1688 return;
1690 format_chars = TREE_STRING_POINTER (format_tree);
1691 format_length = TREE_STRING_LENGTH (format_tree);
1692 if (array_size != 0)
1694 /* Variable length arrays can't be initialized. */
1695 gcc_assert (TREE_CODE (array_size) == INTEGER_CST);
1697 if (tree_fits_shwi_p (array_size))
1699 HOST_WIDE_INT array_size_value = tree_to_shwi (array_size);
1700 if (array_size_value > 0
1701 && array_size_value == (int) array_size_value
1702 && format_length > array_size_value)
1703 format_length = array_size_value;
1706 if (offset)
1708 if (offset >= format_length)
1710 res->number_non_literal++;
1711 return;
1713 format_chars += offset;
1714 format_length -= offset;
1716 if (format_length < 1 || format_chars[--format_length] != 0)
1718 res->number_unterminated++;
1719 return;
1721 if (format_length == 0)
1723 res->number_empty++;
1724 return;
1727 /* Skip to first argument to check. */
1728 while (arg_num + 1 < info->first_arg_num)
1730 if (params == 0)
1731 return;
1732 params = TREE_CHAIN (params);
1733 ++arg_num;
1735 /* Provisionally increment res->number_other; check_format_info_main
1736 will decrement it if it finds there are extra arguments, but this way
1737 need not adjust it for every return. */
1738 res->number_other++;
1739 object_allocator <format_wanted_type> fwt_pool ("format_wanted_type pool");
1740 check_format_info_main (res, info, format_chars, fmt_param_loc, format_tree,
1741 format_length, params, arg_num, fwt_pool, arglocs);
1744 /* Support class for argument_parser and check_format_info_main.
1745 Tracks any flag characters that have been applied to the
1746 current argument. */
1748 class flag_chars_t
1750 public:
1751 flag_chars_t ();
1752 bool has_char_p (char ch) const;
1753 void add_char (char ch);
1754 void validate (const format_kind_info *fki,
1755 const format_char_info *fci,
1756 const format_flag_spec *flag_specs,
1757 const char * const format_chars,
1758 tree format_string_cst,
1759 location_t format_string_loc,
1760 const char * const orig_format_chars,
1761 char format_char,
1762 bool quoted);
1763 int get_alloc_flag (const format_kind_info *fki);
1764 int assignment_suppression_p (const format_kind_info *fki);
1766 private:
1767 char m_flag_chars[256];
1770 /* Support struct for argument_parser and check_format_info_main.
1771 Encapsulates any length modifier applied to the current argument. */
1773 struct length_modifier
1775 length_modifier ()
1776 : chars (NULL), val (FMT_LEN_none), std (STD_C89),
1777 scalar_identity_flag (0)
1781 length_modifier (const char *chars_,
1782 enum format_lengths val_,
1783 enum format_std_version std_,
1784 int scalar_identity_flag_)
1785 : chars (chars_), val (val_), std (std_),
1786 scalar_identity_flag (scalar_identity_flag_)
1790 const char *chars;
1791 enum format_lengths val;
1792 enum format_std_version std;
1793 int scalar_identity_flag;
1796 /* Parsing one argument within a format string. */
1798 class argument_parser
1800 public:
1801 argument_parser (function_format_info *info, const char *&format_chars,
1802 tree format_string_cst,
1803 const char * const orig_format_chars,
1804 location_t format_string_loc, flag_chars_t &flag_chars,
1805 int &has_operand_number, tree first_fillin_param,
1806 object_allocator <format_wanted_type> &fwt_pool_,
1807 vec<location_t> *arglocs);
1809 bool read_any_dollar ();
1811 bool read_format_flags ();
1813 bool
1814 read_any_format_width (tree &params,
1815 unsigned HOST_WIDE_INT &arg_num);
1817 void
1818 read_any_format_left_precision ();
1820 bool
1821 read_any_format_precision (tree &params,
1822 unsigned HOST_WIDE_INT &arg_num);
1824 void handle_alloc_chars ();
1826 length_modifier read_any_length_modifier ();
1828 void read_any_other_modifier ();
1830 const format_char_info *find_format_char_info (char format_char);
1832 void
1833 validate_flag_pairs (const format_char_info *fci,
1834 char format_char);
1836 void
1837 give_y2k_warnings (const format_char_info *fci,
1838 char format_char);
1840 void parse_any_scan_set (const format_char_info *fci);
1842 bool handle_conversions (const format_char_info *fci,
1843 const length_modifier &len_modifier,
1844 tree &wanted_type,
1845 const char *&wanted_type_name,
1846 unsigned HOST_WIDE_INT &arg_num,
1847 tree &params,
1848 char format_char);
1850 bool
1851 check_argument_type (const format_char_info *fci,
1852 const length_modifier &len_modifier,
1853 tree &wanted_type,
1854 const char *&wanted_type_name,
1855 const bool suppressed,
1856 unsigned HOST_WIDE_INT &arg_num,
1857 tree &params,
1858 const int alloc_flag,
1859 const char * const format_start,
1860 const char * const type_start,
1861 location_t fmt_param_loc,
1862 char conversion_char);
1864 private:
1865 const function_format_info *const info;
1866 const format_kind_info * const fki;
1867 const format_flag_spec * const flag_specs;
1868 const char *start_of_this_format;
1869 const char *&format_chars;
1870 const tree format_string_cst;
1871 const char * const orig_format_chars;
1872 const location_t format_string_loc;
1873 object_allocator <format_wanted_type> &fwt_pool;
1874 flag_chars_t &flag_chars;
1875 int main_arg_num;
1876 tree main_arg_params;
1877 int &has_operand_number;
1878 const tree first_fillin_param;
1879 format_wanted_type width_wanted_type;
1880 format_wanted_type precision_wanted_type;
1881 public:
1882 format_wanted_type main_wanted_type;
1883 private:
1884 format_wanted_type *first_wanted_type;
1885 format_wanted_type *last_wanted_type;
1886 vec<location_t> *arglocs;
1889 /* flag_chars_t's constructor. */
1891 flag_chars_t::flag_chars_t ()
1893 m_flag_chars[0] = 0;
1896 /* Has CH been seen as a flag within the current argument? */
1898 bool
1899 flag_chars_t::has_char_p (char ch) const
1901 return strchr (m_flag_chars, ch) != 0;
1904 /* Add CH to the flags seen within the current argument. */
1906 void
1907 flag_chars_t::add_char (char ch)
1909 int i = strlen (m_flag_chars);
1910 m_flag_chars[i++] = ch;
1911 m_flag_chars[i] = 0;
1914 /* Validate the individual flags used, removing any that are invalid. */
1916 void
1917 flag_chars_t::validate (const format_kind_info *fki,
1918 const format_char_info *fci,
1919 const format_flag_spec *flag_specs,
1920 const char * const format_chars,
1921 tree format_string_cst,
1922 location_t format_string_loc,
1923 const char * const orig_format_chars,
1924 char format_char,
1925 bool quoted)
1927 int i;
1928 int d = 0;
1929 bool quotflag = false;
1931 for (i = 0; m_flag_chars[i] != 0; i++)
1933 const format_flag_spec *s = get_flag_spec (flag_specs,
1934 m_flag_chars[i], NULL);
1935 m_flag_chars[i - d] = m_flag_chars[i];
1936 if (m_flag_chars[i] == fki->length_code_char)
1937 continue;
1939 /* Remember if a quoting flag is seen. */
1940 quotflag |= s->quoting;
1942 if (strchr (fci->flag_chars, m_flag_chars[i]) == 0)
1944 format_warning_at_char (format_string_loc, format_string_cst,
1945 format_chars - orig_format_chars,
1946 OPT_Wformat_,
1947 "%s used with %<%%%c%> %s format",
1948 _(s->name), format_char, fki->name);
1949 d++;
1950 continue;
1952 if (pedantic)
1954 const format_flag_spec *t;
1955 if (ADJ_STD (s->std) > C_STD_VER)
1956 warning_at (format_string_loc, OPT_Wformat_,
1957 "%s does not support %s",
1958 C_STD_NAME (s->std), _(s->long_name));
1959 t = get_flag_spec (flag_specs, m_flag_chars[i], fci->flags2);
1960 if (t != NULL && ADJ_STD (t->std) > ADJ_STD (s->std))
1962 const char *long_name = (t->long_name != NULL
1963 ? t->long_name
1964 : s->long_name);
1965 if (ADJ_STD (t->std) > C_STD_VER)
1966 warning_at (format_string_loc, OPT_Wformat_,
1967 "%s does not support %s with"
1968 " the %<%%%c%> %s format",
1969 C_STD_NAME (t->std), _(long_name),
1970 format_char, fki->name);
1974 /* Detect quoting directives used within a quoted sequence, such
1975 as GCC's "%<...%qE". */
1976 if (quoted && s->quoting)
1978 format_warning_at_char (format_string_loc, format_string_cst,
1979 format_chars - orig_format_chars - 1,
1980 OPT_Wformat_,
1981 "%s used within a quoted sequence",
1982 _(s->name));
1985 m_flag_chars[i - d] = 0;
1987 if (!quoted
1988 && !quotflag
1989 && strchr (fci->flags2, '\''))
1991 format_warning_at_char (format_string_loc, format_string_cst,
1992 format_chars - orig_format_chars,
1993 OPT_Wformat_,
1994 "%qc conversion used unquoted",
1995 format_char);
1999 /* Determine if an assignment-allocation has been set, requiring
2000 an extra char ** for writing back a dynamically-allocated char *.
2001 This is for handling the optional 'm' character in scanf. */
2004 flag_chars_t::get_alloc_flag (const format_kind_info *fki)
2006 if ((fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE)
2007 && has_char_p ('a'))
2008 return 1;
2009 if (fki->alloc_char && has_char_p (fki->alloc_char))
2010 return 1;
2011 return 0;
2014 /* Determine if an assignment-suppression character was seen.
2015 ('*' in scanf, for discarding the converted input). */
2018 flag_chars_t::assignment_suppression_p (const format_kind_info *fki)
2020 if (fki->suppression_char
2021 && has_char_p (fki->suppression_char))
2022 return 1;
2023 return 0;
2026 /* Constructor for argument_parser. Initialize for parsing one
2027 argument within a format string. */
2029 argument_parser::
2030 argument_parser (function_format_info *info_, const char *&format_chars_,
2031 tree format_string_cst_,
2032 const char * const orig_format_chars_,
2033 location_t format_string_loc_,
2034 flag_chars_t &flag_chars_,
2035 int &has_operand_number_,
2036 tree first_fillin_param_,
2037 object_allocator <format_wanted_type> &fwt_pool_,
2038 vec<location_t> *arglocs_)
2039 : info (info_),
2040 fki (&format_types[info->format_type]),
2041 flag_specs (fki->flag_specs),
2042 start_of_this_format (format_chars_),
2043 format_chars (format_chars_),
2044 format_string_cst (format_string_cst_),
2045 orig_format_chars (orig_format_chars_),
2046 format_string_loc (format_string_loc_),
2047 fwt_pool (fwt_pool_),
2048 flag_chars (flag_chars_),
2049 main_arg_num (0),
2050 main_arg_params (NULL),
2051 has_operand_number (has_operand_number_),
2052 first_fillin_param (first_fillin_param_),
2053 first_wanted_type (NULL),
2054 last_wanted_type (NULL),
2055 arglocs (arglocs_)
2059 /* Handle dollars at the start of format arguments, setting up main_arg_params
2060 and main_arg_num.
2062 Return true if format parsing is to continue, false otherwise. */
2064 bool
2065 argument_parser::read_any_dollar ()
2067 if ((fki->flags & (int) FMT_FLAG_USE_DOLLAR) && has_operand_number != 0)
2069 /* Possibly read a $ operand number at the start of the format.
2070 If one was previously used, one is required here. If one
2071 is not used here, we can't immediately conclude this is a
2072 format without them, since it could be printf %m or scanf %*. */
2073 int opnum;
2074 opnum = maybe_read_dollar_number (&format_chars, 0,
2075 first_fillin_param,
2076 &main_arg_params, fki);
2077 if (opnum == -1)
2078 return false;
2079 else if (opnum > 0)
2081 has_operand_number = 1;
2082 main_arg_num = opnum + info->first_arg_num - 1;
2085 else if (fki->flags & FMT_FLAG_USE_DOLLAR)
2087 if (avoid_dollar_number (format_chars))
2088 return false;
2090 return true;
2093 /* Read any format flags, but do not yet validate them beyond removing
2094 duplicates, since in general validation depends on the rest of
2095 the format.
2097 Return true if format parsing is to continue, false otherwise. */
2099 bool
2100 argument_parser::read_format_flags ()
2102 while (*format_chars != 0
2103 && strchr (fki->flag_chars, *format_chars) != 0)
2105 const format_flag_spec *s = get_flag_spec (flag_specs,
2106 *format_chars, NULL);
2107 if (flag_chars.has_char_p (*format_chars))
2109 format_warning_at_char (format_string_loc, format_string_cst,
2110 format_chars + 1 - orig_format_chars,
2111 OPT_Wformat_,
2112 "repeated %s in format", _(s->name));
2114 else
2115 flag_chars.add_char (*format_chars);
2117 if (s->skip_next_char)
2119 ++format_chars;
2120 if (*format_chars == 0)
2122 warning_at (format_string_loc, OPT_Wformat_,
2123 "missing fill character at end of strfmon format");
2124 return false;
2127 ++format_chars;
2130 return true;
2133 /* Read any format width, possibly * or *m$.
2135 Return true if format parsing is to continue, false otherwise. */
2137 bool
2138 argument_parser::
2139 read_any_format_width (tree &params,
2140 unsigned HOST_WIDE_INT &arg_num)
2142 if (!fki->width_char)
2143 return true;
2145 if (fki->width_type != NULL && *format_chars == '*')
2147 flag_chars.add_char (fki->width_char);
2148 /* "...a field width...may be indicated by an asterisk.
2149 In this case, an int argument supplies the field width..." */
2150 ++format_chars;
2151 if (has_operand_number != 0)
2153 int opnum;
2154 opnum = maybe_read_dollar_number (&format_chars,
2155 has_operand_number == 1,
2156 first_fillin_param,
2157 &params, fki);
2158 if (opnum == -1)
2159 return false;
2160 else if (opnum > 0)
2162 has_operand_number = 1;
2163 arg_num = opnum + info->first_arg_num - 1;
2165 else
2166 has_operand_number = 0;
2168 else
2170 if (avoid_dollar_number (format_chars))
2171 return false;
2173 if (info->first_arg_num != 0)
2175 tree cur_param;
2176 if (params == 0)
2177 cur_param = NULL;
2178 else
2180 cur_param = TREE_VALUE (params);
2181 if (has_operand_number <= 0)
2183 params = TREE_CHAIN (params);
2184 ++arg_num;
2187 width_wanted_type.wanted_type = *fki->width_type;
2188 width_wanted_type.wanted_type_name = NULL;
2189 width_wanted_type.pointer_count = 0;
2190 width_wanted_type.char_lenient_flag = 0;
2191 width_wanted_type.scalar_identity_flag = 0;
2192 width_wanted_type.writing_in_flag = 0;
2193 width_wanted_type.reading_from_flag = 0;
2194 width_wanted_type.kind = CF_KIND_FIELD_WIDTH;
2195 width_wanted_type.format_start = format_chars - 1;
2196 width_wanted_type.format_length = 1;
2197 width_wanted_type.param = cur_param;
2198 width_wanted_type.arg_num = arg_num;
2199 width_wanted_type.offset_loc =
2200 format_chars - orig_format_chars;
2201 width_wanted_type.next = NULL;
2202 if (last_wanted_type != 0)
2203 last_wanted_type->next = &width_wanted_type;
2204 if (first_wanted_type == 0)
2205 first_wanted_type = &width_wanted_type;
2206 last_wanted_type = &width_wanted_type;
2209 else
2211 /* Possibly read a numeric width. If the width is zero,
2212 we complain if appropriate. */
2213 int non_zero_width_char = FALSE;
2214 int found_width = FALSE;
2215 while (ISDIGIT (*format_chars))
2217 found_width = TRUE;
2218 if (*format_chars != '0')
2219 non_zero_width_char = TRUE;
2220 ++format_chars;
2222 if (found_width && !non_zero_width_char &&
2223 (fki->flags & (int) FMT_FLAG_ZERO_WIDTH_BAD))
2224 warning_at (format_string_loc, OPT_Wformat_,
2225 "zero width in %s format", fki->name);
2226 if (found_width)
2227 flag_chars.add_char (fki->width_char);
2230 return true;
2233 /* Read any format left precision (must be a number, not *). */
2234 void
2235 argument_parser::read_any_format_left_precision ()
2237 if (fki->left_precision_char == 0)
2238 return;
2239 if (*format_chars != '#')
2240 return;
2242 ++format_chars;
2243 flag_chars.add_char (fki->left_precision_char);
2244 if (!ISDIGIT (*format_chars))
2245 format_warning_at_char (format_string_loc, format_string_cst,
2246 format_chars - orig_format_chars,
2247 OPT_Wformat_,
2248 "empty left precision in %s format", fki->name);
2249 while (ISDIGIT (*format_chars))
2250 ++format_chars;
2253 /* Read any format precision, possibly * or *m$.
2255 Return true if format parsing is to continue, false otherwise. */
2257 bool
2258 argument_parser::
2259 read_any_format_precision (tree &params,
2260 unsigned HOST_WIDE_INT &arg_num)
2262 if (fki->precision_char == 0)
2263 return true;
2264 if (*format_chars != '.')
2265 return true;
2267 ++format_chars;
2268 flag_chars.add_char (fki->precision_char);
2269 if (fki->precision_type != NULL && *format_chars == '*')
2271 /* "...a...precision...may be indicated by an asterisk.
2272 In this case, an int argument supplies the...precision." */
2273 ++format_chars;
2274 if (has_operand_number != 0)
2276 int opnum;
2277 opnum = maybe_read_dollar_number (&format_chars,
2278 has_operand_number == 1,
2279 first_fillin_param,
2280 &params, fki);
2281 if (opnum == -1)
2282 return false;
2283 else if (opnum > 0)
2285 has_operand_number = 1;
2286 arg_num = opnum + info->first_arg_num - 1;
2288 else
2289 has_operand_number = 0;
2291 else
2293 if (avoid_dollar_number (format_chars))
2294 return false;
2296 if (info->first_arg_num != 0)
2298 tree cur_param;
2299 if (params == 0)
2300 cur_param = NULL;
2301 else
2303 cur_param = TREE_VALUE (params);
2304 if (has_operand_number <= 0)
2306 params = TREE_CHAIN (params);
2307 ++arg_num;
2310 precision_wanted_type.wanted_type = *fki->precision_type;
2311 precision_wanted_type.wanted_type_name = NULL;
2312 precision_wanted_type.pointer_count = 0;
2313 precision_wanted_type.char_lenient_flag = 0;
2314 precision_wanted_type.scalar_identity_flag = 0;
2315 precision_wanted_type.writing_in_flag = 0;
2316 precision_wanted_type.reading_from_flag = 0;
2317 precision_wanted_type.kind = CF_KIND_FIELD_PRECISION;
2318 precision_wanted_type.param = cur_param;
2319 precision_wanted_type.format_start = format_chars - 2;
2320 precision_wanted_type.format_length = 2;
2321 precision_wanted_type.arg_num = arg_num;
2322 precision_wanted_type.offset_loc =
2323 format_chars - orig_format_chars;
2324 precision_wanted_type.next = NULL;
2325 if (last_wanted_type != 0)
2326 last_wanted_type->next = &precision_wanted_type;
2327 if (first_wanted_type == 0)
2328 first_wanted_type = &precision_wanted_type;
2329 last_wanted_type = &precision_wanted_type;
2332 else
2334 if (!(fki->flags & (int) FMT_FLAG_EMPTY_PREC_OK)
2335 && !ISDIGIT (*format_chars))
2336 format_warning_at_char (format_string_loc, format_string_cst,
2337 format_chars - orig_format_chars,
2338 OPT_Wformat_,
2339 "empty precision in %s format", fki->name);
2340 while (ISDIGIT (*format_chars))
2341 ++format_chars;
2344 return true;
2347 /* Parse any assignment-allocation flags, which request an extra
2348 char ** for writing back a dynamically-allocated char *.
2349 This is for handling the optional 'm' character in scanf,
2350 and, before C99, 'a' (for compatibility with a non-standard
2351 GNU libc extension). */
2353 void
2354 argument_parser::handle_alloc_chars ()
2356 if (fki->alloc_char && fki->alloc_char == *format_chars)
2358 flag_chars.add_char (fki->alloc_char);
2359 format_chars++;
2362 /* Handle the scanf allocation kludge. */
2363 if (fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE)
2365 if (*format_chars == 'a' && !flag_isoc99)
2367 if (format_chars[1] == 's' || format_chars[1] == 'S'
2368 || format_chars[1] == '[')
2370 /* 'a' is used as a flag. */
2371 flag_chars.add_char ('a');
2372 format_chars++;
2378 /* Look for length modifiers within the current format argument,
2379 returning a length_modifier instance describing it (or the
2380 default if one is not found).
2382 Issue warnings about non-standard modifiers. */
2384 length_modifier
2385 argument_parser::read_any_length_modifier ()
2387 length_modifier result;
2389 const format_length_info *fli = fki->length_char_specs;
2390 if (!fli)
2391 return result;
2393 while (fli->name != 0
2394 && strncmp (fli->name, format_chars, strlen (fli->name)))
2395 fli++;
2396 if (fli->name != 0)
2398 format_chars += strlen (fli->name);
2399 if (fli->double_name != 0 && fli->name[0] == *format_chars)
2401 format_chars++;
2402 result = length_modifier (fli->double_name, fli->double_index,
2403 fli->double_std, 0);
2405 else
2407 result = length_modifier (fli->name, fli->index, fli->std,
2408 fli->scalar_identity_flag);
2410 flag_chars.add_char (fki->length_code_char);
2412 if (pedantic)
2414 /* Warn if the length modifier is non-standard. */
2415 if (ADJ_STD (result.std) > C_STD_VER)
2416 warning_at (format_string_loc, OPT_Wformat_,
2417 "%s does not support the %qs %s length modifier",
2418 C_STD_NAME (result.std), result.chars,
2419 fki->name);
2422 return result;
2425 /* Read any other modifier (strftime E/O). */
2427 void
2428 argument_parser::read_any_other_modifier ()
2430 if (fki->modifier_chars == NULL)
2431 return;
2433 while (*format_chars != 0
2434 && strchr (fki->modifier_chars, *format_chars) != 0)
2436 if (flag_chars.has_char_p (*format_chars))
2438 const format_flag_spec *s = get_flag_spec (flag_specs,
2439 *format_chars, NULL);
2440 format_warning_at_char (format_string_loc, format_string_cst,
2441 format_chars - orig_format_chars,
2442 OPT_Wformat_,
2443 "repeated %s in format", _(s->name));
2445 else
2446 flag_chars.add_char (*format_chars);
2447 ++format_chars;
2451 /* Return the format_char_info corresponding to FORMAT_CHAR,
2452 potentially issuing a warning if the format char is
2453 not supported in the C standard version we are checking
2454 against.
2456 Issue a warning and return NULL if it is not found.
2458 Issue warnings about non-standard modifiers. */
2460 const format_char_info *
2461 argument_parser::find_format_char_info (char format_char)
2463 const format_char_info *fci = fki->conversion_specs;
2465 while (fci->format_chars != 0
2466 && strchr (fci->format_chars, format_char) == 0)
2467 ++fci;
2468 if (fci->format_chars == 0)
2470 format_warning_at_char (format_string_loc, format_string_cst,
2471 format_chars - orig_format_chars,
2472 OPT_Wformat_,
2473 "unknown conversion type character"
2474 " %qc in format",
2475 format_char);
2476 return NULL;
2479 if (pedantic)
2481 if (ADJ_STD (fci->std) > C_STD_VER)
2482 format_warning_at_char (format_string_loc, format_string_cst,
2483 format_chars - orig_format_chars,
2484 OPT_Wformat_,
2485 "%s does not support the %<%%%c%> %s format",
2486 C_STD_NAME (fci->std), format_char, fki->name);
2489 return fci;
2492 /* Validate the pairs of flags used.
2493 Issue warnings about incompatible combinations of flags. */
2495 void
2496 argument_parser::validate_flag_pairs (const format_char_info *fci,
2497 char format_char)
2499 const format_flag_pair * const bad_flag_pairs = fki->bad_flag_pairs;
2501 for (int i = 0; bad_flag_pairs[i].flag_char1 != 0; i++)
2503 const format_flag_spec *s, *t;
2504 if (!flag_chars.has_char_p (bad_flag_pairs[i].flag_char1))
2505 continue;
2506 if (!flag_chars.has_char_p (bad_flag_pairs[i].flag_char2))
2507 continue;
2508 if (bad_flag_pairs[i].predicate != 0
2509 && strchr (fci->flags2, bad_flag_pairs[i].predicate) == 0)
2510 continue;
2511 s = get_flag_spec (flag_specs, bad_flag_pairs[i].flag_char1, NULL);
2512 t = get_flag_spec (flag_specs, bad_flag_pairs[i].flag_char2, NULL);
2513 if (bad_flag_pairs[i].ignored)
2515 if (bad_flag_pairs[i].predicate != 0)
2516 warning_at (format_string_loc, OPT_Wformat_,
2517 "%s ignored with %s and %<%%%c%> %s format",
2518 _(s->name), _(t->name), format_char,
2519 fki->name);
2520 else
2521 warning_at (format_string_loc, OPT_Wformat_,
2522 "%s ignored with %s in %s format",
2523 _(s->name), _(t->name), fki->name);
2525 else
2527 if (bad_flag_pairs[i].predicate != 0)
2528 warning_at (format_string_loc, OPT_Wformat_,
2529 "use of %s and %s together with %<%%%c%> %s format",
2530 _(s->name), _(t->name), format_char,
2531 fki->name);
2532 else
2533 warning_at (format_string_loc, OPT_Wformat_,
2534 "use of %s and %s together in %s format",
2535 _(s->name), _(t->name), fki->name);
2540 /* Give Y2K warnings. */
2542 void
2543 argument_parser::give_y2k_warnings (const format_char_info *fci,
2544 char format_char)
2546 if (!warn_format_y2k)
2547 return;
2549 int y2k_level = 0;
2550 if (strchr (fci->flags2, '4') != 0)
2551 if (flag_chars.has_char_p ('E'))
2552 y2k_level = 3;
2553 else
2554 y2k_level = 2;
2555 else if (strchr (fci->flags2, '3') != 0)
2556 y2k_level = 3;
2557 else if (strchr (fci->flags2, '2') != 0)
2558 y2k_level = 2;
2559 if (y2k_level == 3)
2560 warning_at (format_string_loc, OPT_Wformat_y2k,
2561 "%<%%%c%> yields only last 2 digits of "
2562 "year in some locales", format_char);
2563 else if (y2k_level == 2)
2564 warning_at (format_string_loc, OPT_Wformat_y2k,
2565 "%<%%%c%> yields only last 2 digits of year",
2566 format_char);
2569 /* Parse any "scan sets" enclosed in square brackets, e.g.
2570 for scanf-style calls. */
2572 void
2573 argument_parser::parse_any_scan_set (const format_char_info *fci)
2575 if (strchr (fci->flags2, '[') == NULL)
2576 return;
2578 /* Skip over scan set, in case it happens to have '%' in it. */
2579 if (*format_chars == '^')
2580 ++format_chars;
2581 /* Find closing bracket; if one is hit immediately, then
2582 it's part of the scan set rather than a terminator. */
2583 if (*format_chars == ']')
2584 ++format_chars;
2585 while (*format_chars && *format_chars != ']')
2586 ++format_chars;
2587 if (*format_chars != ']')
2588 /* The end of the format string was reached. */
2589 format_warning_at_char (format_string_loc, format_string_cst,
2590 format_chars - orig_format_chars,
2591 OPT_Wformat_,
2592 "no closing %<]%> for %<%%[%> format");
2595 /* Return true if this argument is to be continued to be parsed,
2596 false to skip to next argument. */
2598 bool
2599 argument_parser::handle_conversions (const format_char_info *fci,
2600 const length_modifier &len_modifier,
2601 tree &wanted_type,
2602 const char *&wanted_type_name,
2603 unsigned HOST_WIDE_INT &arg_num,
2604 tree &params,
2605 char format_char)
2607 enum format_std_version wanted_type_std;
2609 if (!(fki->flags & (int) FMT_FLAG_ARG_CONVERT))
2610 return true;
2612 wanted_type = (fci->types[len_modifier.val].type
2613 ? *fci->types[len_modifier.val].type : 0);
2614 wanted_type_name = fci->types[len_modifier.val].name;
2615 wanted_type_std = fci->types[len_modifier.val].std;
2616 if (wanted_type == 0)
2618 format_warning_at_char (format_string_loc, format_string_cst,
2619 format_chars - orig_format_chars,
2620 OPT_Wformat_,
2621 "use of %qs length modifier with %qc type"
2622 " character has either no effect"
2623 " or undefined behavior",
2624 len_modifier.chars, format_char);
2625 /* Heuristic: skip one argument when an invalid length/type
2626 combination is encountered. */
2627 arg_num++;
2628 if (params != 0)
2629 params = TREE_CHAIN (params);
2630 return false;
2632 else if (pedantic
2633 /* Warn if non-standard, provided it is more non-standard
2634 than the length and type characters that may already
2635 have been warned for. */
2636 && ADJ_STD (wanted_type_std) > ADJ_STD (len_modifier.std)
2637 && ADJ_STD (wanted_type_std) > ADJ_STD (fci->std))
2639 if (ADJ_STD (wanted_type_std) > C_STD_VER)
2640 format_warning_at_char (format_string_loc, format_string_cst,
2641 format_chars - orig_format_chars,
2642 OPT_Wformat_,
2643 "%s does not support the %<%%%s%c%> %s format",
2644 C_STD_NAME (wanted_type_std),
2645 len_modifier.chars,
2646 format_char, fki->name);
2649 return true;
2652 /* Check type of argument against desired type.
2654 Return true if format parsing is to continue, false otherwise. */
2656 bool
2657 argument_parser::
2658 check_argument_type (const format_char_info *fci,
2659 const length_modifier &len_modifier,
2660 tree &wanted_type,
2661 const char *&wanted_type_name,
2662 const bool suppressed,
2663 unsigned HOST_WIDE_INT &arg_num,
2664 tree &params,
2665 const int alloc_flag,
2666 const char * const format_start,
2667 const char * const type_start,
2668 location_t fmt_param_loc,
2669 char conversion_char)
2671 if (info->first_arg_num == 0)
2672 return true;
2674 if ((fci->pointer_count == 0 && wanted_type == void_type_node)
2675 || suppressed)
2677 if (main_arg_num != 0)
2679 if (suppressed)
2680 warning_at (format_string_loc, OPT_Wformat_,
2681 "operand number specified with "
2682 "suppressed assignment");
2683 else
2684 warning_at (format_string_loc, OPT_Wformat_,
2685 "operand number specified for format "
2686 "taking no argument");
2689 else
2691 format_wanted_type *wanted_type_ptr;
2693 if (main_arg_num != 0)
2695 arg_num = main_arg_num;
2696 params = main_arg_params;
2698 else
2700 ++arg_num;
2701 if (has_operand_number > 0)
2703 warning_at (format_string_loc, OPT_Wformat_,
2704 "missing $ operand number in format");
2705 return false;
2707 else
2708 has_operand_number = 0;
2711 wanted_type_ptr = &main_wanted_type;
2712 while (fci)
2714 tree cur_param;
2715 if (params == 0)
2716 cur_param = NULL;
2717 else
2719 cur_param = TREE_VALUE (params);
2720 params = TREE_CHAIN (params);
2723 wanted_type_ptr->wanted_type = wanted_type;
2724 wanted_type_ptr->wanted_type_name = wanted_type_name;
2725 wanted_type_ptr->pointer_count = fci->pointer_count + alloc_flag;
2726 wanted_type_ptr->char_lenient_flag = 0;
2727 if (strchr (fci->flags2, 'c') != 0)
2728 wanted_type_ptr->char_lenient_flag = 1;
2729 wanted_type_ptr->scalar_identity_flag = 0;
2730 if (len_modifier.scalar_identity_flag)
2731 wanted_type_ptr->scalar_identity_flag = 1;
2732 wanted_type_ptr->writing_in_flag = 0;
2733 wanted_type_ptr->reading_from_flag = 0;
2734 if (alloc_flag)
2735 wanted_type_ptr->writing_in_flag = 1;
2736 else
2738 if (strchr (fci->flags2, 'W') != 0)
2739 wanted_type_ptr->writing_in_flag = 1;
2740 if (strchr (fci->flags2, 'R') != 0)
2741 wanted_type_ptr->reading_from_flag = 1;
2743 wanted_type_ptr->kind = CF_KIND_FORMAT;
2744 wanted_type_ptr->param = cur_param;
2745 wanted_type_ptr->arg_num = arg_num;
2746 wanted_type_ptr->format_start = format_start;
2747 wanted_type_ptr->format_length = format_chars - format_start;
2748 wanted_type_ptr->offset_loc = format_chars - orig_format_chars;
2749 wanted_type_ptr->next = NULL;
2750 if (last_wanted_type != 0)
2751 last_wanted_type->next = wanted_type_ptr;
2752 if (first_wanted_type == 0)
2753 first_wanted_type = wanted_type_ptr;
2754 last_wanted_type = wanted_type_ptr;
2756 fci = fci->chain;
2757 if (fci)
2759 wanted_type_ptr = fwt_pool.allocate ();
2760 arg_num++;
2761 wanted_type = *fci->types[len_modifier.val].type;
2762 wanted_type_name = fci->types[len_modifier.val].name;
2767 if (first_wanted_type != 0)
2769 ptrdiff_t offset_to_format_start = (start_of_this_format - 1) - orig_format_chars;
2770 ptrdiff_t offset_to_format_end = (format_chars - 1) - orig_format_chars;
2771 /* By default, use the end of the range for the caret location. */
2772 substring_loc fmt_loc (fmt_param_loc, TREE_TYPE (format_string_cst),
2773 offset_to_format_end,
2774 offset_to_format_start, offset_to_format_end);
2775 ptrdiff_t offset_to_type_start = type_start - orig_format_chars;
2776 check_format_types (fmt_loc, first_wanted_type, fki,
2777 offset_to_type_start,
2778 conversion_char, arglocs);
2781 return true;
2784 /* Do the main part of checking a call to a format function. FORMAT_CHARS
2785 is the NUL-terminated format string (which at this point may contain
2786 internal NUL characters); FORMAT_LENGTH is its length (excluding the
2787 terminating NUL character). ARG_NUM is one less than the number of
2788 the first format argument to check; PARAMS points to that format
2789 argument in the list of arguments. */
2791 static void
2792 check_format_info_main (format_check_results *res,
2793 function_format_info *info, const char *format_chars,
2794 location_t fmt_param_loc, tree format_string_cst,
2795 int format_length, tree params,
2796 unsigned HOST_WIDE_INT arg_num,
2797 object_allocator <format_wanted_type> &fwt_pool,
2798 vec<location_t> *arglocs)
2800 const char * const orig_format_chars = format_chars;
2801 const tree first_fillin_param = params;
2803 const format_kind_info * const fki = &format_types[info->format_type];
2804 const format_flag_spec * const flag_specs = fki->flag_specs;
2805 const location_t format_string_loc = res->format_string_loc;
2807 /* -1 if no conversions taking an operand have been found; 0 if one has
2808 and it didn't use $; 1 if $ formats are in use. */
2809 int has_operand_number = -1;
2811 /* Vector of pointers to opening quoting directives (like GCC "%<"). */
2812 auto_vec<const char*> quotdirs;
2814 /* Pointers to the most recent color directives (like GCC's "%r or %R").
2815 A starting color directive much be terminated before the end of
2816 the format string. A terminating directive makes no sense without
2817 a prior starting directive. */
2818 const char *color_begin = NULL;
2819 const char *color_end = NULL;
2821 init_dollar_format_checking (info->first_arg_num, first_fillin_param);
2823 while (*format_chars != 0)
2825 if (*format_chars++ != '%')
2826 continue;
2827 if (*format_chars == 0)
2829 format_warning_at_char (format_string_loc, format_string_cst,
2830 format_chars - orig_format_chars,
2831 OPT_Wformat_,
2832 "spurious trailing %<%%%> in format");
2833 continue;
2835 if (*format_chars == '%')
2837 ++format_chars;
2838 continue;
2841 flag_chars_t flag_chars;
2842 argument_parser arg_parser (info, format_chars, format_string_cst,
2843 orig_format_chars, format_string_loc,
2844 flag_chars, has_operand_number,
2845 first_fillin_param, fwt_pool, arglocs);
2847 if (!arg_parser.read_any_dollar ())
2848 return;
2850 if (!arg_parser.read_format_flags ())
2851 return;
2853 /* Read any format width, possibly * or *m$. */
2854 if (!arg_parser.read_any_format_width (params, arg_num))
2855 return;
2857 /* Read any format left precision (must be a number, not *). */
2858 arg_parser.read_any_format_left_precision ();
2860 /* Read any format precision, possibly * or *m$. */
2861 if (!arg_parser.read_any_format_precision (params, arg_num))
2862 return;
2864 const char *format_start = format_chars;
2866 arg_parser.handle_alloc_chars ();
2868 /* The rest of the conversion specification is the length modifier
2869 (if any), and the conversion specifier, so this is where the
2870 type information starts. If we need to issue a suggestion
2871 about a type mismatch, then we should preserve everything up
2872 to here. */
2873 const char *type_start = format_chars;
2875 /* Read any length modifier, if this kind of format has them. */
2876 const length_modifier len_modifier
2877 = arg_parser.read_any_length_modifier ();
2879 /* Read any modifier (strftime E/O). */
2880 arg_parser.read_any_other_modifier ();
2882 char format_char = *format_chars;
2883 if (format_char == 0
2884 || (!(fki->flags & (int) FMT_FLAG_FANCY_PERCENT_OK)
2885 && format_char == '%'))
2887 format_warning_at_char (format_string_loc, format_string_cst,
2888 format_chars - orig_format_chars,
2889 OPT_Wformat_,
2890 "conversion lacks type at end of format");
2891 continue;
2893 format_chars++;
2895 const format_char_info * const fci
2896 = arg_parser.find_format_char_info (format_char);
2897 if (!fci)
2898 continue;
2900 flag_chars.validate (fki, fci, flag_specs, format_chars,
2901 format_string_cst,
2902 format_string_loc, orig_format_chars, format_char,
2903 quotdirs.length () > 0);
2905 const int alloc_flag = flag_chars.get_alloc_flag (fki);
2906 const bool suppressed = flag_chars.assignment_suppression_p (fki);
2908 /* Diagnose nested or unmatched quoting directives such as GCC's
2909 "%<...%<" and "%>...%>". */
2910 bool quot_begin_p = strchr (fci->flags2, '<');
2911 bool quot_end_p = strchr (fci->flags2, '>');
2913 if (quot_begin_p && !quot_end_p)
2915 if (quotdirs.length ())
2916 format_warning_at_char (format_string_loc, format_string_cst,
2917 format_chars - orig_format_chars,
2918 OPT_Wformat_,
2919 "nested quoting directive");
2920 quotdirs.safe_push (format_chars);
2922 else if (!quot_begin_p && quot_end_p)
2924 if (quotdirs.length ())
2925 quotdirs.pop ();
2926 else
2927 format_warning_at_char (format_string_loc, format_string_cst,
2928 format_chars - orig_format_chars,
2929 OPT_Wformat_,
2930 "unmatched quoting directive");
2933 bool color_begin_p = strchr (fci->flags2, '/');
2934 if (color_begin_p)
2936 color_begin = format_chars;
2937 color_end = NULL;
2939 else if (strchr (fci->flags2, '\\'))
2941 if (color_end)
2942 format_warning_at_char (format_string_loc, format_string_cst,
2943 format_chars - orig_format_chars,
2944 OPT_Wformat_,
2945 "%qc directive redundant after prior "
2946 "occurence of the same", format_char);
2947 else if (!color_begin)
2948 format_warning_at_char (format_string_loc, format_string_cst,
2949 format_chars - orig_format_chars,
2950 OPT_Wformat_,
2951 "unmatched color reset directive");
2952 color_end = format_chars;
2955 /* Diagnose directives that shouldn't appear in a quoted sequence.
2956 (They are denoted by a double quote in FLAGS2.) */
2957 if (quotdirs.length ())
2959 if (strchr (fci->flags2, '"'))
2960 format_warning_at_char (format_string_loc, format_string_cst,
2961 format_chars - orig_format_chars,
2962 OPT_Wformat_,
2963 "%qc conversion used within a quoted "
2964 "sequence",
2965 format_char);
2968 /* Validate the pairs of flags used. */
2969 arg_parser.validate_flag_pairs (fci, format_char);
2971 arg_parser.give_y2k_warnings (fci, format_char);
2973 arg_parser.parse_any_scan_set (fci);
2975 tree wanted_type = NULL;
2976 const char *wanted_type_name = NULL;
2978 if (!arg_parser.handle_conversions (fci, len_modifier,
2979 wanted_type, wanted_type_name,
2980 arg_num,
2981 params,
2982 format_char))
2983 continue;
2985 arg_parser.main_wanted_type.next = NULL;
2987 /* Finally. . .check type of argument against desired type! */
2988 if (!arg_parser.check_argument_type (fci, len_modifier,
2989 wanted_type, wanted_type_name,
2990 suppressed,
2991 arg_num, params,
2992 alloc_flag,
2993 format_start, type_start,
2994 fmt_param_loc,
2995 format_char))
2996 return;
2999 if (format_chars - orig_format_chars != format_length)
3000 format_warning_at_char (format_string_loc, format_string_cst,
3001 format_chars + 1 - orig_format_chars,
3002 OPT_Wformat_contains_nul,
3003 "embedded %<\\0%> in format");
3004 if (info->first_arg_num != 0 && params != 0
3005 && has_operand_number <= 0)
3007 res->number_other--;
3008 res->number_extra_args++;
3010 if (has_operand_number > 0)
3011 finish_dollar_format_checking (res, fki->flags & (int) FMT_FLAG_DOLLAR_GAP_POINTER_OK);
3013 if (quotdirs.length ())
3014 format_warning_at_char (format_string_loc, format_string_cst,
3015 quotdirs.pop () - orig_format_chars,
3016 OPT_Wformat_, "unterminated quoting directive");
3017 if (color_begin && !color_end)
3018 format_warning_at_char (format_string_loc, format_string_cst,
3019 color_begin - orig_format_chars,
3020 OPT_Wformat_, "unterminated color directive");
3023 /* Check the argument types from a single format conversion (possibly
3024 including width and precision arguments).
3026 FMT_LOC is the location of the format conversion.
3028 TYPES is a singly-linked list expressing the parts of the format
3029 conversion that expect argument types, and the arguments they
3030 correspond to.
3032 OFFSET_TO_TYPE_START is the offset within the execution-charset encoded
3033 format string to where type information begins for the conversion
3034 (the length modifier and conversion specifier).
3036 CONVERSION_CHAR is the user-provided conversion specifier.
3038 For example, given:
3040 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
3042 then FMT_LOC covers this range:
3044 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
3045 ^^^^^^^^^
3047 and TYPES in this case is a three-entry singly-linked list consisting of:
3048 (1) the check for the field width here:
3049 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
3050 ^ ^^^^
3051 against arg3, and
3052 (2) the check for the field precision here:
3053 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
3054 ^^ ^^^^
3055 against arg4, and
3056 (3) the check for the length modifier and conversion char here:
3057 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
3058 ^^^ ^^^^
3059 against arg5.
3061 OFFSET_TO_TYPE_START is 13, the offset to the "lld" within the
3062 STRING_CST:
3064 0000000000111111111122
3065 0123456789012345678901
3066 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
3068 | ` CONVERSION_CHAR: 'd'
3069 type starts here. */
3071 static void
3072 check_format_types (const substring_loc &fmt_loc,
3073 format_wanted_type *types, const format_kind_info *fki,
3074 int offset_to_type_start,
3075 char conversion_char,
3076 vec<location_t> *arglocs)
3078 for (; types != 0; types = types->next)
3080 tree cur_param;
3081 tree cur_type;
3082 tree orig_cur_type;
3083 tree wanted_type;
3084 int arg_num;
3085 int i;
3086 int char_type_flag;
3088 wanted_type = types->wanted_type;
3089 arg_num = types->arg_num;
3091 /* The following should not occur here. */
3092 gcc_assert (wanted_type);
3093 gcc_assert (wanted_type != void_type_node || types->pointer_count);
3095 if (types->pointer_count == 0)
3096 wanted_type = lang_hooks.types.type_promotes_to (wanted_type);
3098 wanted_type = TYPE_MAIN_VARIANT (wanted_type);
3100 cur_param = types->param;
3101 if (!cur_param)
3103 format_type_warning (fmt_loc, UNKNOWN_LOCATION, types, wanted_type,
3104 NULL, fki, offset_to_type_start,
3105 conversion_char);
3106 continue;
3109 cur_type = TREE_TYPE (cur_param);
3110 if (cur_type == error_mark_node)
3111 continue;
3112 orig_cur_type = cur_type;
3113 char_type_flag = 0;
3115 location_t param_loc = UNKNOWN_LOCATION;
3116 if (EXPR_HAS_LOCATION (cur_param))
3117 param_loc = EXPR_LOCATION (cur_param);
3118 else if (arglocs)
3120 /* arg_num is 1-based. */
3121 gcc_assert (types->arg_num > 0);
3122 param_loc = (*arglocs)[types->arg_num - 1];
3125 STRIP_NOPS (cur_param);
3127 /* Check the types of any additional pointer arguments
3128 that precede the "real" argument. */
3129 for (i = 0; i < types->pointer_count; ++i)
3131 if (TREE_CODE (cur_type) == POINTER_TYPE)
3133 cur_type = TREE_TYPE (cur_type);
3134 if (cur_type == error_mark_node)
3135 break;
3137 /* Check for writing through a NULL pointer. */
3138 if (types->writing_in_flag
3139 && i == 0
3140 && cur_param != 0
3141 && integer_zerop (cur_param))
3142 warning (OPT_Wformat_, "writing through null pointer "
3143 "(argument %d)", arg_num);
3145 /* Check for reading through a NULL pointer. Ignore
3146 printf-family of functions as they are checked for
3147 null arguments by the middle-end. */
3148 if (fki->conversion_specs != print_char_table
3149 && types->reading_from_flag
3150 && i == 0
3151 && cur_param != 0
3152 && integer_zerop (cur_param))
3153 warning (OPT_Wformat_, "reading through null pointer "
3154 "(argument %d)", arg_num);
3156 if (cur_param != 0 && TREE_CODE (cur_param) == ADDR_EXPR)
3157 cur_param = TREE_OPERAND (cur_param, 0);
3158 else
3159 cur_param = 0;
3161 /* See if this is an attempt to write into a const type with
3162 scanf or with printf "%n". Note: the writing in happens
3163 at the first indirection only, if for example
3164 void * const * is passed to scanf %p; passing
3165 const void ** is simply passing an incompatible type. */
3166 if (types->writing_in_flag
3167 && i == 0
3168 && (TYPE_READONLY (cur_type)
3169 || (cur_param != 0
3170 && (CONSTANT_CLASS_P (cur_param)
3171 || (DECL_P (cur_param)
3172 && TREE_READONLY (cur_param))))))
3173 warning (OPT_Wformat_, "writing into constant object "
3174 "(argument %d)", arg_num);
3176 /* If there are extra type qualifiers beyond the first
3177 indirection, then this makes the types technically
3178 incompatible. */
3179 if (i > 0
3180 && pedantic
3181 && (TYPE_READONLY (cur_type)
3182 || TYPE_VOLATILE (cur_type)
3183 || TYPE_ATOMIC (cur_type)
3184 || TYPE_RESTRICT (cur_type)))
3185 warning (OPT_Wformat_, "extra type qualifiers in format "
3186 "argument (argument %d)",
3187 arg_num);
3190 else
3192 format_type_warning (fmt_loc, param_loc,
3193 types, wanted_type, orig_cur_type, fki,
3194 offset_to_type_start, conversion_char);
3195 break;
3199 if (i < types->pointer_count)
3200 continue;
3202 cur_type = TYPE_MAIN_VARIANT (cur_type);
3204 /* Check whether the argument type is a character type. This leniency
3205 only applies to certain formats, flagged with 'c'. */
3206 if (types->char_lenient_flag)
3207 char_type_flag = (cur_type == char_type_node
3208 || cur_type == signed_char_type_node
3209 || cur_type == unsigned_char_type_node);
3211 /* Check the type of the "real" argument, if there's a type we want. */
3212 if (lang_hooks.types_compatible_p (wanted_type, cur_type))
3213 continue;
3214 /* If we want 'void *', allow any pointer type.
3215 (Anything else would already have got a warning.)
3216 With -Wpedantic, only allow pointers to void and to character
3217 types. */
3218 if (wanted_type == void_type_node
3219 && (!pedantic || (i == 1 && char_type_flag)))
3220 continue;
3221 /* Don't warn about differences merely in signedness, unless
3222 -Wpedantic. With -Wpedantic, warn if the type is a pointer
3223 target and not a character type, and for character types at
3224 a second level of indirection. */
3225 if (TREE_CODE (wanted_type) == INTEGER_TYPE
3226 && TREE_CODE (cur_type) == INTEGER_TYPE
3227 && ((!pedantic && !warn_format_signedness)
3228 || (i == 0 && !warn_format_signedness)
3229 || (i == 1 && char_type_flag))
3230 && (TYPE_UNSIGNED (wanted_type)
3231 ? wanted_type == c_common_unsigned_type (cur_type)
3232 : wanted_type == c_common_signed_type (cur_type)))
3233 continue;
3234 /* Don't warn about differences merely in signedness if we know
3235 that the current type is integer-promoted and its original type
3236 was unsigned such as that it is in the range of WANTED_TYPE. */
3237 if (TREE_CODE (wanted_type) == INTEGER_TYPE
3238 && TREE_CODE (cur_type) == INTEGER_TYPE
3239 && warn_format_signedness
3240 && TYPE_UNSIGNED (wanted_type)
3241 && cur_param != NULL_TREE
3242 && TREE_CODE (cur_param) == NOP_EXPR)
3244 tree t = TREE_TYPE (TREE_OPERAND (cur_param, 0));
3245 if (TYPE_UNSIGNED (t)
3246 && cur_type == lang_hooks.types.type_promotes_to (t))
3247 continue;
3249 /* Likewise, "signed char", "unsigned char" and "char" are
3250 equivalent but the above test won't consider them equivalent. */
3251 if (wanted_type == char_type_node
3252 && (!pedantic || i < 2)
3253 && char_type_flag)
3254 continue;
3255 if (types->scalar_identity_flag
3256 && (TREE_CODE (cur_type) == TREE_CODE (wanted_type)
3257 || (INTEGRAL_TYPE_P (cur_type)
3258 && INTEGRAL_TYPE_P (wanted_type)))
3259 && TYPE_PRECISION (cur_type) == TYPE_PRECISION (wanted_type))
3260 continue;
3261 /* Now we have a type mismatch. */
3262 format_type_warning (fmt_loc, param_loc, types,
3263 wanted_type, orig_cur_type, fki,
3264 offset_to_type_start, conversion_char);
3268 /* Given type TYPE, attempt to dereference the type N times
3269 (e.g. from ("int ***", 2) to "int *")
3271 Return the derefenced type, with any qualifiers
3272 such as "const" stripped from the result, or
3273 NULL if unsuccessful (e.g. TYPE is not a pointer type). */
3275 static tree
3276 deref_n_times (tree type, int n)
3278 gcc_assert (type);
3280 for (int i = n; i > 0; i--)
3282 if (TREE_CODE (type) != POINTER_TYPE)
3283 return NULL_TREE;
3284 type = TREE_TYPE (type);
3286 /* Strip off any "const" etc. */
3287 return build_qualified_type (type, 0);
3290 /* Lookup the format code for FORMAT_LEN within FLI,
3291 returning the string code for expressing it, or NULL
3292 if it is not found. */
3294 static const char *
3295 get_modifier_for_format_len (const format_length_info *fli,
3296 enum format_lengths format_len)
3298 for (; fli->name; fli++)
3300 if (fli->index == format_len)
3301 return fli->name;
3302 if (fli->double_index == format_len)
3303 return fli->double_name;
3305 return NULL;
3308 #if CHECKING_P
3310 namespace selftest {
3312 static void
3313 test_get_modifier_for_format_len ()
3315 ASSERT_STREQ ("h",
3316 get_modifier_for_format_len (printf_length_specs, FMT_LEN_h));
3317 ASSERT_STREQ ("hh",
3318 get_modifier_for_format_len (printf_length_specs, FMT_LEN_hh));
3319 ASSERT_STREQ ("L",
3320 get_modifier_for_format_len (printf_length_specs, FMT_LEN_L));
3321 ASSERT_EQ (NULL,
3322 get_modifier_for_format_len (printf_length_specs, FMT_LEN_none));
3325 } // namespace selftest
3327 #endif /* CHECKING_P */
3329 /* Determine if SPEC_TYPE and ARG_TYPE are sufficiently similar for a
3330 format_type_detail using SPEC_TYPE to be offered as a suggestion for
3331 Wformat type errors where the argument has type ARG_TYPE. */
3333 static bool
3334 matching_type_p (tree spec_type, tree arg_type)
3336 gcc_assert (spec_type);
3337 gcc_assert (arg_type);
3339 /* If any of the types requires structural equality, we can't compare
3340 their canonical types. */
3341 if (TYPE_STRUCTURAL_EQUALITY_P (spec_type)
3342 || TYPE_STRUCTURAL_EQUALITY_P (arg_type))
3343 return false;
3345 spec_type = TYPE_CANONICAL (spec_type);
3346 arg_type = TYPE_CANONICAL (arg_type);
3348 if (TREE_CODE (spec_type) == INTEGER_TYPE
3349 && TREE_CODE (arg_type) == INTEGER_TYPE
3350 && (TYPE_UNSIGNED (spec_type)
3351 ? spec_type == c_common_unsigned_type (arg_type)
3352 : spec_type == c_common_signed_type (arg_type)))
3353 return true;
3355 return spec_type == arg_type;
3358 /* Subroutine of get_format_for_type.
3360 Generate a string containing the length modifier and conversion specifier
3361 that should be used to format arguments of type ARG_TYPE within FKI
3362 (effectively the inverse of the checking code).
3364 If CONVERSION_CHAR is not zero (the first pass), the resulting suggestion
3365 is required to use it, for correcting bogus length modifiers.
3366 If CONVERSION_CHAR is zero (the second pass), then allow any suggestion
3367 that matches ARG_TYPE.
3369 If successful, returns a non-NULL string which should be freed
3370 by the caller.
3371 Otherwise, returns NULL. */
3373 static char *
3374 get_format_for_type_1 (const format_kind_info *fki, tree arg_type,
3375 char conversion_char)
3377 gcc_assert (arg_type);
3379 const format_char_info *spec;
3380 for (spec = &fki->conversion_specs[0];
3381 spec->format_chars;
3382 spec++)
3384 if (conversion_char)
3385 if (!strchr (spec->format_chars, conversion_char))
3386 continue;
3388 tree effective_arg_type = deref_n_times (arg_type,
3389 spec->pointer_count);
3390 if (!effective_arg_type)
3391 continue;
3392 for (int i = 0; i < FMT_LEN_MAX; i++)
3394 const format_type_detail *ftd = &spec->types[i];
3395 if (!ftd->type)
3396 continue;
3397 if (matching_type_p (*ftd->type, effective_arg_type))
3399 const char *len_modifier
3400 = get_modifier_for_format_len (fki->length_char_specs,
3401 (enum format_lengths)i);
3402 if (!len_modifier)
3403 len_modifier = "";
3405 if (conversion_char)
3406 /* We found a match, using the given conversion char - the
3407 length modifier was incorrect (or absent).
3408 Provide a suggestion using the conversion char with the
3409 correct length modifier for the type. */
3410 return xasprintf ("%s%c", len_modifier, conversion_char);
3411 else
3412 /* 2nd pass: no match was possible using the user-provided
3413 conversion char, but we do have a match without using it.
3414 Provide a suggestion using the first conversion char
3415 listed for the given type. */
3416 return xasprintf ("%s%c", len_modifier, spec->format_chars[0]);
3421 return NULL;
3424 /* Generate a string containing the length modifier and conversion specifier
3425 that should be used to format arguments of type ARG_TYPE within FKI
3426 (effectively the inverse of the checking code).
3428 If successful, returns a non-NULL string which should be freed
3429 by the caller.
3430 Otherwise, returns NULL. */
3432 static char *
3433 get_format_for_type (const format_kind_info *fki, tree arg_type,
3434 char conversion_char)
3436 gcc_assert (arg_type);
3437 gcc_assert (conversion_char);
3439 /* First pass: look for a format_char_info containing CONVERSION_CHAR
3440 If we find one, then presumably the length modifier was incorrect
3441 (or absent). */
3442 char *result = get_format_for_type_1 (fki, arg_type, conversion_char);
3443 if (result)
3444 return result;
3446 /* Second pass: we didn't find a match for CONVERSION_CHAR, so try
3447 matching just on the type. */
3448 return get_format_for_type_1 (fki, arg_type, '\0');
3451 /* Attempt to get a string for use as a replacement fix-it hint for the
3452 source range in FMT_LOC.
3454 Preserve all of the text within the range of FMT_LOC up to
3455 OFFSET_TO_TYPE_START, replacing the rest with an appropriate
3456 length modifier and conversion specifier for ARG_TYPE, attempting
3457 to keep the user-provided CONVERSION_CHAR if possible.
3459 For example, given a long vs long long mismatch for arg5 here:
3461 000000000111111111122222222223333333333|
3462 123456789012345678901234567890123456789` column numbers
3463 0000000000111111111122|
3464 0123456789012345678901` string offsets
3465 V~~~~~~~~ : range of FMT_LOC, from cols 23-31
3466 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
3468 | ` CONVERSION_CHAR: 'd'
3469 type starts here
3471 where OFFSET_TO_TYPE_START is 13 (the offset to the "lld" within the
3472 STRING_CST), where the user provided:
3473 %-+*.*lld
3474 the result (assuming "long" argument 5) should be:
3475 %-+*.*ld
3477 If successful, returns a non-NULL string which should be freed
3478 by the caller.
3479 Otherwise, returns NULL. */
3481 static char *
3482 get_corrected_substring (const substring_loc &fmt_loc,
3483 format_wanted_type *type, tree arg_type,
3484 const format_kind_info *fki,
3485 int offset_to_type_start, char conversion_char)
3487 /* Attempt to provide hints for argument types, but not for field widths
3488 and precisions. */
3489 if (!arg_type)
3490 return NULL;
3491 if (type->kind != CF_KIND_FORMAT)
3492 return NULL;
3494 /* Locate the current code within the source range, rejecting
3495 any awkward cases where the format string occupies more than
3496 one line.
3497 Lookup the place where the type starts (including any length
3498 modifiers), getting it as the caret location. */
3499 substring_loc type_loc (fmt_loc);
3500 type_loc.set_caret_index (offset_to_type_start);
3502 location_t fmt_substring_loc;
3503 const char *err = type_loc.get_location (&fmt_substring_loc);
3504 if (err)
3505 return NULL;
3507 source_range fmt_substring_range
3508 = get_range_from_loc (line_table, fmt_substring_loc);
3510 expanded_location caret
3511 = expand_location_to_spelling_point (fmt_substring_loc);
3512 expanded_location start
3513 = expand_location_to_spelling_point (fmt_substring_range.m_start);
3514 expanded_location finish
3515 = expand_location_to_spelling_point (fmt_substring_range.m_finish);
3516 if (caret.file != start.file)
3517 return NULL;
3518 if (start.file != finish.file)
3519 return NULL;
3520 if (caret.line != start.line)
3521 return NULL;
3522 if (start.line != finish.line)
3523 return NULL;
3524 if (start.column > caret.column)
3525 return NULL;
3526 if (start.column > finish.column)
3527 return NULL;
3528 if (caret.column > finish.column)
3529 return NULL;
3531 char_span line = location_get_source_line (start.file, start.line);
3532 if (!line)
3533 return NULL;
3535 /* If we got this far, then we have the line containing the
3536 existing conversion specification.
3538 Generate a trimmed copy, containing the prefix part of the conversion
3539 specification, up to the (but not including) the length modifier.
3540 In the above example, this would be "%-+*.*". */
3541 int length_up_to_type = caret.column - start.column;
3542 char_span prefix_span = line.subspan (start.column - 1, length_up_to_type);
3543 char *prefix = prefix_span.xstrdup ();
3545 /* Now attempt to generate a suggestion for the rest of the specification
3546 (length modifier and conversion char), based on ARG_TYPE and
3547 CONVERSION_CHAR.
3548 In the above example, this would be "ld". */
3549 char *format_for_type = get_format_for_type (fki, arg_type, conversion_char);
3550 if (!format_for_type)
3552 free (prefix);
3553 return NULL;
3556 /* Success. Generate the resulting suggestion for the whole range of
3557 FMT_LOC by concatenating the two strings.
3558 In the above example, this would be "%-+*.*ld". */
3559 char *result = concat (prefix, format_for_type, NULL);
3560 free (format_for_type);
3561 free (prefix);
3562 return result;
3565 /* Helper class for adding zero or more trailing '*' to types.
3567 The format type and name exclude any '*' for pointers, so those
3568 must be formatted manually. For all the types we currently have,
3569 this is adequate, but formats taking pointers to functions or
3570 arrays would require the full type to be built up in order to
3571 print it with %T. */
3573 class indirection_suffix
3575 public:
3576 indirection_suffix (int pointer_count) : m_pointer_count (pointer_count) {}
3578 /* Determine the size of the buffer (including NUL-terminator). */
3580 size_t get_buffer_size () const
3582 return m_pointer_count + 2;
3585 /* Write the '*' to DST and add a NUL-terminator. */
3587 void fill_buffer (char *dst) const
3589 if (m_pointer_count == 0)
3590 dst[0] = 0;
3591 else if (c_dialect_cxx ())
3593 memset (dst, '*', m_pointer_count);
3594 dst[m_pointer_count] = 0;
3596 else
3598 dst[0] = ' ';
3599 memset (dst + 1, '*', m_pointer_count);
3600 dst[m_pointer_count + 1] = 0;
3604 private:
3605 int m_pointer_count;
3608 /* Subclass of range_label for labelling the range in the format string
3609 with the type in question, adding trailing '*' for pointer_count. */
3611 class range_label_for_format_type_mismatch
3612 : public range_label_for_type_mismatch
3614 public:
3615 range_label_for_format_type_mismatch (tree labelled_type, tree other_type,
3616 int pointer_count)
3617 : range_label_for_type_mismatch (labelled_type, other_type),
3618 m_pointer_count (pointer_count)
3622 label_text get_text (unsigned range_idx) const FINAL OVERRIDE
3624 label_text text = range_label_for_type_mismatch::get_text (range_idx);
3625 if (text.m_buffer == NULL)
3626 return text;
3628 indirection_suffix suffix (m_pointer_count);
3629 char *p = (char *) alloca (suffix.get_buffer_size ());
3630 suffix.fill_buffer (p);
3632 char *result = concat (text.m_buffer, p, NULL);
3633 text.maybe_free ();
3634 return label_text (result, true);
3637 private:
3638 int m_pointer_count;
3641 /* Give a warning about a format argument of different type from that expected.
3642 The range of the diagnostic is taken from WHOLE_FMT_LOC; the caret location
3643 is based on the location of the char at TYPE->offset_loc.
3644 PARAM_LOC is the location of the relevant argument, or UNKNOWN_LOCATION
3645 if this is unavailable.
3646 WANTED_TYPE is the type the argument should have,
3647 possibly stripped of pointer dereferences. The description (such as "field
3648 precision"), the placement in the format string, a possibly more
3649 friendly name of WANTED_TYPE, and the number of pointer dereferences
3650 are taken from TYPE. ARG_TYPE is the type of the actual argument,
3651 or NULL if it is missing.
3653 OFFSET_TO_TYPE_START is the offset within the execution-charset encoded
3654 format string to where type information begins for the conversion
3655 (the length modifier and conversion specifier).
3656 CONVERSION_CHAR is the user-provided conversion specifier.
3658 For example, given a type mismatch for argument 5 here:
3660 00000000011111111112222222222333333333344444444445555555555|
3661 12345678901234567890123456789012345678901234567890123456789` column numbers
3662 0000000000111111111122|
3663 0123456789012345678901` offsets within STRING_CST
3664 V~~~~~~~~ : range of WHOLE_FMT_LOC, from cols 23-31
3665 sprintf (d, "before %-+*.*lld after", int_expr, int_expr, long_expr);
3666 ^ ^ ^~~~~~~~~
3667 | ` CONVERSION_CHAR: 'd' PARAM_LOC
3668 type starts here
3670 OFFSET_TO_TYPE_START is 13, the offset to the "lld" within the
3671 STRING_CST. */
3673 static void
3674 format_type_warning (const substring_loc &whole_fmt_loc,
3675 location_t param_loc,
3676 format_wanted_type *type,
3677 tree wanted_type, tree arg_type,
3678 const format_kind_info *fki,
3679 int offset_to_type_start,
3680 char conversion_char)
3682 enum format_specifier_kind kind = type->kind;
3683 const char *wanted_type_name = type->wanted_type_name;
3684 const char *format_start = type->format_start;
3685 int format_length = type->format_length;
3686 int pointer_count = type->pointer_count;
3687 int arg_num = type->arg_num;
3689 /* If ARG_TYPE is a typedef with a misleading name (for example,
3690 size_t but not the standard size_t expected by printf %zu), avoid
3691 printing the typedef name. */
3692 if (wanted_type_name
3693 && arg_type
3694 && TYPE_NAME (arg_type)
3695 && TREE_CODE (TYPE_NAME (arg_type)) == TYPE_DECL
3696 && DECL_NAME (TYPE_NAME (arg_type))
3697 && !strcmp (wanted_type_name,
3698 lang_hooks.decl_printable_name (TYPE_NAME (arg_type), 2)))
3699 arg_type = TYPE_MAIN_VARIANT (arg_type);
3701 indirection_suffix suffix (pointer_count);
3702 char *p = (char *) alloca (suffix.get_buffer_size ());
3703 suffix.fill_buffer (p);
3705 /* WHOLE_FMT_LOC has the caret at the end of the range.
3706 Set the caret to be at the offset from TYPE. Subtract one
3707 from the offset for the same reason as in format_warning_at_char. */
3708 substring_loc fmt_loc (whole_fmt_loc);
3709 fmt_loc.set_caret_index (type->offset_loc - 1);
3711 range_label_for_format_type_mismatch fmt_label (wanted_type, arg_type,
3712 pointer_count);
3713 range_label_for_type_mismatch param_label (arg_type, wanted_type);
3715 /* Get a string for use as a replacement fix-it hint for the range in
3716 fmt_loc, or NULL. */
3717 char *corrected_substring
3718 = get_corrected_substring (fmt_loc, type, arg_type, fki,
3719 offset_to_type_start, conversion_char);
3720 format_string_diagnostic_t diag (fmt_loc, &fmt_label, param_loc, &param_label,
3721 corrected_substring);
3722 if (wanted_type_name)
3724 if (arg_type)
3725 diag.emit_warning
3726 (OPT_Wformat_,
3727 "%s %<%s%.*s%> expects argument of type %<%s%s%>, "
3728 "but argument %d has type %qT",
3729 gettext (kind_descriptions[kind]),
3730 (kind == CF_KIND_FORMAT ? "%" : ""),
3731 format_length, format_start,
3732 wanted_type_name, p, arg_num, arg_type);
3733 else
3734 diag.emit_warning
3735 (OPT_Wformat_,
3736 "%s %<%s%.*s%> expects a matching %<%s%s%> argument",
3737 gettext (kind_descriptions[kind]),
3738 (kind == CF_KIND_FORMAT ? "%" : ""),
3739 format_length, format_start, wanted_type_name, p);
3741 else
3743 if (arg_type)
3744 diag.emit_warning
3745 (OPT_Wformat_,
3746 "%s %<%s%.*s%> expects argument of type %<%T%s%>, "
3747 "but argument %d has type %qT",
3748 gettext (kind_descriptions[kind]),
3749 (kind == CF_KIND_FORMAT ? "%" : ""),
3750 format_length, format_start,
3751 wanted_type, p, arg_num, arg_type);
3752 else
3753 diag.emit_warning
3754 (OPT_Wformat_,
3755 "%s %<%s%.*s%> expects a matching %<%T%s%> argument",
3756 gettext (kind_descriptions[kind]),
3757 (kind == CF_KIND_FORMAT ? "%" : ""),
3758 format_length, format_start, wanted_type, p);
3761 free (corrected_substring);
3765 /* Given a format_char_info array FCI, and a character C, this function
3766 returns the index into the conversion_specs where that specifier's
3767 data is located. The character must exist. */
3768 static unsigned int
3769 find_char_info_specifier_index (const format_char_info *fci, int c)
3771 unsigned i;
3773 for (i = 0; fci->format_chars; i++, fci++)
3774 if (strchr (fci->format_chars, c))
3775 return i;
3777 /* We shouldn't be looking for a non-existent specifier. */
3778 gcc_unreachable ();
3781 /* Given a format_length_info array FLI, and a character C, this
3782 function returns the index into the conversion_specs where that
3783 modifier's data is located. The character must exist. */
3784 static unsigned int
3785 find_length_info_modifier_index (const format_length_info *fli, int c)
3787 unsigned i;
3789 for (i = 0; fli->name; i++, fli++)
3790 if (strchr (fli->name, c))
3791 return i;
3793 /* We shouldn't be looking for a non-existent modifier. */
3794 gcc_unreachable ();
3797 /* Determine the type of HOST_WIDE_INT in the code being compiled for
3798 use in GCC's __asm_fprintf__ custom format attribute. You must
3799 have set dynamic_format_types before calling this function. */
3800 static void
3801 init_dynamic_asm_fprintf_info (void)
3803 static tree hwi;
3805 if (!hwi)
3807 format_length_info *new_asm_fprintf_length_specs;
3808 unsigned int i;
3810 /* Find the underlying type for HOST_WIDE_INT. For the %w
3811 length modifier to work, one must have issued: "typedef
3812 HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code
3813 prior to using that modifier. */
3814 hwi = maybe_get_identifier ("__gcc_host_wide_int__");
3815 if (!hwi)
3817 error ("%<__gcc_host_wide_int__%> is not defined as a type");
3818 return;
3820 hwi = identifier_global_value (hwi);
3821 if (!hwi || TREE_CODE (hwi) != TYPE_DECL)
3823 error ("%<__gcc_host_wide_int__%> is not defined as a type");
3824 return;
3826 hwi = DECL_ORIGINAL_TYPE (hwi);
3827 gcc_assert (hwi);
3828 if (hwi != long_integer_type_node && hwi != long_long_integer_type_node)
3830 error ("%<__gcc_host_wide_int__%> is not defined as %<long%>"
3831 " or %<long long%>");
3832 return;
3835 /* Create a new (writable) copy of asm_fprintf_length_specs. */
3836 new_asm_fprintf_length_specs = (format_length_info *)
3837 xmemdup (asm_fprintf_length_specs,
3838 sizeof (asm_fprintf_length_specs),
3839 sizeof (asm_fprintf_length_specs));
3841 /* HOST_WIDE_INT must be one of 'long' or 'long long'. */
3842 i = find_length_info_modifier_index (new_asm_fprintf_length_specs, 'w');
3843 if (hwi == long_integer_type_node)
3844 new_asm_fprintf_length_specs[i].index = FMT_LEN_l;
3845 else if (hwi == long_long_integer_type_node)
3846 new_asm_fprintf_length_specs[i].index = FMT_LEN_ll;
3847 else
3848 gcc_unreachable ();
3850 /* Assign the new data for use. */
3851 dynamic_format_types[asm_fprintf_format_type].length_char_specs =
3852 new_asm_fprintf_length_specs;
3856 /* Determine the type of a "locus" in the code being compiled for use
3857 in GCC's __gcc_gfc__ custom format attribute. You must have set
3858 dynamic_format_types before calling this function. */
3859 static void
3860 init_dynamic_gfc_info (void)
3862 if (!locus)
3864 static format_char_info *gfc_fci;
3866 /* For the GCC __gcc_gfc__ custom format specifier to work, one
3867 must have declared 'locus' prior to using this attribute. If
3868 we haven't seen this declarations then you shouldn't use the
3869 specifier requiring that type. */
3870 if ((locus = maybe_get_identifier ("locus")))
3872 locus = identifier_global_value (locus);
3873 if (locus)
3875 if (TREE_CODE (locus) != TYPE_DECL
3876 || TREE_TYPE (locus) == error_mark_node)
3878 error ("%<locus%> is not defined as a type");
3879 locus = 0;
3881 else
3882 locus = TREE_TYPE (locus);
3886 /* Assign the new data for use. */
3888 /* Handle the __gcc_gfc__ format specifics. */
3889 if (!gfc_fci)
3890 dynamic_format_types[gcc_gfc_format_type].conversion_specs =
3891 gfc_fci = (format_char_info *)
3892 xmemdup (gcc_gfc_char_table,
3893 sizeof (gcc_gfc_char_table),
3894 sizeof (gcc_gfc_char_table));
3895 if (locus)
3897 const unsigned i = find_char_info_specifier_index (gfc_fci, 'L');
3898 gfc_fci[i].types[0].type = &locus;
3899 gfc_fci[i].pointer_count = 1;
3904 /* Lookup the type named NAME and return a pointer-to-NAME type if found.
3905 Otherwise, return void_type_node if NAME has not been used yet, or NULL_TREE if
3906 NAME is not a type (issuing an error). */
3908 static tree
3909 get_pointer_to_named_type (const char *name)
3911 tree result;
3912 if ((result = maybe_get_identifier (name)))
3914 result = identifier_global_value (result);
3915 if (result)
3917 if (TREE_CODE (result) != TYPE_DECL)
3919 error ("%qs is not defined as a type", name);
3920 result = NULL_TREE;
3922 else
3923 result = TREE_TYPE (result);
3926 else
3927 result = void_type_node;
3928 return result;
3931 /* Determine the types of "tree" and "location_t" in the code being
3932 compiled for use in GCC's diagnostic custom format attributes. You
3933 must have set dynamic_format_types before calling this function. */
3934 static void
3935 init_dynamic_diag_info (void)
3937 /* For the GCC-diagnostics custom format specifiers to work, one
3938 must have declared 'tree' and 'location_t' prior to using those
3939 attributes. If we haven't seen these declarations then
3940 the specifiers requiring these types shouldn't be used.
3941 However we don't force a hard ICE because we may see only one
3942 or the other type. */
3943 if (tree loc = maybe_get_identifier ("location_t"))
3945 loc = identifier_global_value (loc);
3946 if (loc && TREE_CODE (loc) != TYPE_DECL)
3947 error ("%<location_t%> is not defined as a type");
3950 /* Initialize the global tree node type local to this file. */
3951 if (!local_tree_type_node
3952 || local_tree_type_node == void_type_node)
3954 /* We need to grab the underlying 'union tree_node' so peek into
3955 an extra type level. */
3956 if ((local_tree_type_node = maybe_get_identifier ("tree")))
3958 local_tree_type_node = identifier_global_value (local_tree_type_node);
3959 if (local_tree_type_node)
3961 if (TREE_CODE (local_tree_type_node) != TYPE_DECL)
3963 error ("%<tree%> is not defined as a type");
3964 local_tree_type_node = 0;
3966 else if (TREE_CODE (TREE_TYPE (local_tree_type_node))
3967 != POINTER_TYPE)
3969 error ("%<tree%> is not defined as a pointer type");
3970 local_tree_type_node = 0;
3972 else
3973 local_tree_type_node =
3974 TREE_TYPE (TREE_TYPE (local_tree_type_node));
3977 else
3978 local_tree_type_node = void_type_node;
3981 /* Similar to the above but for gimple*. */
3982 if (!local_gimple_ptr_node
3983 || local_gimple_ptr_node == void_type_node)
3984 local_gimple_ptr_node = get_pointer_to_named_type ("gimple");
3986 /* Similar to the above but for cgraph_node*. */
3987 if (!local_cgraph_node_ptr_node
3988 || local_cgraph_node_ptr_node == void_type_node)
3989 local_cgraph_node_ptr_node = get_pointer_to_named_type ("cgraph_node");
3991 static tree hwi;
3993 if (!hwi)
3995 static format_length_info *diag_ls;
3996 unsigned int i;
3998 /* Find the underlying type for HOST_WIDE_INT. For the 'w'
3999 length modifier to work, one must have issued: "typedef
4000 HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code
4001 prior to using that modifier. */
4002 if ((hwi = maybe_get_identifier ("__gcc_host_wide_int__")))
4004 hwi = identifier_global_value (hwi);
4005 if (hwi)
4007 if (TREE_CODE (hwi) != TYPE_DECL)
4009 error ("%<__gcc_host_wide_int__%> is not defined as a type");
4010 hwi = 0;
4012 else
4014 hwi = DECL_ORIGINAL_TYPE (hwi);
4015 gcc_assert (hwi);
4016 if (hwi != long_integer_type_node
4017 && hwi != long_long_integer_type_node)
4019 error ("%<__gcc_host_wide_int__%> is not defined"
4020 " as %<long%> or %<long long%>");
4021 hwi = 0;
4027 /* Assign the new data for use. */
4029 /* All the GCC diag formats use the same length specs. */
4030 if (!diag_ls)
4031 dynamic_format_types[gcc_diag_format_type].length_char_specs =
4032 dynamic_format_types[gcc_tdiag_format_type].length_char_specs =
4033 dynamic_format_types[gcc_cdiag_format_type].length_char_specs =
4034 dynamic_format_types[gcc_cxxdiag_format_type].length_char_specs =
4035 dynamic_format_types[gcc_dump_printf_format_type].length_char_specs =
4036 diag_ls = (format_length_info *)
4037 xmemdup (gcc_diag_length_specs,
4038 sizeof (gcc_diag_length_specs),
4039 sizeof (gcc_diag_length_specs));
4040 if (hwi)
4042 /* HOST_WIDE_INT must be one of 'long' or 'long long'. */
4043 i = find_length_info_modifier_index (diag_ls, 'w');
4044 if (hwi == long_integer_type_node)
4045 diag_ls[i].index = FMT_LEN_l;
4046 else if (hwi == long_long_integer_type_node)
4047 diag_ls[i].index = FMT_LEN_ll;
4048 else
4049 gcc_unreachable ();
4053 /* It's safe to "re-initialize these to the same values. */
4054 dynamic_format_types[gcc_diag_format_type].conversion_specs =
4055 gcc_diag_char_table;
4056 dynamic_format_types[gcc_tdiag_format_type].conversion_specs =
4057 gcc_tdiag_char_table;
4058 dynamic_format_types[gcc_cdiag_format_type].conversion_specs =
4059 gcc_cdiag_char_table;
4060 dynamic_format_types[gcc_cxxdiag_format_type].conversion_specs =
4061 gcc_cxxdiag_char_table;
4062 dynamic_format_types[gcc_dump_printf_format_type].conversion_specs =
4063 gcc_dump_printf_char_table;
4066 #ifdef TARGET_FORMAT_TYPES
4067 extern const format_kind_info TARGET_FORMAT_TYPES[];
4068 #endif
4070 #ifdef TARGET_OVERRIDES_FORMAT_ATTRIBUTES
4071 extern const target_ovr_attr TARGET_OVERRIDES_FORMAT_ATTRIBUTES[];
4072 #endif
4073 #ifdef TARGET_OVERRIDES_FORMAT_INIT
4074 extern void TARGET_OVERRIDES_FORMAT_INIT (void);
4075 #endif
4077 /* Attributes such as "printf" are equivalent to those such as
4078 "gnu_printf" unless this is overridden by a target. */
4079 static const target_ovr_attr gnu_target_overrides_format_attributes[] =
4081 { "gnu_printf", "printf" },
4082 { "gnu_scanf", "scanf" },
4083 { "gnu_strftime", "strftime" },
4084 { "gnu_strfmon", "strfmon" },
4085 { NULL, NULL }
4088 /* Translate to unified attribute name. This is used in decode_format_type and
4089 decode_format_attr. In attr_name the user specified argument is passed. It
4090 returns the unified format name from TARGET_OVERRIDES_FORMAT_ATTRIBUTES
4091 or the attr_name passed to this function, if there is no matching entry. */
4092 static const char *
4093 convert_format_name_to_system_name (const char *attr_name)
4095 int i;
4097 if (attr_name == NULL || *attr_name == 0
4098 || strncmp (attr_name, "gcc_", 4) == 0)
4099 return attr_name;
4100 #ifdef TARGET_OVERRIDES_FORMAT_INIT
4101 TARGET_OVERRIDES_FORMAT_INIT ();
4102 #endif
4104 #ifdef TARGET_OVERRIDES_FORMAT_ATTRIBUTES
4105 /* Check if format attribute is overridden by target. */
4106 if (TARGET_OVERRIDES_FORMAT_ATTRIBUTES != NULL
4107 && TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT > 0)
4109 for (i = 0; i < TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT; ++i)
4111 if (cmp_attribs (TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_src,
4112 attr_name))
4113 return attr_name;
4114 if (cmp_attribs (TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_dst,
4115 attr_name))
4116 return TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_src;
4119 #endif
4120 /* Otherwise default to gnu format. */
4121 for (i = 0;
4122 gnu_target_overrides_format_attributes[i].named_attr_src != NULL;
4123 ++i)
4125 if (cmp_attribs (gnu_target_overrides_format_attributes[i].named_attr_src,
4126 attr_name))
4127 return attr_name;
4128 if (cmp_attribs (gnu_target_overrides_format_attributes[i].named_attr_dst,
4129 attr_name))
4130 return gnu_target_overrides_format_attributes[i].named_attr_src;
4133 return attr_name;
4136 /* Handle a "format" attribute; arguments as in
4137 struct attribute_spec.handler. */
4138 tree
4139 handle_format_attribute (tree *node, tree atname, tree args,
4140 int flags, bool *no_add_attrs)
4142 const_tree type = *node;
4143 function_format_info info;
4145 #ifdef TARGET_FORMAT_TYPES
4146 /* If the target provides additional format types, we need to
4147 add them to FORMAT_TYPES at first use. */
4148 if (TARGET_FORMAT_TYPES != NULL && !dynamic_format_types)
4150 dynamic_format_types = XNEWVEC (format_kind_info,
4151 n_format_types + TARGET_N_FORMAT_TYPES);
4152 memcpy (dynamic_format_types, format_types_orig,
4153 sizeof (format_types_orig));
4154 memcpy (&dynamic_format_types[n_format_types], TARGET_FORMAT_TYPES,
4155 TARGET_N_FORMAT_TYPES * sizeof (dynamic_format_types[0]));
4157 format_types = dynamic_format_types;
4158 /* Provide a reference for the first potential external type. */
4159 first_target_format_type = n_format_types;
4160 n_format_types += TARGET_N_FORMAT_TYPES;
4162 #endif
4164 /* Canonicalize name of format function. */
4165 if (TREE_CODE (TREE_VALUE (args)) == IDENTIFIER_NODE)
4166 TREE_VALUE (args) = canonicalize_attr_name (TREE_VALUE (args));
4168 if (!decode_format_attr (type, atname, args, &info, /* validated_p = */false))
4170 *no_add_attrs = true;
4171 return NULL_TREE;
4174 if (prototype_p (type))
4176 if (!check_format_string (type, info.format_num, flags,
4177 no_add_attrs, info.format_type))
4178 return NULL_TREE;
4180 if (info.first_arg_num != 0)
4182 unsigned HOST_WIDE_INT arg_num = 1;
4183 function_args_iterator iter;
4184 tree arg_type;
4186 /* Verify that first_arg_num points to the last arg,
4187 the ... */
4188 FOREACH_FUNCTION_ARGS (type, arg_type, iter)
4189 arg_num++;
4191 if (arg_num != info.first_arg_num)
4193 if (!(flags & (int) ATTR_FLAG_BUILT_IN))
4194 error ("args to be formatted is not %<...%>");
4195 *no_add_attrs = true;
4196 return NULL_TREE;
4201 /* Check if this is a strftime variant. Just for this variant
4202 FMT_FLAG_ARG_CONVERT is not set. */
4203 if ((format_types[info.format_type].flags & (int) FMT_FLAG_ARG_CONVERT) == 0
4204 && info.first_arg_num != 0)
4206 error ("strftime formats cannot format arguments");
4207 *no_add_attrs = true;
4208 return NULL_TREE;
4211 /* If this is a custom GCC-internal format type, we have to
4212 initialize certain bits at runtime. */
4213 if (info.format_type == asm_fprintf_format_type
4214 || info.format_type == gcc_gfc_format_type
4215 || info.format_type == gcc_diag_format_type
4216 || info.format_type == gcc_tdiag_format_type
4217 || info.format_type == gcc_cdiag_format_type
4218 || info.format_type == gcc_cxxdiag_format_type
4219 || info.format_type == gcc_dump_printf_format_type)
4221 /* Our first time through, we have to make sure that our
4222 format_type data is allocated dynamically and is modifiable. */
4223 if (!dynamic_format_types)
4224 format_types = dynamic_format_types = (format_kind_info *)
4225 xmemdup (format_types_orig, sizeof (format_types_orig),
4226 sizeof (format_types_orig));
4228 /* If this is format __asm_fprintf__, we have to initialize
4229 GCC's notion of HOST_WIDE_INT for checking %wd. */
4230 if (info.format_type == asm_fprintf_format_type)
4231 init_dynamic_asm_fprintf_info ();
4232 /* If this is format __gcc_gfc__, we have to initialize GCC's
4233 notion of 'locus' at runtime for %L. */
4234 else if (info.format_type == gcc_gfc_format_type)
4235 init_dynamic_gfc_info ();
4236 /* If this is one of the diagnostic attributes, then we have to
4237 initialize 'location_t' and 'tree' at runtime. */
4238 else if (info.format_type == gcc_diag_format_type
4239 || info.format_type == gcc_tdiag_format_type
4240 || info.format_type == gcc_cdiag_format_type
4241 || info.format_type == gcc_cxxdiag_format_type
4242 || info.format_type == gcc_dump_printf_format_type)
4243 init_dynamic_diag_info ();
4244 else
4245 gcc_unreachable ();
4248 return NULL_TREE;
4251 #if CHECKING_P
4253 namespace selftest {
4255 /* Selftests of location handling. */
4257 /* Get the format_kind_info with the given name. */
4259 static const format_kind_info *
4260 get_info (const char *name)
4262 int idx = decode_format_type (name);
4263 const format_kind_info *fki = &format_types[idx];
4264 ASSERT_STREQ (fki->name, name);
4265 return fki;
4268 /* Verify that get_format_for_type (FKI, TYPE, CONVERSION_CHAR)
4269 is EXPECTED_FORMAT. */
4271 static void
4272 assert_format_for_type_streq (const location &loc, const format_kind_info *fki,
4273 const char *expected_format, tree type,
4274 char conversion_char)
4276 gcc_assert (fki);
4277 gcc_assert (expected_format);
4278 gcc_assert (type);
4280 char *actual_format = get_format_for_type (fki, type, conversion_char);
4281 ASSERT_STREQ_AT (loc, expected_format, actual_format);
4282 free (actual_format);
4285 /* Selftests for get_format_for_type. */
4287 #define ASSERT_FORMAT_FOR_TYPE_STREQ(EXPECTED_FORMAT, TYPE, CONVERSION_CHAR) \
4288 assert_format_for_type_streq (SELFTEST_LOCATION, (fki), (EXPECTED_FORMAT), \
4289 (TYPE), (CONVERSION_CHAR))
4291 /* Selftest for get_format_for_type for "printf"-style functions. */
4293 static void
4294 test_get_format_for_type_printf ()
4296 const format_kind_info *fki = get_info ("gnu_printf");
4297 ASSERT_NE (fki, NULL);
4299 ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node, 'i');
4300 ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node, 'i');
4301 ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node, 'o');
4302 ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node, 'o');
4303 ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node, 'x');
4304 ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node, 'x');
4305 ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node, 'X');
4306 ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node, 'X');
4307 ASSERT_FORMAT_FOR_TYPE_STREQ ("d", integer_type_node, 'd');
4308 ASSERT_FORMAT_FOR_TYPE_STREQ ("i", integer_type_node, 'i');
4309 ASSERT_FORMAT_FOR_TYPE_STREQ ("o", integer_type_node, 'o');
4310 ASSERT_FORMAT_FOR_TYPE_STREQ ("x", integer_type_node, 'x');
4311 ASSERT_FORMAT_FOR_TYPE_STREQ ("X", integer_type_node, 'X');
4312 ASSERT_FORMAT_FOR_TYPE_STREQ ("d", unsigned_type_node, 'd');
4313 ASSERT_FORMAT_FOR_TYPE_STREQ ("i", unsigned_type_node, 'i');
4314 ASSERT_FORMAT_FOR_TYPE_STREQ ("o", unsigned_type_node, 'o');
4315 ASSERT_FORMAT_FOR_TYPE_STREQ ("x", unsigned_type_node, 'x');
4316 ASSERT_FORMAT_FOR_TYPE_STREQ ("X", unsigned_type_node, 'X');
4317 ASSERT_FORMAT_FOR_TYPE_STREQ ("ld", long_integer_type_node, 'd');
4318 ASSERT_FORMAT_FOR_TYPE_STREQ ("li", long_integer_type_node, 'i');
4319 ASSERT_FORMAT_FOR_TYPE_STREQ ("lx", long_integer_type_node, 'x');
4320 ASSERT_FORMAT_FOR_TYPE_STREQ ("lo", long_unsigned_type_node, 'o');
4321 ASSERT_FORMAT_FOR_TYPE_STREQ ("lx", long_unsigned_type_node, 'x');
4322 ASSERT_FORMAT_FOR_TYPE_STREQ ("lld", long_long_integer_type_node, 'd');
4323 ASSERT_FORMAT_FOR_TYPE_STREQ ("lli", long_long_integer_type_node, 'i');
4324 ASSERT_FORMAT_FOR_TYPE_STREQ ("llo", long_long_unsigned_type_node, 'o');
4325 ASSERT_FORMAT_FOR_TYPE_STREQ ("llx", long_long_unsigned_type_node, 'x');
4326 ASSERT_FORMAT_FOR_TYPE_STREQ ("s", build_pointer_type (char_type_node), 'i');
4329 /* Selftest for get_format_for_type for "scanf"-style functions. */
4331 static void
4332 test_get_format_for_type_scanf ()
4334 const format_kind_info *fki = get_info ("gnu_scanf");
4335 ASSERT_NE (fki, NULL);
4336 ASSERT_FORMAT_FOR_TYPE_STREQ ("d", build_pointer_type (integer_type_node), 'd');
4337 ASSERT_FORMAT_FOR_TYPE_STREQ ("u", build_pointer_type (unsigned_type_node), 'u');
4338 ASSERT_FORMAT_FOR_TYPE_STREQ ("ld",
4339 build_pointer_type (long_integer_type_node), 'd');
4340 ASSERT_FORMAT_FOR_TYPE_STREQ ("lu",
4341 build_pointer_type (long_unsigned_type_node), 'u');
4342 ASSERT_FORMAT_FOR_TYPE_STREQ
4343 ("lld", build_pointer_type (long_long_integer_type_node), 'd');
4344 ASSERT_FORMAT_FOR_TYPE_STREQ
4345 ("llu", build_pointer_type (long_long_unsigned_type_node), 'u');
4346 ASSERT_FORMAT_FOR_TYPE_STREQ ("e", build_pointer_type (float_type_node), 'e');
4347 ASSERT_FORMAT_FOR_TYPE_STREQ ("le", build_pointer_type (double_type_node), 'e');
4350 #undef ASSERT_FORMAT_FOR_TYPE_STREQ
4352 /* Exercise the type-printing label code, to give some coverage
4353 under "make selftest-valgrind" (in particular, to ensure that
4354 the label-printing machinery doesn't leak). */
4356 static void
4357 test_type_mismatch_range_labels ()
4359 /* Create a tempfile and write some text to it.
4360 ....................0000000001 11111111 12 22222222
4361 ....................1234567890 12345678 90 12345678. */
4362 const char *content = " printf (\"msg: %i\\n\", msg);\n";
4363 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
4364 line_table_test ltt;
4366 linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
4368 location_t c17 = linemap_position_for_column (line_table, 17);
4369 ASSERT_EQ (LOCATION_COLUMN (c17), 17);
4370 location_t c18 = linemap_position_for_column (line_table, 18);
4371 location_t c24 = linemap_position_for_column (line_table, 24);
4372 location_t c26 = linemap_position_for_column (line_table, 26);
4374 /* Don't attempt to run the tests if column data might be unavailable. */
4375 if (c26 > LINE_MAP_MAX_LOCATION_WITH_COLS)
4376 return;
4378 location_t fmt = make_location (c18, c17, c18);
4379 ASSERT_EQ (LOCATION_COLUMN (fmt), 18);
4381 location_t param = make_location (c24, c24, c26);
4382 ASSERT_EQ (LOCATION_COLUMN (param), 24);
4384 range_label_for_format_type_mismatch fmt_label (char_type_node,
4385 integer_type_node, 1);
4386 range_label_for_type_mismatch param_label (integer_type_node,
4387 char_type_node);
4388 gcc_rich_location richloc (fmt, &fmt_label);
4389 richloc.add_range (param, SHOW_RANGE_WITHOUT_CARET, &param_label);
4391 test_diagnostic_context dc;
4392 diagnostic_show_locus (&dc, &richloc, DK_ERROR);
4393 if (c_dialect_cxx ())
4394 /* "char*", without a space. */
4395 ASSERT_STREQ ("\n"
4396 " printf (\"msg: %i\\n\", msg);\n"
4397 " ~^ ~~~\n"
4398 " | |\n"
4399 " char* int\n",
4400 pp_formatted_text (dc.printer));
4401 else
4402 /* "char *", with a space. */
4403 ASSERT_STREQ ("\n"
4404 " printf (\"msg: %i\\n\", msg);\n"
4405 " ~^ ~~~\n"
4406 " | |\n"
4407 " | int\n"
4408 " char *\n",
4409 pp_formatted_text (dc.printer));
4412 /* Run all of the selftests within this file. */
4414 void
4415 c_format_c_tests ()
4417 test_get_modifier_for_format_len ();
4418 test_get_format_for_type_printf ();
4419 test_get_format_for_type_scanf ();
4420 test_type_mismatch_range_labels ();
4423 } // namespace selftest
4425 #endif /* CHECKING_P */
4427 #include "gt-c-family-c-format.h"