]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/c-family/c-format.c
PR c++/61339 - add mismatch between struct and class [-Wmismatched-tags] to non-bugs
[thirdparty/gcc.git] / gcc / c-family / c-format.c
1 /* Check calls to formatted I/O functions (-Wformat).
2 Copyright (C) 1992-2019 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
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.
10
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.
15
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/>. */
19
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"
39
40 /* Handle attributes associated with format checking. */
41
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};
52
53 struct function_format_info
54 {
55 enum format_type format_type; /* type of format (printf, scanf, etc.) */
56 /* IS_RAW is relevant only for GCC diagnostic format functions.
57 It is set for "raw" formatting functions like pp_printf that
58 are not intended to produce complete diagnostics according to
59 GCC guidelines, and clear for others like error and warning
60 whose format string is checked for proper quoting and spelling. */
61 bool is_raw;
62 unsigned HOST_WIDE_INT format_num; /* number of format argument */
63 unsigned HOST_WIDE_INT first_arg_num; /* number of first arg (zero for varargs) */
64 };
65
66 /* Initialized in init_dynamic_diag_info. */
67 static GTY(()) tree local_tree_type_node;
68 static GTY(()) tree local_gimple_ptr_node;
69 static GTY(()) tree local_cgraph_node_ptr_node;
70 static GTY(()) tree locus;
71
72 static bool decode_format_attr (const_tree, tree, tree, function_format_info *,
73 bool);
74 static format_type decode_format_type (const char *, bool * = NULL);
75
76 static bool check_format_string (const_tree argument,
77 unsigned HOST_WIDE_INT format_num,
78 int flags, bool *no_add_attrs,
79 int expected_format_type);
80 static tree get_constant (const_tree fntype, const_tree atname, tree expr,
81 int argno, unsigned HOST_WIDE_INT *value,
82 int flags, bool validated_p);
83 static const char *convert_format_name_to_system_name (const char *attr_name);
84
85 static int first_target_format_type;
86 static const char *format_name (int format_num);
87 static int format_flags (int format_num);
88
89 /* Emit a warning as per format_warning_va, but construct the substring_loc
90 for the character at offset (CHAR_IDX - 1) within a string constant
91 FORMAT_STRING_CST at FMT_STRING_LOC. */
92
93 ATTRIBUTE_GCC_DIAG (5,6)
94 static bool
95 format_warning_at_char (location_t fmt_string_loc, tree format_string_cst,
96 int char_idx, int opt, const char *gmsgid, ...)
97 {
98 va_list ap;
99 va_start (ap, gmsgid);
100 tree string_type = TREE_TYPE (format_string_cst);
101
102 /* The callers are of the form:
103 format_warning (format_string_loc, format_string_cst,
104 format_chars - orig_format_chars,
105 where format_chars has already been incremented, so that
106 CHAR_IDX is one character beyond where the warning should
107 be emitted. Fix it. */
108 char_idx -= 1;
109
110 substring_loc fmt_loc (fmt_string_loc, string_type, char_idx, char_idx,
111 char_idx);
112 format_string_diagnostic_t diag (fmt_loc, NULL, UNKNOWN_LOCATION, NULL,
113 NULL);
114 bool warned = diag.emit_warning_va (opt, gmsgid, &ap);
115 va_end (ap);
116
117 return warned;
118 }
119
120
121 /* Emit a warning as per format_warning_va, but construct the substring_loc
122 for the substring at offset (POS1, POS2 - 1) within a string constant
123 FORMAT_STRING_CST at FMT_STRING_LOC. */
124
125 ATTRIBUTE_GCC_DIAG (6,7)
126 static bool
127 format_warning_substr (location_t fmt_string_loc, tree format_string_cst,
128 int pos1, int pos2, int opt, const char *gmsgid, ...)
129 {
130 va_list ap;
131 va_start (ap, gmsgid);
132 tree string_type = TREE_TYPE (format_string_cst);
133
134 pos2 -= 1;
135
136 substring_loc fmt_loc (fmt_string_loc, string_type, pos1, pos1, pos2);
137 format_string_diagnostic_t diag (fmt_loc, NULL, UNKNOWN_LOCATION, NULL,
138 NULL);
139 bool warned = diag.emit_warning_va (opt, gmsgid, &ap);
140 va_end (ap);
141
142 return warned;
143 }
144
145
146 /* Check that we have a pointer to a string suitable for use as a format.
147 The default is to check for a char type.
148 For objective-c dialects, this is extended to include references to string
149 objects validated by objc_string_ref_type_p ().
150 Targets may also provide a string object type that can be used within c and
151 c++ and shared with their respective objective-c dialects. In this case the
152 reference to a format string is checked for validity via a hook.
153
154 The function returns true if strref points to any string type valid for the
155 language dialect and target. */
156
157 bool
158 valid_format_string_type_p (tree strref)
159 {
160 return (strref != NULL
161 && TREE_CODE (strref) == POINTER_TYPE
162 && (TYPE_MAIN_VARIANT (TREE_TYPE (strref)) == char_type_node
163 || objc_string_ref_type_p (strref)
164 || (*targetcm.string_object_ref_type_p) ((const_tree) strref)));
165 }
166
167 /* Handle a "format_arg" attribute; arguments as in
168 struct attribute_spec.handler. */
169 tree
170 handle_format_arg_attribute (tree *node, tree atname,
171 tree args, int flags, bool *no_add_attrs)
172 {
173 tree type = *node;
174 /* Note that TREE_VALUE (args) is changed in place below. */
175 tree *format_num_expr = &TREE_VALUE (args);
176 unsigned HOST_WIDE_INT format_num = 0;
177
178 if (tree val = get_constant (type, atname, *format_num_expr, 0, &format_num,
179 0, false))
180 *format_num_expr = val;
181 else
182 {
183 *no_add_attrs = true;
184 return NULL_TREE;
185 }
186
187 if (prototype_p (type))
188 {
189 /* The format arg can be any string reference valid for the language and
190 target. We cannot be more specific in this case. */
191 if (!check_format_string (type, format_num, flags, no_add_attrs, -1))
192 return NULL_TREE;
193 }
194
195 if (!valid_format_string_type_p (TREE_TYPE (type)))
196 {
197 if (!(flags & (int) ATTR_FLAG_BUILT_IN))
198 error ("function does not return string type");
199 *no_add_attrs = true;
200 return NULL_TREE;
201 }
202
203 return NULL_TREE;
204 }
205
206 /* Verify that the format_num argument is actually a string reference suitable,
207 for the language dialect and target (in case the format attribute is in
208 error). When we know the specific reference type expected, this is also
209 checked. */
210 static bool
211 check_format_string (const_tree fntype, unsigned HOST_WIDE_INT format_num,
212 int flags, bool *no_add_attrs, int expected_format_type)
213 {
214 unsigned HOST_WIDE_INT i;
215 bool is_objc_sref, is_target_sref, is_char_ref;
216 tree ref;
217 int fmt_flags;
218 function_args_iterator iter;
219
220 i = 1;
221 FOREACH_FUNCTION_ARGS (fntype, ref, iter)
222 {
223 if (i == format_num)
224 break;
225 i++;
226 }
227
228 if (!ref
229 || !valid_format_string_type_p (ref))
230 {
231 if (!(flags & (int) ATTR_FLAG_BUILT_IN))
232 error ("format string argument is not a string type");
233 *no_add_attrs = true;
234 return false;
235 }
236
237 /* We only know that we want a suitable string reference. */
238 if (expected_format_type < 0)
239 return true;
240
241 /* Now check that the arg matches the expected type. */
242 is_char_ref =
243 (TYPE_MAIN_VARIANT (TREE_TYPE (ref)) == char_type_node);
244
245 fmt_flags = format_flags (expected_format_type);
246 is_objc_sref = is_target_sref = false;
247 if (!is_char_ref)
248 is_objc_sref = objc_string_ref_type_p (ref);
249
250 if (!(fmt_flags & FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL))
251 {
252 if (is_char_ref)
253 return true; /* OK, we expected a char and found one. */
254 else
255 {
256 /* We expected a char but found an extended string type. */
257 if (is_objc_sref)
258 error ("found a %qs reference but the format argument should"
259 " be a string", format_name (gcc_objc_string_format_type));
260 else
261 error ("found a %qT but the format argument should be a string",
262 ref);
263 *no_add_attrs = true;
264 return false;
265 }
266 }
267
268 /* We expect a string object type as the format arg. */
269 if (is_char_ref)
270 {
271 error ("format argument should be a %qs reference but"
272 " a string was found", format_name (expected_format_type));
273 *no_add_attrs = true;
274 return false;
275 }
276
277 /* We will assert that objective-c will support either its own string type
278 or the target-supplied variant. */
279 if (!is_objc_sref)
280 is_target_sref = (*targetcm.string_object_ref_type_p) ((const_tree) ref);
281
282 if (expected_format_type == (int) gcc_objc_string_format_type
283 && (is_objc_sref || is_target_sref))
284 return true;
285
286 /* We will allow a target string ref to match only itself. */
287 if (first_target_format_type
288 && expected_format_type >= first_target_format_type
289 && is_target_sref)
290 return true;
291 else
292 {
293 error ("format argument should be a %qs reference",
294 format_name (expected_format_type));
295 *no_add_attrs = true;
296 return false;
297 }
298
299 gcc_unreachable ();
300 }
301
302 /* Under the control of FLAGS, verify EXPR is a valid constant that
303 refers to a positional argument ARGNO having a string type (char*
304 or, for targets like Darwin, a pointer to struct CFString) to
305 a function type FNTYPE declared with attribute ATNAME.
306 If valid, store the constant's integer value in *VALUE and return
307 the value.
308 If VALIDATED_P is true assert the validation is successful.
309 Returns the converted constant value on success, null otherwise. */
310
311 static tree
312 get_constant (const_tree fntype, const_tree atname, tree expr, int argno,
313 unsigned HOST_WIDE_INT *value, int flags, bool validated_p)
314 {
315 /* Require the referenced argument to have a string type. For targets
316 like Darwin, also accept pointers to struct CFString. */
317 if (tree val = positional_argument (fntype, atname, expr, STRING_CST,
318 argno, flags))
319 {
320 *value = TREE_INT_CST_LOW (val);
321 return val;
322 }
323
324 gcc_assert (!validated_p);
325 return NULL_TREE;
326 }
327
328 /* Decode the arguments to a "format" attribute into a
329 function_format_info structure. It is already known that the list
330 is of the right length. If VALIDATED_P is true, then these
331 attributes have already been validated and must not be erroneous;
332 if false, it will give an error message. Returns true if the
333 attributes are successfully decoded, false otherwise. */
334
335 static bool
336 decode_format_attr (const_tree fntype, tree atname, tree args,
337 function_format_info *info, bool validated_p)
338 {
339 tree format_type_id = TREE_VALUE (args);
340 /* Note that TREE_VALUE (args) is changed in place below. Ditto
341 for the value of the next element on the list. */
342 tree *format_num_expr = &TREE_VALUE (TREE_CHAIN (args));
343 tree *first_arg_num_expr = &TREE_VALUE (TREE_CHAIN (TREE_CHAIN (args)));
344
345 if (TREE_CODE (format_type_id) != IDENTIFIER_NODE)
346 {
347 gcc_assert (!validated_p);
348 error ("unrecognized format specifier");
349 return false;
350 }
351 else
352 {
353 const char *p = IDENTIFIER_POINTER (format_type_id);
354
355 info->format_type = decode_format_type (p, &info->is_raw);
356
357 if (!c_dialect_objc ()
358 && info->format_type == gcc_objc_string_format_type)
359 {
360 gcc_assert (!validated_p);
361 warning (OPT_Wformat_, "%qE is only allowed in Objective-C dialects",
362 format_type_id);
363 info->format_type = format_type_error;
364 return false;
365 }
366
367 if (info->format_type == format_type_error)
368 {
369 gcc_assert (!validated_p);
370 warning (OPT_Wformat_, "%qE is an unrecognized format function type",
371 format_type_id);
372 return false;
373 }
374 }
375
376 if (tree val = get_constant (fntype, atname, *format_num_expr,
377 2, &info->format_num, 0, validated_p))
378 *format_num_expr = val;
379 else
380 return false;
381
382 if (tree val = get_constant (fntype, atname, *first_arg_num_expr,
383 3, &info->first_arg_num,
384 (POSARG_ZERO | POSARG_ELLIPSIS), validated_p))
385 *first_arg_num_expr = val;
386 else
387 return false;
388
389 if (info->first_arg_num != 0 && info->first_arg_num <= info->format_num)
390 {
391 gcc_assert (!validated_p);
392 error ("format string argument follows the arguments to be formatted");
393 return false;
394 }
395
396 return true;
397 }
398 \f
399 /* Check a call to a format function against a parameter list. */
400
401 /* The C standard version C++ is treated as equivalent to
402 or inheriting from, for the purpose of format features supported. */
403 #define CPLUSPLUS_STD_VER (cxx_dialect < cxx11 ? STD_C94 : STD_C99)
404 /* The C standard version we are checking formats against when pedantic. */
405 #define C_STD_VER ((int) (c_dialect_cxx () \
406 ? CPLUSPLUS_STD_VER \
407 : (flag_isoc99 \
408 ? STD_C99 \
409 : (flag_isoc94 ? STD_C94 : STD_C89))))
410 /* The name to give to the standard version we are warning about when
411 pedantic. FEATURE_VER is the version in which the feature warned out
412 appeared, which is higher than C_STD_VER. */
413 #define C_STD_NAME(FEATURE_VER) (c_dialect_cxx () \
414 ? (cxx_dialect < cxx11 ? "ISO C++98" \
415 : "ISO C++11") \
416 : ((FEATURE_VER) == STD_EXT \
417 ? "ISO C" \
418 : "ISO C90"))
419 /* Adjust a C standard version, which may be STD_C9L, to account for
420 -Wno-long-long. Returns other standard versions unchanged. */
421 #define ADJ_STD(VER) ((int) ((VER) == STD_C9L \
422 ? (warn_long_long ? STD_C99 : STD_C89) \
423 : (VER)))
424
425 /* Enum describing the kind of specifiers present in the format and
426 requiring an argument. */
427 enum format_specifier_kind {
428 CF_KIND_FORMAT,
429 CF_KIND_FIELD_WIDTH,
430 CF_KIND_FIELD_PRECISION
431 };
432
433 static const char *kind_descriptions[] = {
434 N_("format"),
435 N_("field width specifier"),
436 N_("field precision specifier")
437 };
438
439 /* Structure describing details of a type expected in format checking,
440 and the type to check against it. */
441 struct format_wanted_type
442 {
443 /* The type wanted. */
444 tree wanted_type;
445 /* The name of this type to use in diagnostics. */
446 const char *wanted_type_name;
447 /* Should be type checked just for scalar width identity. */
448 int scalar_identity_flag;
449 /* The level of indirection through pointers at which this type occurs. */
450 int pointer_count;
451 /* Whether, when pointer_count is 1, to allow any character type when
452 pedantic, rather than just the character or void type specified. */
453 int char_lenient_flag;
454 /* Whether the argument, dereferenced once, is written into and so the
455 argument must not be a pointer to a const-qualified type. */
456 int writing_in_flag;
457 /* Whether the argument, dereferenced once, is read from and so
458 must not be a NULL pointer. */
459 int reading_from_flag;
460 /* The kind of specifier that this type is used for. */
461 enum format_specifier_kind kind;
462 /* The starting character of the specifier. This never includes the
463 initial percent sign. */
464 const char *format_start;
465 /* The length of the specifier. */
466 int format_length;
467 /* The actual parameter to check against the wanted type. */
468 tree param;
469 /* The argument number of that parameter. */
470 int arg_num;
471 /* The offset location of this argument with respect to the format
472 string location. */
473 unsigned int offset_loc;
474 /* The next type to check for this format conversion, or NULL if none. */
475 struct format_wanted_type *next;
476 };
477
478 /* Convenience macro for format_length_info meaning unused. */
479 #define NO_FMT NULL, FMT_LEN_none, STD_C89
480
481 static const format_length_info printf_length_specs[] =
482 {
483 { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99, 0 },
484 { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L, 0 },
485 { "q", FMT_LEN_ll, STD_EXT, NO_FMT, 0 },
486 { "L", FMT_LEN_L, STD_C89, NO_FMT, 0 },
487 { "z", FMT_LEN_z, STD_C99, NO_FMT, 0 },
488 { "Z", FMT_LEN_z, STD_EXT, NO_FMT, 0 },
489 { "t", FMT_LEN_t, STD_C99, NO_FMT, 0 },
490 { "j", FMT_LEN_j, STD_C99, NO_FMT, 0 },
491 { "H", FMT_LEN_H, STD_EXT, NO_FMT, 0 },
492 { "D", FMT_LEN_D, STD_EXT, "DD", FMT_LEN_DD, STD_EXT, 0 },
493 { NO_FMT, NO_FMT, 0 }
494 };
495
496 /* Length specifiers valid for asm_fprintf. */
497 static const format_length_info asm_fprintf_length_specs[] =
498 {
499 { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89, 0 },
500 { "w", FMT_LEN_none, STD_C89, NO_FMT, 0 },
501 { NO_FMT, NO_FMT, 0 }
502 };
503
504 /* Length specifiers valid for GCC diagnostics. */
505 static const format_length_info gcc_diag_length_specs[] =
506 {
507 { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89, 0 },
508 { "w", FMT_LEN_none, STD_C89, NO_FMT, 0 },
509 { NO_FMT, NO_FMT, 0 }
510 };
511
512 /* The custom diagnostics all accept the same length specifiers. */
513 #define gcc_tdiag_length_specs gcc_diag_length_specs
514 #define gcc_cdiag_length_specs gcc_diag_length_specs
515 #define gcc_cxxdiag_length_specs gcc_diag_length_specs
516 #define gcc_dump_printf_length_specs gcc_diag_length_specs
517
518 /* This differs from printf_length_specs only in that "Z" is not accepted. */
519 static const format_length_info scanf_length_specs[] =
520 {
521 { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99, 0 },
522 { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C9L, 0 },
523 { "q", FMT_LEN_ll, STD_EXT, NO_FMT, 0 },
524 { "L", FMT_LEN_L, STD_C89, NO_FMT, 0 },
525 { "z", FMT_LEN_z, STD_C99, NO_FMT, 0 },
526 { "t", FMT_LEN_t, STD_C99, NO_FMT, 0 },
527 { "j", FMT_LEN_j, STD_C99, NO_FMT, 0 },
528 { "H", FMT_LEN_H, STD_EXT, NO_FMT, 0 },
529 { "D", FMT_LEN_D, STD_EXT, "DD", FMT_LEN_DD, STD_EXT, 0 },
530 { NO_FMT, NO_FMT, 0 }
531 };
532
533
534 /* All tables for strfmon use STD_C89 everywhere, since -pedantic warnings
535 make no sense for a format type not part of any C standard version. */
536 static const format_length_info strfmon_length_specs[] =
537 {
538 /* A GNU extension. */
539 { "L", FMT_LEN_L, STD_C89, NO_FMT, 0 },
540 { NO_FMT, NO_FMT, 0 }
541 };
542
543
544 /* For now, the Fortran front-end routines only use l as length modifier. */
545 static const format_length_info gcc_gfc_length_specs[] =
546 {
547 { "l", FMT_LEN_l, STD_C89, NO_FMT, 0 },
548 { NO_FMT, NO_FMT, 0 }
549 };
550
551
552 static const format_flag_spec printf_flag_specs[] =
553 {
554 { ' ', 0, 0, 0, N_("' ' flag"), N_("the ' ' printf flag"), STD_C89 },
555 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89 },
556 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89 },
557 { '0', 0, 0, 0, N_("'0' flag"), N_("the '0' printf flag"), STD_C89 },
558 { '-', 0, 0, 0, N_("'-' flag"), N_("the '-' printf flag"), STD_C89 },
559 { '\'', 0, 0, 0, N_("''' flag"), N_("the ''' printf flag"), STD_EXT },
560 { 'I', 0, 0, 0, N_("'I' flag"), N_("the 'I' printf flag"), STD_EXT },
561 { 'w', 0, 0, 0, N_("field width"), N_("field width in printf format"), STD_C89 },
562 { 'p', 0, 0, 0, N_("precision"), N_("precision in printf format"), STD_C89 },
563 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
564 { 0, 0, 0, 0, NULL, NULL, STD_C89 }
565 };
566
567
568 static const format_flag_pair printf_flag_pairs[] =
569 {
570 { ' ', '+', 1, 0 },
571 { '0', '-', 1, 0 },
572 { '0', 'p', 1, 'i' },
573 { 0, 0, 0, 0 }
574 };
575
576 static const format_flag_spec asm_fprintf_flag_specs[] =
577 {
578 { ' ', 0, 0, 0, N_("' ' flag"), N_("the ' ' printf flag"), STD_C89 },
579 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89 },
580 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89 },
581 { '0', 0, 0, 0, N_("'0' flag"), N_("the '0' printf flag"), STD_C89 },
582 { '-', 0, 0, 0, N_("'-' flag"), N_("the '-' printf flag"), STD_C89 },
583 { 'w', 0, 0, 0, N_("field width"), N_("field width in printf format"), STD_C89 },
584 { 'p', 0, 0, 0, N_("precision"), N_("precision in printf format"), STD_C89 },
585 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
586 { 0, 0, 0, 0, NULL, NULL, STD_C89 }
587 };
588
589 static const format_flag_pair asm_fprintf_flag_pairs[] =
590 {
591 { ' ', '+', 1, 0 },
592 { '0', '-', 1, 0 },
593 { '0', 'p', 1, 'i' },
594 { 0, 0, 0, 0 }
595 };
596
597 static const format_flag_pair gcc_diag_flag_pairs[] =
598 {
599 { 0, 0, 0, 0 }
600 };
601
602 #define gcc_tdiag_flag_pairs gcc_diag_flag_pairs
603 #define gcc_cdiag_flag_pairs gcc_diag_flag_pairs
604 #define gcc_cxxdiag_flag_pairs gcc_diag_flag_pairs
605 #define gcc_gfc_flag_pairs gcc_diag_flag_pairs
606 #define gcc_dump_printf_flag_pairs gcc_diag_flag_pairs
607
608 static const format_flag_spec gcc_diag_flag_specs[] =
609 {
610 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89 },
611 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89 },
612 { 'q', 0, 0, 1, N_("'q' flag"), N_("the 'q' diagnostic flag"), STD_C89 },
613 { 'p', 0, 0, 0, N_("precision"), N_("precision in printf format"), STD_C89 },
614 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
615 { 0, 0, 0, 0, NULL, NULL, STD_C89 }
616 };
617
618 #define gcc_tdiag_flag_specs gcc_diag_flag_specs
619 #define gcc_cdiag_flag_specs gcc_diag_flag_specs
620 #define gcc_cxxdiag_flag_specs gcc_diag_flag_specs
621 #define gcc_gfc_flag_specs gcc_diag_flag_specs
622 #define gcc_dump_printf_flag_specs gcc_diag_flag_specs
623
624 static const format_flag_spec scanf_flag_specs[] =
625 {
626 { '*', 0, 0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89 },
627 { 'a', 0, 0, 0, N_("'a' flag"), N_("the 'a' scanf flag"), STD_EXT },
628 { 'm', 0, 0, 0, N_("'m' flag"), N_("the 'm' scanf flag"), STD_EXT },
629 { 'w', 0, 0, 0, N_("field width"), N_("field width in scanf format"), STD_C89 },
630 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in scanf format"), STD_C89 },
631 { '\'', 0, 0, 0, N_("''' flag"), N_("the ''' scanf flag"), STD_EXT },
632 { 'I', 0, 0, 0, N_("'I' flag"), N_("the 'I' scanf flag"), STD_EXT },
633 { 0, 0, 0, 0, NULL, NULL, STD_C89 }
634 };
635
636
637 static const format_flag_pair scanf_flag_pairs[] =
638 {
639 { '*', 'L', 0, 0 },
640 { 'a', 'm', 0, 0 },
641 { 0, 0, 0, 0 }
642 };
643
644
645 static const format_flag_spec strftime_flag_specs[] =
646 {
647 { '_', 0, 0, 0, N_("'_' flag"), N_("the '_' strftime flag"), STD_EXT },
648 { '-', 0, 0, 0, N_("'-' flag"), N_("the '-' strftime flag"), STD_EXT },
649 { '0', 0, 0, 0, N_("'0' flag"), N_("the '0' strftime flag"), STD_EXT },
650 { '^', 0, 0, 0, N_("'^' flag"), N_("the '^' strftime flag"), STD_EXT },
651 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' strftime flag"), STD_EXT },
652 { 'w', 0, 0, 0, N_("field width"), N_("field width in strftime format"), STD_EXT },
653 { 'E', 0, 0, 0, N_("'E' modifier"), N_("the 'E' strftime modifier"), STD_C99 },
654 { 'O', 0, 0, 0, N_("'O' modifier"), N_("the 'O' strftime modifier"), STD_C99 },
655 { 'O', 'o', 0, 0, NULL, N_("the 'O' modifier"), STD_EXT },
656 { 0, 0, 0, 0, NULL, NULL, STD_C89 }
657 };
658
659
660 static const format_flag_pair strftime_flag_pairs[] =
661 {
662 { 'E', 'O', 0, 0 },
663 { '_', '-', 0, 0 },
664 { '_', '0', 0, 0 },
665 { '-', '0', 0, 0 },
666 { '^', '#', 0, 0 },
667 { 0, 0, 0, 0 }
668 };
669
670
671 static const format_flag_spec strfmon_flag_specs[] =
672 {
673 { '=', 0, 1, 0, N_("fill character"), N_("fill character in strfmon format"), STD_C89 },
674 { '^', 0, 0, 0, N_("'^' flag"), N_("the '^' strfmon flag"), STD_C89 },
675 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' strfmon flag"), STD_C89 },
676 { '(', 0, 0, 0, N_("'(' flag"), N_("the '(' strfmon flag"), STD_C89 },
677 { '!', 0, 0, 0, N_("'!' flag"), N_("the '!' strfmon flag"), STD_C89 },
678 { '-', 0, 0, 0, N_("'-' flag"), N_("the '-' strfmon flag"), STD_C89 },
679 { 'w', 0, 0, 0, N_("field width"), N_("field width in strfmon format"), STD_C89 },
680 { '#', 0, 0, 0, N_("left precision"), N_("left precision in strfmon format"), STD_C89 },
681 { 'p', 0, 0, 0, N_("right precision"), N_("right precision in strfmon format"), STD_C89 },
682 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in strfmon format"), STD_C89 },
683 { 0, 0, 0, 0, NULL, NULL, STD_C89 }
684 };
685
686 static const format_flag_pair strfmon_flag_pairs[] =
687 {
688 { '+', '(', 0, 0 },
689 { 0, 0, 0, 0 }
690 };
691
692
693 static const format_char_info print_char_table[] =
694 {
695 /* C89 conversion specifiers. */
696 { "di", 0, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, TEX_LL, T99_SST, T99_PD, T99_IM, BADLEN, BADLEN, BADLEN }, "-wp0 +'I", "i", NULL },
697 { "oxX", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM, BADLEN, BADLEN, BADLEN }, "-wp0#", "i", NULL },
698 { "u", 0, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM, BADLEN, BADLEN, BADLEN }, "-wp0'I", "i", NULL },
699 { "fgG", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "-wp0 +#'I", "", NULL },
700 { "eE", 0, STD_C89, { T89_D, BADLEN, BADLEN, T99_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "-wp0 +#I", "", NULL },
701 { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, T94_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL },
702 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "cR", NULL },
703 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "c", NULL },
704 { "n", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, T99_PD, T99_IM, BADLEN, BADLEN, BADLEN }, "", "W", NULL },
705 /* C99 conversion specifiers. */
706 { "F", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "-wp0 +#'I", "", NULL },
707 { "aA", 0, STD_C99, { T99_D, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "-wp0 +#", "", NULL },
708 /* X/Open conversion specifiers. */
709 { "C", 0, STD_EXT, { TEX_WI, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL },
710 { "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "R", NULL },
711 /* GNU conversion specifiers. */
712 { "m", 0, STD_EXT, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "", NULL },
713 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
714 };
715
716 static const format_char_info asm_fprintf_char_table[] =
717 {
718 /* C89 conversion specifiers. */
719 { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0 +", "i", NULL },
720 { "oxX", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0#", "i", NULL },
721 { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp0", "i", NULL },
722 { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-w", "", NULL },
723 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "-wp", "cR", NULL },
724
725 /* asm_fprintf conversion specifiers. */
726 { "O", 0, STD_C89, NOARGUMENTS, "", "", NULL },
727 { "R", 0, STD_C89, NOARGUMENTS, "", "", NULL },
728 { "I", 0, STD_C89, NOARGUMENTS, "", "", NULL },
729 { "L", 0, STD_C89, NOARGUMENTS, "", "", NULL },
730 { "U", 0, STD_C89, NOARGUMENTS, "", "", NULL },
731 { "r", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", NULL },
732 { "z", 0, STD_C89, NOARGUMENTS, "", "", NULL },
733 { "@", 0, STD_C89, NOARGUMENTS, "", "", NULL },
734 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
735 };
736
737 /* GCC-specific format_char_info arrays. */
738
739 /* The conversion specifiers implemented within pp_format, and thus supported
740 by all pretty_printer instances within GCC. */
741
742 #define PP_FORMAT_CHAR_TABLE \
743 { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \
744 { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \
745 { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \
746 { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \
747 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL }, \
748 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, \
749 { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "//cR", NULL }, \
750 { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL }, \
751 { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL }, \
752 { "'" , 0, STD_C89, NOARGUMENTS, "", "", NULL }, \
753 { "R", 0, STD_C89, NOARGUMENTS, "", "\\", NULL }, \
754 { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, \
755 { "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_diag_char_table[0] }
756
757 static const format_char_info gcc_diag_char_table[] =
758 {
759 /* The conversion specifiers implemented within pp_format. */
760 PP_FORMAT_CHAR_TABLE,
761
762 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
763 };
764
765 static const format_char_info gcc_tdiag_char_table[] =
766 {
767 /* The conversion specifiers implemented within pp_format. */
768 PP_FORMAT_CHAR_TABLE,
769
770 /* Custom conversion specifiers implemented by default_tree_printer. */
771
772 /* These will require a "tree" at runtime. */
773 { "DFTV", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "'", NULL },
774 { "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL },
775 { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
776
777 /* G requires a "gimple*" argument at runtime. */
778 { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
779
780 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
781 };
782
783 static const format_char_info gcc_cdiag_char_table[] =
784 {
785 /* The conversion specifiers implemented within pp_format. */
786 PP_FORMAT_CHAR_TABLE,
787
788 /* Custom conversion specifiers implemented by c_tree_printer. */
789
790 /* These will require a "tree" at runtime. */
791 { "DFTV", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "'", NULL },
792 { "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL },
793 { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
794
795 /* G requires a "gimple*" argument at runtime. */
796 { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
797
798 { "v", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL },
799
800 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
801 };
802
803 static const format_char_info gcc_cxxdiag_char_table[] =
804 {
805 /* The conversion specifiers implemented within pp_format. */
806 PP_FORMAT_CHAR_TABLE,
807
808 /* Custom conversion specifiers implemented by cp_printer. */
809
810 /* These will require a "tree" at runtime. */
811 { "ADFHISTVX",1,STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "'", NULL },
812 { "E", 1,STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL },
813 { "K", 1, STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
814
815 /* G requires a "gimple*" argument at runtime. */
816 { "G", 1, STD_C89,{ T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
817
818 /* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.) */
819 { "CLOPQ",0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
820
821 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
822 };
823
824 static const format_char_info gcc_gfc_char_table[] =
825 {
826 /* C89 conversion specifiers. */
827 { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
828 { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
829 { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL },
830 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "cR", NULL },
831
832 /* gfc conversion specifiers. */
833
834 { "C", 0, STD_C89, NOARGUMENTS, "", "", NULL },
835
836 /* This will require a "locus" at runtime. */
837 { "L", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "R", NULL },
838
839 /* These will require nothing. */
840 { "<>",0, STD_C89, NOARGUMENTS, "", "", NULL },
841 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
842 };
843
844 static const format_char_info gcc_dump_printf_char_table[] =
845 {
846 /* The conversion specifiers implemented within pp_format. */
847 PP_FORMAT_CHAR_TABLE,
848
849 /* Custom conversion specifiers implemented by dump_pretty_printer. */
850
851 /* E and G require a "gimple *" argument at runtime. */
852 { "EG", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
853
854 /* C requires a "cgraph_node *" argument at runtime. */
855 { "C", 1, STD_C89, { T_CGRAPH_NODE, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
856
857 /* T requires a "tree" at runtime. */
858 { "T", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
859
860 /* %f requires a "double"; it doesn't support modifiers. */
861 { "f", 0, STD_C89, { T89_D, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL },
862
863 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
864 };
865
866 static const format_char_info scan_char_table[] =
867 {
868 /* C89 conversion specifiers. */
869 { "di", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, TEX_LL, T99_SST, T99_PD, T99_IM, BADLEN, BADLEN, BADLEN }, "*w'I", "W", NULL },
870 { "u", 1, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM, BADLEN, BADLEN, BADLEN }, "*w'I", "W", NULL },
871 { "oxX", 1, STD_C89, { T89_UI, T99_UC, T89_US, T89_UL, T9L_ULL, TEX_ULL, T99_ST, T99_UPD, T99_UIM, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL },
872 { "efgEG", 1, STD_C89, { T89_F, BADLEN, BADLEN, T89_D, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "*w'", "W", NULL },
873 { "c", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*mw", "cW", NULL },
874 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*amw", "cW", NULL },
875 { "[", 1, STD_C89, { T89_C, BADLEN, BADLEN, T94_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*amw", "cW[", NULL },
876 { "p", 2, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*w", "W", NULL },
877 { "n", 1, STD_C89, { T89_I, T99_SC, T89_S, T89_L, T9L_LL, BADLEN, T99_SST, T99_PD, T99_IM, BADLEN, BADLEN, BADLEN }, "", "W", NULL },
878 /* C99 conversion specifiers. */
879 { "F", 1, STD_C99, { T99_F, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "*w'", "W", NULL },
880 { "aA", 1, STD_C99, { T99_F, BADLEN, BADLEN, T99_D, BADLEN, T99_LD, BADLEN, BADLEN, BADLEN, TEX_D32, TEX_D64, TEX_D128 }, "*w'", "W", NULL },
881 /* X/Open conversion specifiers. */
882 { "C", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*mw", "W", NULL },
883 { "S", 1, STD_EXT, { TEX_W, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "*amw", "W", NULL },
884 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
885 };
886
887 static const format_char_info time_char_table[] =
888 {
889 /* C89 conversion specifiers. */
890 { "ABZab", 0, STD_C89, NOLENGTHS, "^#", "", NULL },
891 { "cx", 0, STD_C89, NOLENGTHS, "E", "3", NULL },
892 { "HIMSUWdmw", 0, STD_C89, NOLENGTHS, "-_0Ow", "", NULL },
893 { "j", 0, STD_C89, NOLENGTHS, "-_0Ow", "o", NULL },
894 { "p", 0, STD_C89, NOLENGTHS, "#", "", NULL },
895 { "X", 0, STD_C89, NOLENGTHS, "E", "", NULL },
896 { "y", 0, STD_C89, NOLENGTHS, "EO-_0w", "4", NULL },
897 { "Y", 0, STD_C89, NOLENGTHS, "-_0EOw", "o", NULL },
898 { "%", 0, STD_C89, NOLENGTHS, "", "", NULL },
899 /* C99 conversion specifiers. */
900 { "C", 0, STD_C99, NOLENGTHS, "-_0EOw", "o", NULL },
901 { "D", 0, STD_C99, NOLENGTHS, "", "2", NULL },
902 { "eVu", 0, STD_C99, NOLENGTHS, "-_0Ow", "", NULL },
903 { "FRTnrt", 0, STD_C99, NOLENGTHS, "", "", NULL },
904 { "g", 0, STD_C99, NOLENGTHS, "O-_0w", "2o", NULL },
905 { "G", 0, STD_C99, NOLENGTHS, "-_0Ow", "o", NULL },
906 { "h", 0, STD_C99, NOLENGTHS, "^#", "", NULL },
907 { "z", 0, STD_C99, NOLENGTHS, "O", "o", NULL },
908 /* GNU conversion specifiers. */
909 { "kls", 0, STD_EXT, NOLENGTHS, "-_0Ow", "", NULL },
910 { "P", 0, STD_EXT, NOLENGTHS, "", "", NULL },
911 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
912 };
913
914 static const format_char_info monetary_char_table[] =
915 {
916 { "in", 0, STD_C89, { T89_D, BADLEN, BADLEN, BADLEN, BADLEN, T89_LD, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "=^+(!-w#p", "", NULL },
917 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL }
918 };
919
920 /* This must be in the same order as enum format_type. */
921 static const format_kind_info format_types_orig[] =
922 {
923 { "gnu_printf", printf_length_specs, print_char_table, " +#0-'I", NULL,
924 printf_flag_specs, printf_flag_pairs,
925 FMT_FLAG_ARG_CONVERT|FMT_FLAG_DOLLAR_MULTIPLE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_EMPTY_PREC_OK,
926 'w', 0, 'p', 0, 'L', 0,
927 &integer_type_node, &integer_type_node
928 },
929 { "asm_fprintf", asm_fprintf_length_specs, asm_fprintf_char_table, " +#0-", NULL,
930 asm_fprintf_flag_specs, asm_fprintf_flag_pairs,
931 FMT_FLAG_ARG_CONVERT|FMT_FLAG_EMPTY_PREC_OK,
932 'w', 0, 'p', 0, 'L', 0,
933 NULL, NULL
934 },
935 { "gcc_diag", gcc_diag_length_specs, gcc_diag_char_table, "q+#", NULL,
936 gcc_diag_flag_specs, gcc_diag_flag_pairs,
937 FMT_FLAG_ARG_CONVERT,
938 0, 0, 'p', 0, 'L', 0,
939 NULL, &integer_type_node
940 },
941 { "gcc_tdiag", gcc_tdiag_length_specs, gcc_tdiag_char_table, "q+#", NULL,
942 gcc_tdiag_flag_specs, gcc_tdiag_flag_pairs,
943 FMT_FLAG_ARG_CONVERT,
944 0, 0, 'p', 0, 'L', 0,
945 NULL, &integer_type_node
946 },
947 { "gcc_cdiag", gcc_cdiag_length_specs, gcc_cdiag_char_table, "q+#", NULL,
948 gcc_cdiag_flag_specs, gcc_cdiag_flag_pairs,
949 FMT_FLAG_ARG_CONVERT,
950 0, 0, 'p', 0, 'L', 0,
951 NULL, &integer_type_node
952 },
953 { "gcc_cxxdiag", gcc_cxxdiag_length_specs, gcc_cxxdiag_char_table, "q+#", NULL,
954 gcc_cxxdiag_flag_specs, gcc_cxxdiag_flag_pairs,
955 FMT_FLAG_ARG_CONVERT,
956 0, 0, 'p', 0, 'L', 0,
957 NULL, &integer_type_node
958 },
959 { "gcc_gfc", gcc_gfc_length_specs, gcc_gfc_char_table, "q+#", NULL,
960 gcc_gfc_flag_specs, gcc_gfc_flag_pairs,
961 FMT_FLAG_ARG_CONVERT,
962 0, 0, 0, 0, 0, 0,
963 NULL, NULL
964 },
965 { "gcc_dump_printf", gcc_dump_printf_length_specs,
966 gcc_dump_printf_char_table, "q+#", NULL,
967 gcc_dump_printf_flag_specs, gcc_dump_printf_flag_pairs,
968 FMT_FLAG_ARG_CONVERT,
969 0, 0, 'p', 0, 'L', 0,
970 NULL, &integer_type_node
971 },
972 { "NSString", NULL, NULL, NULL, NULL,
973 NULL, NULL,
974 FMT_FLAG_ARG_CONVERT|FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL, 0, 0, 0, 0, 0, 0,
975 NULL, NULL
976 },
977 { "gnu_scanf", scanf_length_specs, scan_char_table, "*'I", NULL,
978 scanf_flag_specs, scanf_flag_pairs,
979 FMT_FLAG_ARG_CONVERT|FMT_FLAG_SCANF_A_KLUDGE|FMT_FLAG_USE_DOLLAR|FMT_FLAG_ZERO_WIDTH_BAD|FMT_FLAG_DOLLAR_GAP_POINTER_OK,
980 'w', 0, 0, '*', 'L', 'm',
981 NULL, NULL
982 },
983 { "gnu_strftime", NULL, time_char_table, "_-0^#", "EO",
984 strftime_flag_specs, strftime_flag_pairs,
985 FMT_FLAG_FANCY_PERCENT_OK, 'w', 0, 0, 0, 0, 0,
986 NULL, NULL
987 },
988 { "gnu_strfmon", strfmon_length_specs, monetary_char_table, "=^+(!-", NULL,
989 strfmon_flag_specs, strfmon_flag_pairs,
990 FMT_FLAG_ARG_CONVERT, 'w', '#', 'p', 0, 'L', 0,
991 NULL, NULL
992 }
993 };
994
995 /* This layer of indirection allows GCC to reassign format_types with
996 new data if necessary, while still allowing the original data to be
997 const. */
998 static const format_kind_info *format_types = format_types_orig;
999 /* We can modify this one. We also add target-specific format types
1000 to the end of the array. */
1001 static format_kind_info *dynamic_format_types;
1002
1003 static int n_format_types = ARRAY_SIZE (format_types_orig);
1004
1005 /* Structure detailing the results of checking a format function call
1006 where the format expression may be a conditional expression with
1007 many leaves resulting from nested conditional expressions. */
1008 struct format_check_results
1009 {
1010 /* Number of leaves of the format argument that could not be checked
1011 as they were not string literals. */
1012 int number_non_literal;
1013 /* Number of leaves of the format argument that were null pointers or
1014 string literals, but had extra format arguments. */
1015 int number_extra_args;
1016 location_t extra_arg_loc;
1017 /* Number of leaves of the format argument that were null pointers or
1018 string literals, but had extra format arguments and used $ operand
1019 numbers. */
1020 int number_dollar_extra_args;
1021 /* Number of leaves of the format argument that were wide string
1022 literals. */
1023 int number_wide;
1024 /* Number of leaves of the format argument that are not array of "char". */
1025 int number_non_char;
1026 /* Number of leaves of the format argument that were empty strings. */
1027 int number_empty;
1028 /* Number of leaves of the format argument that were unterminated
1029 strings. */
1030 int number_unterminated;
1031 /* Number of leaves of the format argument that were not counted above. */
1032 int number_other;
1033 /* Location of the format string. */
1034 location_t format_string_loc;
1035 };
1036
1037 struct format_check_context
1038 {
1039 format_check_results *res;
1040 function_format_info *info;
1041 tree params;
1042 vec<location_t> *arglocs;
1043 };
1044
1045 /* Return the format name (as specified in the original table) for the format
1046 type indicated by format_num. */
1047 static const char *
1048 format_name (int format_num)
1049 {
1050 if (format_num >= 0 && format_num < n_format_types)
1051 return format_types[format_num].name;
1052 gcc_unreachable ();
1053 }
1054
1055 /* Return the format flags (as specified in the original table) for the format
1056 type indicated by format_num. */
1057 static int
1058 format_flags (int format_num)
1059 {
1060 if (format_num >= 0 && format_num < n_format_types)
1061 return format_types[format_num].flags;
1062 gcc_unreachable ();
1063 }
1064
1065 static void check_format_info (function_format_info *, tree,
1066 vec<location_t> *);
1067 static void check_format_arg (void *, tree, unsigned HOST_WIDE_INT);
1068 static void check_format_info_main (format_check_results *,
1069 function_format_info *, const char *,
1070 location_t, tree,
1071 int, tree,
1072 unsigned HOST_WIDE_INT,
1073 object_allocator<format_wanted_type> &,
1074 vec<location_t> *);
1075
1076 static void init_dollar_format_checking (int, tree);
1077 static int maybe_read_dollar_number (const char **, int,
1078 tree, tree *, const format_kind_info *);
1079 static bool avoid_dollar_number (const char *);
1080 static void finish_dollar_format_checking (format_check_results *, int);
1081
1082 static const format_flag_spec *get_flag_spec (const format_flag_spec *,
1083 int, const char *);
1084
1085 static void check_format_types (const substring_loc &fmt_loc,
1086 format_wanted_type *,
1087 const format_kind_info *fki,
1088 int offset_to_type_start,
1089 char conversion_char,
1090 vec<location_t> *arglocs);
1091 static void format_type_warning (const substring_loc &fmt_loc,
1092 location_t param_loc,
1093 format_wanted_type *, tree,
1094 tree,
1095 const format_kind_info *fki,
1096 int offset_to_type_start,
1097 char conversion_char);
1098
1099 /* Decode a format type from a string, returning the type, or
1100 format_type_error if not valid, in which case the caller should
1101 print an error message. On success, when IS_RAW is non-null, set
1102 *IS_RAW when the format type corresponds to a GCC "raw" diagnostic
1103 formatting function and clear it otherwise. */
1104 static format_type
1105 decode_format_type (const char *s, bool *is_raw /* = NULL */)
1106 {
1107 bool is_raw_buf;
1108
1109 if (!is_raw)
1110 is_raw = &is_raw_buf;
1111
1112 *is_raw = false;
1113
1114 s = convert_format_name_to_system_name (s);
1115
1116 size_t slen = strlen (s);
1117 for (int i = 0; i < n_format_types; i++)
1118 {
1119 /* Check for a match with no underscores. */
1120 if (!strcmp (s, format_types[i].name))
1121 return static_cast<format_type> (i);
1122
1123 /* Check for leading and trailing underscores. */
1124 size_t alen = strlen (format_types[i].name);
1125 if (slen == alen + 4 && s[0] == '_' && s[1] == '_'
1126 && s[slen - 1] == '_' && s[slen - 2] == '_'
1127 && !strncmp (s + 2, format_types[i].name, alen))
1128 return static_cast<format_type>(i);
1129
1130 /* Check for the "_raw" suffix and no leading underscores. */
1131 if (slen == alen + 4
1132 && !strncmp (s, format_types[i].name, alen)
1133 && !strcmp (s + alen, "_raw"))
1134 {
1135 *is_raw = true;
1136 return static_cast<format_type>(i);
1137 }
1138
1139 /* Check for the "_raw__" suffix and leading underscores. */
1140 if (slen == alen + 8 && s[0] == '_' && s[1] == '_'
1141 && !strncmp (s + 2, format_types[i].name, alen)
1142 && !strcmp (s + 2 + alen, "_raw__"))
1143 {
1144 *is_raw = true;
1145 return static_cast<format_type>(i);
1146 }
1147 }
1148
1149 return format_type_error;
1150 }
1151
1152 \f
1153 /* Check the argument list of a call to printf, scanf, etc.
1154 ATTRS are the attributes on the function type. There are NARGS argument
1155 values in the array ARGARRAY.
1156 Also, if -Wsuggest-attribute=format,
1157 warn for calls to vprintf or vscanf in functions with no such format
1158 attribute themselves. */
1159
1160 void
1161 check_function_format (const_tree fntype, tree attrs, int nargs,
1162 tree *argarray, vec<location_t> *arglocs)
1163 {
1164 tree a;
1165
1166 tree atname = get_identifier ("format");
1167
1168 /* See if this function has any format attributes. */
1169 for (a = attrs; a; a = TREE_CHAIN (a))
1170 {
1171 if (is_attribute_p ("format", get_attribute_name (a)))
1172 {
1173 /* Yup; check it. */
1174 function_format_info info;
1175 decode_format_attr (fntype, atname, TREE_VALUE (a), &info,
1176 /*validated=*/true);
1177 if (warn_format)
1178 {
1179 /* FIXME: Rewrite all the internal functions in this file
1180 to use the ARGARRAY directly instead of constructing this
1181 temporary list. */
1182 tree params = NULL_TREE;
1183 int i;
1184 for (i = nargs - 1; i >= 0; i--)
1185 params = tree_cons (NULL_TREE, argarray[i], params);
1186 check_format_info (&info, params, arglocs);
1187 }
1188
1189 /* Attempt to detect whether the current function might benefit
1190 from the format attribute if the called function is decorated
1191 with it. Avoid using calls with string literal formats for
1192 guidance since those are unlikely to be viable candidates. */
1193 if (warn_suggest_attribute_format
1194 && current_function_decl != NULL_TREE
1195 && info.first_arg_num == 0
1196 && (format_types[info.format_type].flags
1197 & (int) FMT_FLAG_ARG_CONVERT)
1198 /* c_strlen will fail for a function parameter but succeed
1199 for a literal or constant array. */
1200 && !c_strlen (argarray[info.format_num - 1], 1))
1201 {
1202 tree c;
1203 for (c = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1204 c;
1205 c = TREE_CHAIN (c))
1206 if (is_attribute_p ("format", TREE_PURPOSE (c))
1207 && (decode_format_type (IDENTIFIER_POINTER
1208 (TREE_VALUE (TREE_VALUE (c))))
1209 == info.format_type))
1210 break;
1211 if (c == NULL_TREE)
1212 {
1213 /* Check if the current function has a parameter to which
1214 the format attribute could be attached; if not, it
1215 can't be a candidate for a format attribute, despite
1216 the vprintf-like or vscanf-like call. */
1217 tree args;
1218 for (args = DECL_ARGUMENTS (current_function_decl);
1219 args != 0;
1220 args = DECL_CHAIN (args))
1221 {
1222 if (TREE_CODE (TREE_TYPE (args)) == POINTER_TYPE
1223 && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (args)))
1224 == char_type_node))
1225 break;
1226 }
1227 if (args != 0)
1228 warning (OPT_Wsuggest_attribute_format, "function %qD "
1229 "might be a candidate for %qs format attribute",
1230 current_function_decl,
1231 format_types[info.format_type].name);
1232 }
1233 }
1234 }
1235 }
1236 }
1237
1238
1239 /* Variables used by the checking of $ operand number formats. */
1240 static char *dollar_arguments_used = NULL;
1241 static char *dollar_arguments_pointer_p = NULL;
1242 static int dollar_arguments_alloc = 0;
1243 static int dollar_arguments_count;
1244 static int dollar_first_arg_num;
1245 static int dollar_max_arg_used;
1246 static int dollar_format_warned;
1247
1248 /* Initialize the checking for a format string that may contain $
1249 parameter number specifications; we will need to keep track of whether
1250 each parameter has been used. FIRST_ARG_NUM is the number of the first
1251 argument that is a parameter to the format, or 0 for a vprintf-style
1252 function; PARAMS is the list of arguments starting at this argument. */
1253
1254 static void
1255 init_dollar_format_checking (int first_arg_num, tree params)
1256 {
1257 tree oparams = params;
1258
1259 dollar_first_arg_num = first_arg_num;
1260 dollar_arguments_count = 0;
1261 dollar_max_arg_used = 0;
1262 dollar_format_warned = 0;
1263 if (first_arg_num > 0)
1264 {
1265 while (params)
1266 {
1267 dollar_arguments_count++;
1268 params = TREE_CHAIN (params);
1269 }
1270 }
1271 if (dollar_arguments_alloc < dollar_arguments_count)
1272 {
1273 free (dollar_arguments_used);
1274 free (dollar_arguments_pointer_p);
1275 dollar_arguments_alloc = dollar_arguments_count;
1276 dollar_arguments_used = XNEWVEC (char, dollar_arguments_alloc);
1277 dollar_arguments_pointer_p = XNEWVEC (char, dollar_arguments_alloc);
1278 }
1279 if (dollar_arguments_alloc)
1280 {
1281 memset (dollar_arguments_used, 0, dollar_arguments_alloc);
1282 if (first_arg_num > 0)
1283 {
1284 int i = 0;
1285 params = oparams;
1286 while (params)
1287 {
1288 dollar_arguments_pointer_p[i] = (TREE_CODE (TREE_TYPE (TREE_VALUE (params)))
1289 == POINTER_TYPE);
1290 params = TREE_CHAIN (params);
1291 i++;
1292 }
1293 }
1294 }
1295 }
1296
1297
1298 /* Look for a decimal number followed by a $ in *FORMAT. If DOLLAR_NEEDED
1299 is set, it is an error if one is not found; otherwise, it is OK. If
1300 such a number is found, check whether it is within range and mark that
1301 numbered operand as being used for later checking. Returns the operand
1302 number if found and within range, zero if no such number was found and
1303 this is OK, or -1 on error. PARAMS points to the first operand of the
1304 format; PARAM_PTR is made to point to the parameter referred to. If
1305 a $ format is found, *FORMAT is updated to point just after it. */
1306
1307 static int
1308 maybe_read_dollar_number (const char **format,
1309 int dollar_needed, tree params, tree *param_ptr,
1310 const format_kind_info *fki)
1311 {
1312 int argnum;
1313 int overflow_flag;
1314 const char *fcp = *format;
1315 if (!ISDIGIT (*fcp))
1316 {
1317 if (dollar_needed)
1318 {
1319 warning (OPT_Wformat_, "missing $ operand number in format");
1320 return -1;
1321 }
1322 else
1323 return 0;
1324 }
1325 argnum = 0;
1326 overflow_flag = 0;
1327 while (ISDIGIT (*fcp))
1328 {
1329 HOST_WIDE_INT nargnum
1330 = HOST_WIDE_INT_UC (10) * argnum + (*fcp - '0');
1331 if ((int) nargnum != nargnum)
1332 overflow_flag = 1;
1333 argnum = nargnum;
1334 fcp++;
1335 }
1336 if (*fcp != '$')
1337 {
1338 if (dollar_needed)
1339 {
1340 warning (OPT_Wformat_, "missing $ operand number in format");
1341 return -1;
1342 }
1343 else
1344 return 0;
1345 }
1346 *format = fcp + 1;
1347 if (pedantic && !dollar_format_warned)
1348 {
1349 warning (OPT_Wformat_, "%s does not support %%n$ operand number formats",
1350 C_STD_NAME (STD_EXT));
1351 dollar_format_warned = 1;
1352 }
1353 if (overflow_flag || argnum == 0
1354 || (dollar_first_arg_num && argnum > dollar_arguments_count))
1355 {
1356 warning (OPT_Wformat_, "operand number out of range in format");
1357 return -1;
1358 }
1359 if (argnum > dollar_max_arg_used)
1360 dollar_max_arg_used = argnum;
1361 /* For vprintf-style functions we may need to allocate more memory to
1362 track which arguments are used. */
1363 while (dollar_arguments_alloc < dollar_max_arg_used)
1364 {
1365 int nalloc;
1366 nalloc = 2 * dollar_arguments_alloc + 16;
1367 dollar_arguments_used = XRESIZEVEC (char, dollar_arguments_used,
1368 nalloc);
1369 dollar_arguments_pointer_p = XRESIZEVEC (char, dollar_arguments_pointer_p,
1370 nalloc);
1371 memset (dollar_arguments_used + dollar_arguments_alloc, 0,
1372 nalloc - dollar_arguments_alloc);
1373 dollar_arguments_alloc = nalloc;
1374 }
1375 if (!(fki->flags & (int) FMT_FLAG_DOLLAR_MULTIPLE)
1376 && dollar_arguments_used[argnum - 1] == 1)
1377 {
1378 dollar_arguments_used[argnum - 1] = 2;
1379 warning (OPT_Wformat_, "format argument %d used more than once in %s format",
1380 argnum, fki->name);
1381 }
1382 else
1383 dollar_arguments_used[argnum - 1] = 1;
1384 if (dollar_first_arg_num)
1385 {
1386 int i;
1387 *param_ptr = params;
1388 for (i = 1; i < argnum && *param_ptr != 0; i++)
1389 *param_ptr = TREE_CHAIN (*param_ptr);
1390
1391 /* This case shouldn't be caught here. */
1392 gcc_assert (*param_ptr);
1393 }
1394 else
1395 *param_ptr = 0;
1396 return argnum;
1397 }
1398
1399 /* Ensure that FORMAT does not start with a decimal number followed by
1400 a $; give a diagnostic and return true if it does, false otherwise. */
1401
1402 static bool
1403 avoid_dollar_number (const char *format)
1404 {
1405 if (!ISDIGIT (*format))
1406 return false;
1407 while (ISDIGIT (*format))
1408 format++;
1409 if (*format == '$')
1410 {
1411 warning (OPT_Wformat_,
1412 "%<$%>operand number used after format without operand number");
1413 return true;
1414 }
1415 return false;
1416 }
1417
1418
1419 /* Finish the checking for a format string that used $ operand number formats
1420 instead of non-$ formats. We check for unused operands before used ones
1421 (a serious error, since the implementation of the format function
1422 can't know what types to pass to va_arg to find the later arguments).
1423 and for unused operands at the end of the format (if we know how many
1424 arguments the format had, so not for vprintf). If there were operand
1425 numbers out of range on a non-vprintf-style format, we won't have reached
1426 here. If POINTER_GAP_OK, unused arguments are OK if all arguments are
1427 pointers. */
1428
1429 static void
1430 finish_dollar_format_checking (format_check_results *res, int pointer_gap_ok)
1431 {
1432 int i;
1433 bool found_pointer_gap = false;
1434 for (i = 0; i < dollar_max_arg_used; i++)
1435 {
1436 if (!dollar_arguments_used[i])
1437 {
1438 if (pointer_gap_ok && (dollar_first_arg_num == 0
1439 || dollar_arguments_pointer_p[i]))
1440 found_pointer_gap = true;
1441 else
1442 warning_at (res->format_string_loc, OPT_Wformat_,
1443 "format argument %d unused before used argument %d "
1444 "in %<$%>-style format",
1445 i + 1, dollar_max_arg_used);
1446 }
1447 }
1448 if (found_pointer_gap
1449 || (dollar_first_arg_num
1450 && dollar_max_arg_used < dollar_arguments_count))
1451 {
1452 res->number_other--;
1453 res->number_dollar_extra_args++;
1454 }
1455 }
1456
1457
1458 /* Retrieve the specification for a format flag. SPEC contains the
1459 specifications for format flags for the applicable kind of format.
1460 FLAG is the flag in question. If PREDICATES is NULL, the basic
1461 spec for that flag must be retrieved and must exist. If
1462 PREDICATES is not NULL, it is a string listing possible predicates
1463 for the spec entry; if an entry predicated on any of these is
1464 found, it is returned, otherwise NULL is returned. */
1465
1466 static const format_flag_spec *
1467 get_flag_spec (const format_flag_spec *spec, int flag, const char *predicates)
1468 {
1469 int i;
1470 for (i = 0; spec[i].flag_char != 0; i++)
1471 {
1472 if (spec[i].flag_char != flag)
1473 continue;
1474 if (predicates != NULL)
1475 {
1476 if (spec[i].predicate != 0
1477 && strchr (predicates, spec[i].predicate) != 0)
1478 return &spec[i];
1479 }
1480 else if (spec[i].predicate == 0)
1481 return &spec[i];
1482 }
1483 gcc_assert (predicates);
1484 return NULL;
1485 }
1486
1487
1488 /* Check the argument list of a call to printf, scanf, etc.
1489 INFO points to the function_format_info structure.
1490 PARAMS is the list of argument values. */
1491
1492 static void
1493 check_format_info (function_format_info *info, tree params,
1494 vec<location_t> *arglocs)
1495 {
1496 format_check_context format_ctx;
1497 unsigned HOST_WIDE_INT arg_num;
1498 tree format_tree;
1499 format_check_results res;
1500 /* Skip to format argument. If the argument isn't available, there's
1501 no work for us to do; prototype checking will catch the problem. */
1502 for (arg_num = 1; ; ++arg_num)
1503 {
1504 if (params == 0)
1505 return;
1506 if (arg_num == info->format_num)
1507 break;
1508 params = TREE_CHAIN (params);
1509 }
1510 format_tree = TREE_VALUE (params);
1511 params = TREE_CHAIN (params);
1512 if (format_tree == 0)
1513 return;
1514
1515 res.number_non_literal = 0;
1516 res.number_extra_args = 0;
1517 res.extra_arg_loc = UNKNOWN_LOCATION;
1518 res.number_dollar_extra_args = 0;
1519 res.number_wide = 0;
1520 res.number_non_char = 0;
1521 res.number_empty = 0;
1522 res.number_unterminated = 0;
1523 res.number_other = 0;
1524 res.format_string_loc = input_location;
1525
1526 format_ctx.res = &res;
1527 format_ctx.info = info;
1528 format_ctx.params = params;
1529 format_ctx.arglocs = arglocs;
1530
1531 check_function_arguments_recurse (check_format_arg, &format_ctx,
1532 format_tree, arg_num);
1533
1534 location_t loc = format_ctx.res->format_string_loc;
1535
1536 if (res.number_non_literal > 0)
1537 {
1538 /* Functions taking a va_list normally pass a non-literal format
1539 string. These functions typically are declared with
1540 first_arg_num == 0, so avoid warning in those cases. */
1541 if (!(format_types[info->format_type].flags & (int) FMT_FLAG_ARG_CONVERT))
1542 {
1543 /* For strftime-like formats, warn for not checking the format
1544 string; but there are no arguments to check. */
1545 warning_at (loc, OPT_Wformat_nonliteral,
1546 "format not a string literal, format string not checked");
1547 }
1548 else if (info->first_arg_num != 0)
1549 {
1550 /* If there are no arguments for the format at all, we may have
1551 printf (foo) which is likely to be a security hole. */
1552 while (arg_num + 1 < info->first_arg_num)
1553 {
1554 if (params == 0)
1555 break;
1556 params = TREE_CHAIN (params);
1557 ++arg_num;
1558 }
1559 if (params == 0 && warn_format_security)
1560 warning_at (loc, OPT_Wformat_security,
1561 "format not a string literal and no format arguments");
1562 else if (params == 0 && warn_format_nonliteral)
1563 warning_at (loc, OPT_Wformat_nonliteral,
1564 "format not a string literal and no format arguments");
1565 else
1566 warning_at (loc, OPT_Wformat_nonliteral,
1567 "format not a string literal, argument types not checked");
1568 }
1569 }
1570
1571 /* If there were extra arguments to the format, normally warn. However,
1572 the standard does say extra arguments are ignored, so in the specific
1573 case where we have multiple leaves (conditional expressions or
1574 ngettext) allow extra arguments if at least one leaf didn't have extra
1575 arguments, but was otherwise OK (either non-literal or checked OK).
1576 If the format is an empty string, this should be counted similarly to the
1577 case of extra format arguments. */
1578 if (res.number_extra_args > 0 && res.number_non_literal == 0
1579 && res.number_other == 0)
1580 {
1581 if (res.extra_arg_loc == UNKNOWN_LOCATION)
1582 res.extra_arg_loc = loc;
1583 warning_at (res.extra_arg_loc, OPT_Wformat_extra_args,
1584 "too many arguments for format");
1585 }
1586 if (res.number_dollar_extra_args > 0 && res.number_non_literal == 0
1587 && res.number_other == 0)
1588 warning_at (loc, OPT_Wformat_extra_args,
1589 "unused arguments in %<$%>-style format");
1590 if (res.number_empty > 0 && res.number_non_literal == 0
1591 && res.number_other == 0)
1592 warning_at (loc, OPT_Wformat_zero_length, "zero-length %s format string",
1593 format_types[info->format_type].name);
1594
1595 if (res.number_wide > 0)
1596 warning_at (loc, OPT_Wformat_, "format is a wide character string");
1597
1598 if (res.number_non_char > 0)
1599 warning_at (loc, OPT_Wformat_,
1600 "format string is not an array of type %qs", "char");
1601
1602 if (res.number_unterminated > 0)
1603 warning_at (loc, OPT_Wformat_, "unterminated format string");
1604 }
1605
1606 /* Callback from check_function_arguments_recurse to check a
1607 format string. FORMAT_TREE is the format parameter. ARG_NUM
1608 is the number of the format argument. CTX points to a
1609 format_check_context. */
1610
1611 static void
1612 check_format_arg (void *ctx, tree format_tree,
1613 unsigned HOST_WIDE_INT arg_num)
1614 {
1615 format_check_context *format_ctx = (format_check_context *) ctx;
1616 format_check_results *res = format_ctx->res;
1617 function_format_info *info = format_ctx->info;
1618 tree params = format_ctx->params;
1619 vec<location_t> *arglocs = format_ctx->arglocs;
1620
1621 int format_length;
1622 HOST_WIDE_INT offset;
1623 const char *format_chars;
1624 tree array_size = 0;
1625 tree array_init;
1626
1627 location_t fmt_param_loc = EXPR_LOC_OR_LOC (format_tree, input_location);
1628
1629 /* Pull out a constant value if the front end didn't, and handle location
1630 wrappers. */
1631 format_tree = fold_for_warn (format_tree);
1632 STRIP_NOPS (format_tree);
1633
1634 if (integer_zerop (format_tree))
1635 {
1636 /* Skip to first argument to check, so we can see if this format
1637 has any arguments (it shouldn't). */
1638 while (arg_num + 1 < info->first_arg_num)
1639 {
1640 if (params == 0)
1641 return;
1642 params = TREE_CHAIN (params);
1643 ++arg_num;
1644 }
1645
1646 if (params == 0)
1647 res->number_other++;
1648 else
1649 {
1650 if (res->number_extra_args == 0)
1651 res->extra_arg_loc = EXPR_LOC_OR_LOC (TREE_VALUE (params),
1652 input_location);
1653 res->number_extra_args++;
1654 }
1655 return;
1656 }
1657
1658 offset = 0;
1659 if (TREE_CODE (format_tree) == POINTER_PLUS_EXPR)
1660 {
1661 tree arg0, arg1;
1662
1663 arg0 = TREE_OPERAND (format_tree, 0);
1664 arg1 = TREE_OPERAND (format_tree, 1);
1665 STRIP_NOPS (arg0);
1666 STRIP_NOPS (arg1);
1667 if (TREE_CODE (arg1) == INTEGER_CST)
1668 format_tree = arg0;
1669 else
1670 {
1671 res->number_non_literal++;
1672 return;
1673 }
1674 /* POINTER_PLUS_EXPR offsets are to be interpreted signed. */
1675 if (!cst_and_fits_in_hwi (arg1))
1676 {
1677 res->number_non_literal++;
1678 return;
1679 }
1680 offset = int_cst_value (arg1);
1681 }
1682 if (TREE_CODE (format_tree) != ADDR_EXPR)
1683 {
1684 res->number_non_literal++;
1685 return;
1686 }
1687 res->format_string_loc = EXPR_LOC_OR_LOC (format_tree, input_location);
1688 format_tree = TREE_OPERAND (format_tree, 0);
1689 if (format_types[info->format_type].flags
1690 & (int) FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL)
1691 {
1692 bool objc_str = (info->format_type == gcc_objc_string_format_type);
1693 /* We cannot examine this string here - but we can check that it is
1694 a valid type. */
1695 if (TREE_CODE (format_tree) != CONST_DECL
1696 || !((objc_str && objc_string_ref_type_p (TREE_TYPE (format_tree)))
1697 || (*targetcm.string_object_ref_type_p)
1698 ((const_tree) TREE_TYPE (format_tree))))
1699 {
1700 res->number_non_literal++;
1701 return;
1702 }
1703 /* Skip to first argument to check. */
1704 while (arg_num + 1 < info->first_arg_num)
1705 {
1706 if (params == 0)
1707 return;
1708 params = TREE_CHAIN (params);
1709 ++arg_num;
1710 }
1711 /* So, we have a valid literal string object and one or more params.
1712 We need to use an external helper to parse the string into format
1713 info. For Objective-C variants we provide the resource within the
1714 objc tree, for target variants, via a hook. */
1715 if (objc_str)
1716 objc_check_format_arg (format_tree, params);
1717 else if (targetcm.check_string_object_format_arg)
1718 (*targetcm.check_string_object_format_arg) (format_tree, params);
1719 /* Else we can't handle it and retire quietly. */
1720 return;
1721 }
1722 if (TREE_CODE (format_tree) == ARRAY_REF
1723 && tree_fits_shwi_p (TREE_OPERAND (format_tree, 1))
1724 && (offset += tree_to_shwi (TREE_OPERAND (format_tree, 1))) >= 0)
1725 format_tree = TREE_OPERAND (format_tree, 0);
1726 if (offset < 0)
1727 {
1728 res->number_non_literal++;
1729 return;
1730 }
1731 if (VAR_P (format_tree)
1732 && TREE_CODE (TREE_TYPE (format_tree)) == ARRAY_TYPE
1733 && (array_init = decl_constant_value (format_tree)) != format_tree
1734 && TREE_CODE (array_init) == STRING_CST)
1735 {
1736 /* Extract the string constant initializer. Note that this may include
1737 a trailing NUL character that is not in the array (e.g.
1738 const char a[3] = "foo";). */
1739 array_size = DECL_SIZE_UNIT (format_tree);
1740 format_tree = array_init;
1741 }
1742 if (TREE_CODE (format_tree) != STRING_CST)
1743 {
1744 res->number_non_literal++;
1745 return;
1746 }
1747 tree underlying_type
1748 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (format_tree)));
1749 if (underlying_type != char_type_node)
1750 {
1751 if (underlying_type == char16_type_node
1752 || underlying_type == char32_type_node
1753 || underlying_type == wchar_type_node)
1754 res->number_wide++;
1755 else
1756 res->number_non_char++;
1757 return;
1758 }
1759 format_chars = TREE_STRING_POINTER (format_tree);
1760 format_length = TREE_STRING_LENGTH (format_tree);
1761 if (array_size != 0)
1762 {
1763 /* Variable length arrays can't be initialized. */
1764 gcc_assert (TREE_CODE (array_size) == INTEGER_CST);
1765
1766 if (tree_fits_shwi_p (array_size))
1767 {
1768 HOST_WIDE_INT array_size_value = tree_to_shwi (array_size);
1769 if (array_size_value > 0
1770 && array_size_value == (int) array_size_value
1771 && format_length > array_size_value)
1772 format_length = array_size_value;
1773 }
1774 }
1775 if (offset)
1776 {
1777 if (offset >= format_length)
1778 {
1779 res->number_non_literal++;
1780 return;
1781 }
1782 format_chars += offset;
1783 format_length -= offset;
1784 }
1785 if (format_length < 1 || format_chars[--format_length] != 0)
1786 {
1787 res->number_unterminated++;
1788 return;
1789 }
1790 if (format_length == 0)
1791 {
1792 res->number_empty++;
1793 return;
1794 }
1795
1796 /* Skip to first argument to check. */
1797 while (arg_num + 1 < info->first_arg_num)
1798 {
1799 if (params == 0)
1800 return;
1801 params = TREE_CHAIN (params);
1802 ++arg_num;
1803 }
1804 /* Provisionally increment res->number_other; check_format_info_main
1805 will decrement it if it finds there are extra arguments, but this way
1806 need not adjust it for every return. */
1807 res->number_other++;
1808 object_allocator <format_wanted_type> fwt_pool ("format_wanted_type pool");
1809 check_format_info_main (res, info, format_chars, fmt_param_loc, format_tree,
1810 format_length, params, arg_num, fwt_pool, arglocs);
1811 }
1812
1813 /* Support class for argument_parser and check_format_info_main.
1814 Tracks any flag characters that have been applied to the
1815 current argument. */
1816
1817 class flag_chars_t
1818 {
1819 public:
1820 flag_chars_t ();
1821 bool has_char_p (char ch) const;
1822 void add_char (char ch);
1823 void validate (const format_kind_info *fki,
1824 const format_char_info *fci,
1825 const format_flag_spec *flag_specs,
1826 const char * const format_chars,
1827 tree format_string_cst,
1828 location_t format_string_loc,
1829 const char * const orig_format_chars,
1830 char format_char,
1831 bool quoted);
1832 int get_alloc_flag (const format_kind_info *fki);
1833 int assignment_suppression_p (const format_kind_info *fki);
1834
1835 private:
1836 char m_flag_chars[256];
1837 };
1838
1839 /* Support struct for argument_parser and check_format_info_main.
1840 Encapsulates any length modifier applied to the current argument. */
1841
1842 class length_modifier
1843 {
1844 public:
1845 length_modifier ()
1846 : chars (NULL), val (FMT_LEN_none), std (STD_C89),
1847 scalar_identity_flag (0)
1848 {
1849 }
1850
1851 length_modifier (const char *chars_,
1852 enum format_lengths val_,
1853 enum format_std_version std_,
1854 int scalar_identity_flag_)
1855 : chars (chars_), val (val_), std (std_),
1856 scalar_identity_flag (scalar_identity_flag_)
1857 {
1858 }
1859
1860 const char *chars;
1861 enum format_lengths val;
1862 enum format_std_version std;
1863 int scalar_identity_flag;
1864 };
1865
1866 /* Parsing one argument within a format string. */
1867
1868 class argument_parser
1869 {
1870 public:
1871 argument_parser (function_format_info *info, const char *&format_chars,
1872 tree format_string_cst,
1873 const char * const orig_format_chars,
1874 location_t format_string_loc, flag_chars_t &flag_chars,
1875 int &has_operand_number, tree first_fillin_param,
1876 object_allocator <format_wanted_type> &fwt_pool_,
1877 vec<location_t> *arglocs);
1878
1879 bool read_any_dollar ();
1880
1881 bool read_format_flags ();
1882
1883 bool
1884 read_any_format_width (tree &params,
1885 unsigned HOST_WIDE_INT &arg_num);
1886
1887 void
1888 read_any_format_left_precision ();
1889
1890 bool
1891 read_any_format_precision (tree &params,
1892 unsigned HOST_WIDE_INT &arg_num);
1893
1894 void handle_alloc_chars ();
1895
1896 length_modifier read_any_length_modifier ();
1897
1898 void read_any_other_modifier ();
1899
1900 const format_char_info *find_format_char_info (char format_char);
1901
1902 void
1903 validate_flag_pairs (const format_char_info *fci,
1904 char format_char);
1905
1906 void
1907 give_y2k_warnings (const format_char_info *fci,
1908 char format_char);
1909
1910 void parse_any_scan_set (const format_char_info *fci);
1911
1912 bool handle_conversions (const format_char_info *fci,
1913 const length_modifier &len_modifier,
1914 tree &wanted_type,
1915 const char *&wanted_type_name,
1916 unsigned HOST_WIDE_INT &arg_num,
1917 tree &params,
1918 char format_char);
1919
1920 bool
1921 check_argument_type (const format_char_info *fci,
1922 const length_modifier &len_modifier,
1923 tree &wanted_type,
1924 const char *&wanted_type_name,
1925 const bool suppressed,
1926 unsigned HOST_WIDE_INT &arg_num,
1927 tree &params,
1928 const int alloc_flag,
1929 const char * const format_start,
1930 const char * const type_start,
1931 location_t fmt_param_loc,
1932 char conversion_char);
1933
1934 private:
1935 const function_format_info *const info;
1936 const format_kind_info * const fki;
1937 const format_flag_spec * const flag_specs;
1938 const char *start_of_this_format;
1939 const char *&format_chars;
1940 const tree format_string_cst;
1941 const char * const orig_format_chars;
1942 const location_t format_string_loc;
1943 object_allocator <format_wanted_type> &fwt_pool;
1944 flag_chars_t &flag_chars;
1945 int main_arg_num;
1946 tree main_arg_params;
1947 int &has_operand_number;
1948 const tree first_fillin_param;
1949 format_wanted_type width_wanted_type;
1950 format_wanted_type precision_wanted_type;
1951 public:
1952 format_wanted_type main_wanted_type;
1953 private:
1954 format_wanted_type *first_wanted_type;
1955 format_wanted_type *last_wanted_type;
1956 vec<location_t> *arglocs;
1957 };
1958
1959 /* flag_chars_t's constructor. */
1960
1961 flag_chars_t::flag_chars_t ()
1962 {
1963 m_flag_chars[0] = 0;
1964 }
1965
1966 /* Has CH been seen as a flag within the current argument? */
1967
1968 bool
1969 flag_chars_t::has_char_p (char ch) const
1970 {
1971 return strchr (m_flag_chars, ch) != 0;
1972 }
1973
1974 /* Add CH to the flags seen within the current argument. */
1975
1976 void
1977 flag_chars_t::add_char (char ch)
1978 {
1979 int i = strlen (m_flag_chars);
1980 m_flag_chars[i++] = ch;
1981 m_flag_chars[i] = 0;
1982 }
1983
1984 /* Validate the individual flags used, removing any that are invalid. */
1985
1986 void
1987 flag_chars_t::validate (const format_kind_info *fki,
1988 const format_char_info *fci,
1989 const format_flag_spec *flag_specs,
1990 const char * const format_chars,
1991 tree format_string_cst,
1992 location_t format_string_loc,
1993 const char * const orig_format_chars,
1994 char format_char,
1995 bool quoted)
1996 {
1997 int i;
1998 int d = 0;
1999 bool quotflag = false;
2000
2001 for (i = 0; m_flag_chars[i] != 0; i++)
2002 {
2003 const format_flag_spec *s = get_flag_spec (flag_specs,
2004 m_flag_chars[i], NULL);
2005 m_flag_chars[i - d] = m_flag_chars[i];
2006 if (m_flag_chars[i] == fki->length_code_char)
2007 continue;
2008
2009 /* Remember if a quoting flag is seen. */
2010 quotflag |= s->quoting;
2011
2012 if (strchr (fci->flag_chars, m_flag_chars[i]) == 0)
2013 {
2014 format_warning_at_char (format_string_loc, format_string_cst,
2015 format_chars - orig_format_chars,
2016 OPT_Wformat_,
2017 "%s used with %<%%%c%> %s format",
2018 _(s->name), format_char, fki->name);
2019 d++;
2020 continue;
2021 }
2022 if (pedantic)
2023 {
2024 const format_flag_spec *t;
2025 if (ADJ_STD (s->std) > C_STD_VER)
2026 warning_at (format_string_loc, OPT_Wformat_,
2027 "%s does not support %s",
2028 C_STD_NAME (s->std), _(s->long_name));
2029 t = get_flag_spec (flag_specs, m_flag_chars[i], fci->flags2);
2030 if (t != NULL && ADJ_STD (t->std) > ADJ_STD (s->std))
2031 {
2032 const char *long_name = (t->long_name != NULL
2033 ? t->long_name
2034 : s->long_name);
2035 if (ADJ_STD (t->std) > C_STD_VER)
2036 warning_at (format_string_loc, OPT_Wformat_,
2037 "%s does not support %s with"
2038 " the %<%%%c%> %s format",
2039 C_STD_NAME (t->std), _(long_name),
2040 format_char, fki->name);
2041 }
2042 }
2043
2044 /* Detect quoting directives used within a quoted sequence, such
2045 as GCC's "%<...%qE". */
2046 if (quoted && s->quoting)
2047 {
2048 format_warning_at_char (format_string_loc, format_string_cst,
2049 format_chars - orig_format_chars - 1,
2050 OPT_Wformat_,
2051 "%s used within a quoted sequence",
2052 _(s->name));
2053 }
2054 }
2055 m_flag_chars[i - d] = 0;
2056
2057 if (!quoted
2058 && !quotflag
2059 && strchr (fci->flags2, '\''))
2060 {
2061 format_warning_at_char (format_string_loc, format_string_cst,
2062 format_chars - orig_format_chars,
2063 OPT_Wformat_,
2064 "%qc conversion used unquoted",
2065 format_char);
2066 }
2067 }
2068
2069 /* Determine if an assignment-allocation has been set, requiring
2070 an extra char ** for writing back a dynamically-allocated char *.
2071 This is for handling the optional 'm' character in scanf. */
2072
2073 int
2074 flag_chars_t::get_alloc_flag (const format_kind_info *fki)
2075 {
2076 if ((fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE)
2077 && has_char_p ('a'))
2078 return 1;
2079 if (fki->alloc_char && has_char_p (fki->alloc_char))
2080 return 1;
2081 return 0;
2082 }
2083
2084 /* Determine if an assignment-suppression character was seen.
2085 ('*' in scanf, for discarding the converted input). */
2086
2087 int
2088 flag_chars_t::assignment_suppression_p (const format_kind_info *fki)
2089 {
2090 if (fki->suppression_char
2091 && has_char_p (fki->suppression_char))
2092 return 1;
2093 return 0;
2094 }
2095
2096 /* Constructor for argument_parser. Initialize for parsing one
2097 argument within a format string. */
2098
2099 argument_parser::
2100 argument_parser (function_format_info *info_, const char *&format_chars_,
2101 tree format_string_cst_,
2102 const char * const orig_format_chars_,
2103 location_t format_string_loc_,
2104 flag_chars_t &flag_chars_,
2105 int &has_operand_number_,
2106 tree first_fillin_param_,
2107 object_allocator <format_wanted_type> &fwt_pool_,
2108 vec<location_t> *arglocs_)
2109 : info (info_),
2110 fki (&format_types[info->format_type]),
2111 flag_specs (fki->flag_specs),
2112 start_of_this_format (format_chars_),
2113 format_chars (format_chars_),
2114 format_string_cst (format_string_cst_),
2115 orig_format_chars (orig_format_chars_),
2116 format_string_loc (format_string_loc_),
2117 fwt_pool (fwt_pool_),
2118 flag_chars (flag_chars_),
2119 main_arg_num (0),
2120 main_arg_params (NULL),
2121 has_operand_number (has_operand_number_),
2122 first_fillin_param (first_fillin_param_),
2123 first_wanted_type (NULL),
2124 last_wanted_type (NULL),
2125 arglocs (arglocs_)
2126 {
2127 }
2128
2129 /* Handle dollars at the start of format arguments, setting up main_arg_params
2130 and main_arg_num.
2131
2132 Return true if format parsing is to continue, false otherwise. */
2133
2134 bool
2135 argument_parser::read_any_dollar ()
2136 {
2137 if ((fki->flags & (int) FMT_FLAG_USE_DOLLAR) && has_operand_number != 0)
2138 {
2139 /* Possibly read a $ operand number at the start of the format.
2140 If one was previously used, one is required here. If one
2141 is not used here, we can't immediately conclude this is a
2142 format without them, since it could be printf %m or scanf %*. */
2143 int opnum;
2144 opnum = maybe_read_dollar_number (&format_chars, 0,
2145 first_fillin_param,
2146 &main_arg_params, fki);
2147 if (opnum == -1)
2148 return false;
2149 else if (opnum > 0)
2150 {
2151 has_operand_number = 1;
2152 main_arg_num = opnum + info->first_arg_num - 1;
2153 }
2154 }
2155 else if (fki->flags & FMT_FLAG_USE_DOLLAR)
2156 {
2157 if (avoid_dollar_number (format_chars))
2158 return false;
2159 }
2160 return true;
2161 }
2162
2163 /* Read any format flags, but do not yet validate them beyond removing
2164 duplicates, since in general validation depends on the rest of
2165 the format.
2166
2167 Return true if format parsing is to continue, false otherwise. */
2168
2169 bool
2170 argument_parser::read_format_flags ()
2171 {
2172 while (*format_chars != 0
2173 && strchr (fki->flag_chars, *format_chars) != 0)
2174 {
2175 const format_flag_spec *s = get_flag_spec (flag_specs,
2176 *format_chars, NULL);
2177 if (flag_chars.has_char_p (*format_chars))
2178 {
2179 format_warning_at_char (format_string_loc, format_string_cst,
2180 format_chars + 1 - orig_format_chars,
2181 OPT_Wformat_,
2182 "repeated %s in format", _(s->name));
2183 }
2184 else
2185 flag_chars.add_char (*format_chars);
2186
2187 if (s->skip_next_char)
2188 {
2189 ++format_chars;
2190 if (*format_chars == 0)
2191 {
2192 warning_at (format_string_loc, OPT_Wformat_,
2193 "missing fill character at end of strfmon format");
2194 return false;
2195 }
2196 }
2197 ++format_chars;
2198 }
2199
2200 return true;
2201 }
2202
2203 /* Read any format width, possibly * or *m$.
2204
2205 Return true if format parsing is to continue, false otherwise. */
2206
2207 bool
2208 argument_parser::
2209 read_any_format_width (tree &params,
2210 unsigned HOST_WIDE_INT &arg_num)
2211 {
2212 if (!fki->width_char)
2213 return true;
2214
2215 if (fki->width_type != NULL && *format_chars == '*')
2216 {
2217 flag_chars.add_char (fki->width_char);
2218 /* "...a field width...may be indicated by an asterisk.
2219 In this case, an int argument supplies the field width..." */
2220 ++format_chars;
2221 if (has_operand_number != 0)
2222 {
2223 int opnum;
2224 opnum = maybe_read_dollar_number (&format_chars,
2225 has_operand_number == 1,
2226 first_fillin_param,
2227 &params, fki);
2228 if (opnum == -1)
2229 return false;
2230 else if (opnum > 0)
2231 {
2232 has_operand_number = 1;
2233 arg_num = opnum + info->first_arg_num - 1;
2234 }
2235 else
2236 has_operand_number = 0;
2237 }
2238 else
2239 {
2240 if (avoid_dollar_number (format_chars))
2241 return false;
2242 }
2243 if (info->first_arg_num != 0)
2244 {
2245 tree cur_param;
2246 if (params == 0)
2247 cur_param = NULL;
2248 else
2249 {
2250 cur_param = TREE_VALUE (params);
2251 if (has_operand_number <= 0)
2252 {
2253 params = TREE_CHAIN (params);
2254 ++arg_num;
2255 }
2256 }
2257 width_wanted_type.wanted_type = *fki->width_type;
2258 width_wanted_type.wanted_type_name = NULL;
2259 width_wanted_type.pointer_count = 0;
2260 width_wanted_type.char_lenient_flag = 0;
2261 width_wanted_type.scalar_identity_flag = 0;
2262 width_wanted_type.writing_in_flag = 0;
2263 width_wanted_type.reading_from_flag = 0;
2264 width_wanted_type.kind = CF_KIND_FIELD_WIDTH;
2265 width_wanted_type.format_start = format_chars - 1;
2266 width_wanted_type.format_length = 1;
2267 width_wanted_type.param = cur_param;
2268 width_wanted_type.arg_num = arg_num;
2269 width_wanted_type.offset_loc =
2270 format_chars - orig_format_chars;
2271 width_wanted_type.next = NULL;
2272 if (last_wanted_type != 0)
2273 last_wanted_type->next = &width_wanted_type;
2274 if (first_wanted_type == 0)
2275 first_wanted_type = &width_wanted_type;
2276 last_wanted_type = &width_wanted_type;
2277 }
2278 }
2279 else
2280 {
2281 /* Possibly read a numeric width. If the width is zero,
2282 we complain if appropriate. */
2283 int non_zero_width_char = FALSE;
2284 int found_width = FALSE;
2285 while (ISDIGIT (*format_chars))
2286 {
2287 found_width = TRUE;
2288 if (*format_chars != '0')
2289 non_zero_width_char = TRUE;
2290 ++format_chars;
2291 }
2292 if (found_width && !non_zero_width_char &&
2293 (fki->flags & (int) FMT_FLAG_ZERO_WIDTH_BAD))
2294 warning_at (format_string_loc, OPT_Wformat_,
2295 "zero width in %s format", fki->name);
2296 if (found_width)
2297 flag_chars.add_char (fki->width_char);
2298 }
2299
2300 return true;
2301 }
2302
2303 /* Read any format left precision (must be a number, not *). */
2304 void
2305 argument_parser::read_any_format_left_precision ()
2306 {
2307 if (fki->left_precision_char == 0)
2308 return;
2309 if (*format_chars != '#')
2310 return;
2311
2312 ++format_chars;
2313 flag_chars.add_char (fki->left_precision_char);
2314 if (!ISDIGIT (*format_chars))
2315 format_warning_at_char (format_string_loc, format_string_cst,
2316 format_chars - orig_format_chars,
2317 OPT_Wformat_,
2318 "empty left precision in %s format", fki->name);
2319 while (ISDIGIT (*format_chars))
2320 ++format_chars;
2321 }
2322
2323 /* Read any format precision, possibly * or *m$.
2324
2325 Return true if format parsing is to continue, false otherwise. */
2326
2327 bool
2328 argument_parser::
2329 read_any_format_precision (tree &params,
2330 unsigned HOST_WIDE_INT &arg_num)
2331 {
2332 if (fki->precision_char == 0)
2333 return true;
2334 if (*format_chars != '.')
2335 return true;
2336
2337 ++format_chars;
2338 flag_chars.add_char (fki->precision_char);
2339 if (fki->precision_type != NULL && *format_chars == '*')
2340 {
2341 /* "...a...precision...may be indicated by an asterisk.
2342 In this case, an int argument supplies the...precision." */
2343 ++format_chars;
2344 if (has_operand_number != 0)
2345 {
2346 int opnum;
2347 opnum = maybe_read_dollar_number (&format_chars,
2348 has_operand_number == 1,
2349 first_fillin_param,
2350 &params, fki);
2351 if (opnum == -1)
2352 return false;
2353 else if (opnum > 0)
2354 {
2355 has_operand_number = 1;
2356 arg_num = opnum + info->first_arg_num - 1;
2357 }
2358 else
2359 has_operand_number = 0;
2360 }
2361 else
2362 {
2363 if (avoid_dollar_number (format_chars))
2364 return false;
2365 }
2366 if (info->first_arg_num != 0)
2367 {
2368 tree cur_param;
2369 if (params == 0)
2370 cur_param = NULL;
2371 else
2372 {
2373 cur_param = TREE_VALUE (params);
2374 if (has_operand_number <= 0)
2375 {
2376 params = TREE_CHAIN (params);
2377 ++arg_num;
2378 }
2379 }
2380 precision_wanted_type.wanted_type = *fki->precision_type;
2381 precision_wanted_type.wanted_type_name = NULL;
2382 precision_wanted_type.pointer_count = 0;
2383 precision_wanted_type.char_lenient_flag = 0;
2384 precision_wanted_type.scalar_identity_flag = 0;
2385 precision_wanted_type.writing_in_flag = 0;
2386 precision_wanted_type.reading_from_flag = 0;
2387 precision_wanted_type.kind = CF_KIND_FIELD_PRECISION;
2388 precision_wanted_type.param = cur_param;
2389 precision_wanted_type.format_start = format_chars - 2;
2390 precision_wanted_type.format_length = 2;
2391 precision_wanted_type.arg_num = arg_num;
2392 precision_wanted_type.offset_loc =
2393 format_chars - orig_format_chars;
2394 precision_wanted_type.next = NULL;
2395 if (last_wanted_type != 0)
2396 last_wanted_type->next = &precision_wanted_type;
2397 if (first_wanted_type == 0)
2398 first_wanted_type = &precision_wanted_type;
2399 last_wanted_type = &precision_wanted_type;
2400 }
2401 }
2402 else
2403 {
2404 if (!(fki->flags & (int) FMT_FLAG_EMPTY_PREC_OK)
2405 && !ISDIGIT (*format_chars))
2406 format_warning_at_char (format_string_loc, format_string_cst,
2407 format_chars - orig_format_chars,
2408 OPT_Wformat_,
2409 "empty precision in %s format", fki->name);
2410 while (ISDIGIT (*format_chars))
2411 ++format_chars;
2412 }
2413
2414 return true;
2415 }
2416
2417 /* Parse any assignment-allocation flags, which request an extra
2418 char ** for writing back a dynamically-allocated char *.
2419 This is for handling the optional 'm' character in scanf,
2420 and, before C99, 'a' (for compatibility with a non-standard
2421 GNU libc extension). */
2422
2423 void
2424 argument_parser::handle_alloc_chars ()
2425 {
2426 if (fki->alloc_char && fki->alloc_char == *format_chars)
2427 {
2428 flag_chars.add_char (fki->alloc_char);
2429 format_chars++;
2430 }
2431
2432 /* Handle the scanf allocation kludge. */
2433 if (fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE)
2434 {
2435 if (*format_chars == 'a' && !flag_isoc99)
2436 {
2437 if (format_chars[1] == 's' || format_chars[1] == 'S'
2438 || format_chars[1] == '[')
2439 {
2440 /* 'a' is used as a flag. */
2441 flag_chars.add_char ('a');
2442 format_chars++;
2443 }
2444 }
2445 }
2446 }
2447
2448 /* Look for length modifiers within the current format argument,
2449 returning a length_modifier instance describing it (or the
2450 default if one is not found).
2451
2452 Issue warnings about non-standard modifiers. */
2453
2454 length_modifier
2455 argument_parser::read_any_length_modifier ()
2456 {
2457 length_modifier result;
2458
2459 const format_length_info *fli = fki->length_char_specs;
2460 if (!fli)
2461 return result;
2462
2463 while (fli->name != 0
2464 && strncmp (fli->name, format_chars, strlen (fli->name)))
2465 fli++;
2466 if (fli->name != 0)
2467 {
2468 format_chars += strlen (fli->name);
2469 if (fli->double_name != 0 && fli->name[0] == *format_chars)
2470 {
2471 format_chars++;
2472 result = length_modifier (fli->double_name, fli->double_index,
2473 fli->double_std, 0);
2474 }
2475 else
2476 {
2477 result = length_modifier (fli->name, fli->index, fli->std,
2478 fli->scalar_identity_flag);
2479 }
2480 flag_chars.add_char (fki->length_code_char);
2481 }
2482 if (pedantic)
2483 {
2484 /* Warn if the length modifier is non-standard. */
2485 if (ADJ_STD (result.std) > C_STD_VER)
2486 warning_at (format_string_loc, OPT_Wformat_,
2487 "%s does not support the %qs %s length modifier",
2488 C_STD_NAME (result.std), result.chars,
2489 fki->name);
2490 }
2491
2492 return result;
2493 }
2494
2495 /* Read any other modifier (strftime E/O). */
2496
2497 void
2498 argument_parser::read_any_other_modifier ()
2499 {
2500 if (fki->modifier_chars == NULL)
2501 return;
2502
2503 while (*format_chars != 0
2504 && strchr (fki->modifier_chars, *format_chars) != 0)
2505 {
2506 if (flag_chars.has_char_p (*format_chars))
2507 {
2508 const format_flag_spec *s = get_flag_spec (flag_specs,
2509 *format_chars, NULL);
2510 format_warning_at_char (format_string_loc, format_string_cst,
2511 format_chars - orig_format_chars,
2512 OPT_Wformat_,
2513 "repeated %s in format", _(s->name));
2514 }
2515 else
2516 flag_chars.add_char (*format_chars);
2517 ++format_chars;
2518 }
2519 }
2520
2521 /* Return the format_char_info corresponding to FORMAT_CHAR,
2522 potentially issuing a warning if the format char is
2523 not supported in the C standard version we are checking
2524 against.
2525
2526 Issue a warning and return NULL if it is not found.
2527
2528 Issue warnings about non-standard modifiers. */
2529
2530 const format_char_info *
2531 argument_parser::find_format_char_info (char format_char)
2532 {
2533 const format_char_info *fci = fki->conversion_specs;
2534
2535 while (fci->format_chars != 0
2536 && strchr (fci->format_chars, format_char) == 0)
2537 ++fci;
2538 if (fci->format_chars == 0)
2539 {
2540 format_warning_at_char (format_string_loc, format_string_cst,
2541 format_chars - orig_format_chars,
2542 OPT_Wformat_,
2543 "unknown conversion type character"
2544 " %qc in format",
2545 format_char);
2546 return NULL;
2547 }
2548
2549 if (pedantic)
2550 {
2551 if (ADJ_STD (fci->std) > C_STD_VER)
2552 format_warning_at_char (format_string_loc, format_string_cst,
2553 format_chars - orig_format_chars,
2554 OPT_Wformat_,
2555 "%s does not support the %<%%%c%> %s format",
2556 C_STD_NAME (fci->std), format_char, fki->name);
2557 }
2558
2559 return fci;
2560 }
2561
2562 /* Validate the pairs of flags used.
2563 Issue warnings about incompatible combinations of flags. */
2564
2565 void
2566 argument_parser::validate_flag_pairs (const format_char_info *fci,
2567 char format_char)
2568 {
2569 const format_flag_pair * const bad_flag_pairs = fki->bad_flag_pairs;
2570
2571 for (int i = 0; bad_flag_pairs[i].flag_char1 != 0; i++)
2572 {
2573 const format_flag_spec *s, *t;
2574 if (!flag_chars.has_char_p (bad_flag_pairs[i].flag_char1))
2575 continue;
2576 if (!flag_chars.has_char_p (bad_flag_pairs[i].flag_char2))
2577 continue;
2578 if (bad_flag_pairs[i].predicate != 0
2579 && strchr (fci->flags2, bad_flag_pairs[i].predicate) == 0)
2580 continue;
2581 s = get_flag_spec (flag_specs, bad_flag_pairs[i].flag_char1, NULL);
2582 t = get_flag_spec (flag_specs, bad_flag_pairs[i].flag_char2, NULL);
2583 if (bad_flag_pairs[i].ignored)
2584 {
2585 if (bad_flag_pairs[i].predicate != 0)
2586 warning_at (format_string_loc, OPT_Wformat_,
2587 "%s ignored with %s and %<%%%c%> %s format",
2588 _(s->name), _(t->name), format_char,
2589 fki->name);
2590 else
2591 warning_at (format_string_loc, OPT_Wformat_,
2592 "%s ignored with %s in %s format",
2593 _(s->name), _(t->name), fki->name);
2594 }
2595 else
2596 {
2597 if (bad_flag_pairs[i].predicate != 0)
2598 warning_at (format_string_loc, OPT_Wformat_,
2599 "use of %s and %s together with %<%%%c%> %s format",
2600 _(s->name), _(t->name), format_char,
2601 fki->name);
2602 else
2603 warning_at (format_string_loc, OPT_Wformat_,
2604 "use of %s and %s together in %s format",
2605 _(s->name), _(t->name), fki->name);
2606 }
2607 }
2608 }
2609
2610 /* Give Y2K warnings. */
2611
2612 void
2613 argument_parser::give_y2k_warnings (const format_char_info *fci,
2614 char format_char)
2615 {
2616 if (!warn_format_y2k)
2617 return;
2618
2619 int y2k_level = 0;
2620 if (strchr (fci->flags2, '4') != 0)
2621 if (flag_chars.has_char_p ('E'))
2622 y2k_level = 3;
2623 else
2624 y2k_level = 2;
2625 else if (strchr (fci->flags2, '3') != 0)
2626 y2k_level = 3;
2627 else if (strchr (fci->flags2, '2') != 0)
2628 y2k_level = 2;
2629 if (y2k_level == 3)
2630 warning_at (format_string_loc, OPT_Wformat_y2k,
2631 "%<%%%c%> yields only last 2 digits of "
2632 "year in some locales", format_char);
2633 else if (y2k_level == 2)
2634 warning_at (format_string_loc, OPT_Wformat_y2k,
2635 "%<%%%c%> yields only last 2 digits of year",
2636 format_char);
2637 }
2638
2639 /* Parse any "scan sets" enclosed in square brackets, e.g.
2640 for scanf-style calls. */
2641
2642 void
2643 argument_parser::parse_any_scan_set (const format_char_info *fci)
2644 {
2645 if (strchr (fci->flags2, '[') == NULL)
2646 return;
2647
2648 /* Skip over scan set, in case it happens to have '%' in it. */
2649 if (*format_chars == '^')
2650 ++format_chars;
2651 /* Find closing bracket; if one is hit immediately, then
2652 it's part of the scan set rather than a terminator. */
2653 if (*format_chars == ']')
2654 ++format_chars;
2655 while (*format_chars && *format_chars != ']')
2656 ++format_chars;
2657 if (*format_chars != ']')
2658 /* The end of the format string was reached. */
2659 format_warning_at_char (format_string_loc, format_string_cst,
2660 format_chars - orig_format_chars,
2661 OPT_Wformat_,
2662 "no closing %<]%> for %<%%[%> format");
2663 }
2664
2665 /* Return true if this argument is to be continued to be parsed,
2666 false to skip to next argument. */
2667
2668 bool
2669 argument_parser::handle_conversions (const format_char_info *fci,
2670 const length_modifier &len_modifier,
2671 tree &wanted_type,
2672 const char *&wanted_type_name,
2673 unsigned HOST_WIDE_INT &arg_num,
2674 tree &params,
2675 char format_char)
2676 {
2677 enum format_std_version wanted_type_std;
2678
2679 if (!(fki->flags & (int) FMT_FLAG_ARG_CONVERT))
2680 return true;
2681
2682 wanted_type = (fci->types[len_modifier.val].type
2683 ? *fci->types[len_modifier.val].type : 0);
2684 wanted_type_name = fci->types[len_modifier.val].name;
2685 wanted_type_std = fci->types[len_modifier.val].std;
2686 if (wanted_type == 0)
2687 {
2688 format_warning_at_char (format_string_loc, format_string_cst,
2689 format_chars - orig_format_chars,
2690 OPT_Wformat_,
2691 "use of %qs length modifier with %qc type"
2692 " character has either no effect"
2693 " or undefined behavior",
2694 len_modifier.chars, format_char);
2695 /* Heuristic: skip one argument when an invalid length/type
2696 combination is encountered. */
2697 arg_num++;
2698 if (params != 0)
2699 params = TREE_CHAIN (params);
2700 return false;
2701 }
2702 else if (pedantic
2703 /* Warn if non-standard, provided it is more non-standard
2704 than the length and type characters that may already
2705 have been warned for. */
2706 && ADJ_STD (wanted_type_std) > ADJ_STD (len_modifier.std)
2707 && ADJ_STD (wanted_type_std) > ADJ_STD (fci->std))
2708 {
2709 if (ADJ_STD (wanted_type_std) > C_STD_VER)
2710 format_warning_at_char (format_string_loc, format_string_cst,
2711 format_chars - orig_format_chars,
2712 OPT_Wformat_,
2713 "%s does not support the %<%%%s%c%> %s format",
2714 C_STD_NAME (wanted_type_std),
2715 len_modifier.chars,
2716 format_char, fki->name);
2717 }
2718
2719 return true;
2720 }
2721
2722 /* Check type of argument against desired type.
2723
2724 Return true if format parsing is to continue, false otherwise. */
2725
2726 bool
2727 argument_parser::
2728 check_argument_type (const format_char_info *fci,
2729 const length_modifier &len_modifier,
2730 tree &wanted_type,
2731 const char *&wanted_type_name,
2732 const bool suppressed,
2733 unsigned HOST_WIDE_INT &arg_num,
2734 tree &params,
2735 const int alloc_flag,
2736 const char * const format_start,
2737 const char * const type_start,
2738 location_t fmt_param_loc,
2739 char conversion_char)
2740 {
2741 if (info->first_arg_num == 0)
2742 return true;
2743
2744 if ((fci->pointer_count == 0 && wanted_type == void_type_node)
2745 || suppressed)
2746 {
2747 if (main_arg_num != 0)
2748 {
2749 if (suppressed)
2750 warning_at (format_string_loc, OPT_Wformat_,
2751 "operand number specified with "
2752 "suppressed assignment");
2753 else
2754 warning_at (format_string_loc, OPT_Wformat_,
2755 "operand number specified for format "
2756 "taking no argument");
2757 }
2758 }
2759 else
2760 {
2761 format_wanted_type *wanted_type_ptr;
2762
2763 if (main_arg_num != 0)
2764 {
2765 arg_num = main_arg_num;
2766 params = main_arg_params;
2767 }
2768 else
2769 {
2770 ++arg_num;
2771 if (has_operand_number > 0)
2772 {
2773 warning_at (format_string_loc, OPT_Wformat_,
2774 "missing $ operand number in format");
2775 return false;
2776 }
2777 else
2778 has_operand_number = 0;
2779 }
2780
2781 wanted_type_ptr = &main_wanted_type;
2782 while (fci)
2783 {
2784 tree cur_param;
2785 if (params == 0)
2786 cur_param = NULL;
2787 else
2788 {
2789 cur_param = TREE_VALUE (params);
2790 params = TREE_CHAIN (params);
2791 }
2792
2793 wanted_type_ptr->wanted_type = wanted_type;
2794 wanted_type_ptr->wanted_type_name = wanted_type_name;
2795 wanted_type_ptr->pointer_count = fci->pointer_count + alloc_flag;
2796 wanted_type_ptr->char_lenient_flag = 0;
2797 if (strchr (fci->flags2, 'c') != 0)
2798 wanted_type_ptr->char_lenient_flag = 1;
2799 wanted_type_ptr->scalar_identity_flag = 0;
2800 if (len_modifier.scalar_identity_flag)
2801 wanted_type_ptr->scalar_identity_flag = 1;
2802 wanted_type_ptr->writing_in_flag = 0;
2803 wanted_type_ptr->reading_from_flag = 0;
2804 if (alloc_flag)
2805 wanted_type_ptr->writing_in_flag = 1;
2806 else
2807 {
2808 if (strchr (fci->flags2, 'W') != 0)
2809 wanted_type_ptr->writing_in_flag = 1;
2810 if (strchr (fci->flags2, 'R') != 0)
2811 wanted_type_ptr->reading_from_flag = 1;
2812 }
2813 wanted_type_ptr->kind = CF_KIND_FORMAT;
2814 wanted_type_ptr->param = cur_param;
2815 wanted_type_ptr->arg_num = arg_num;
2816 wanted_type_ptr->format_start = format_start;
2817 wanted_type_ptr->format_length = format_chars - format_start;
2818 wanted_type_ptr->offset_loc = format_chars - orig_format_chars;
2819 wanted_type_ptr->next = NULL;
2820 if (last_wanted_type != 0)
2821 last_wanted_type->next = wanted_type_ptr;
2822 if (first_wanted_type == 0)
2823 first_wanted_type = wanted_type_ptr;
2824 last_wanted_type = wanted_type_ptr;
2825
2826 fci = fci->chain;
2827 if (fci)
2828 {
2829 wanted_type_ptr = fwt_pool.allocate ();
2830 arg_num++;
2831 wanted_type = *fci->types[len_modifier.val].type;
2832 wanted_type_name = fci->types[len_modifier.val].name;
2833 }
2834 }
2835 }
2836
2837 if (first_wanted_type != 0)
2838 {
2839 ptrdiff_t offset_to_format_start = (start_of_this_format - 1) - orig_format_chars;
2840 ptrdiff_t offset_to_format_end = (format_chars - 1) - orig_format_chars;
2841 /* By default, use the end of the range for the caret location. */
2842 substring_loc fmt_loc (fmt_param_loc, TREE_TYPE (format_string_cst),
2843 offset_to_format_end,
2844 offset_to_format_start, offset_to_format_end);
2845 ptrdiff_t offset_to_type_start = type_start - orig_format_chars;
2846 check_format_types (fmt_loc, first_wanted_type, fki,
2847 offset_to_type_start,
2848 conversion_char, arglocs);
2849 }
2850
2851 return true;
2852 }
2853
2854 /* Describes "paired tokens" within the format string that are
2855 expected to be balanced. */
2856
2857 class baltoks_t
2858 {
2859 public:
2860 baltoks_t (): singlequote (), doublequote () { }
2861
2862 typedef auto_vec<const char *> balanced_tokens_t;
2863 /* Vectors of pointers to opening brackets ('['), curly brackets ('{'),
2864 quoting directives (like GCC "%<"), parentheses, and angle brackets
2865 ('<'). Used to detect unbalanced tokens. */
2866 balanced_tokens_t brackets;
2867 balanced_tokens_t curly;
2868 balanced_tokens_t quotdirs;
2869 balanced_tokens_t parens;
2870 balanced_tokens_t pointy;
2871 /* Pointer to the last opening quote. */
2872 const char *singlequote;
2873 const char *doublequote;
2874 };
2875
2876 /* Describes a keyword, operator, or other name. */
2877
2878 struct token_t
2879 {
2880 const char *name; /* Keyword/operator name. */
2881 unsigned char len; /* Its length. */
2882 const char *alt; /* Alternate spelling. */
2883 };
2884
2885 /* Helper for initializing global token_t arrays below. */
2886 #define NAME(name) { name, sizeof name - 1, NULL }
2887
2888 /* C/C++ operators that are expected to be quoted within the format
2889 string. */
2890
2891 static const token_t c_opers[] =
2892 {
2893 NAME ("!="), NAME ("%="), NAME ("&&"), NAME ("&="), NAME ("*="),
2894 NAME ("++"), NAME ("+="), NAME ("--"), NAME ("-="), NAME ("->"),
2895 NAME ("/="), NAME ("<<"), NAME ("<<="), NAME ("<="), NAME ("=="),
2896 NAME (">="), NAME (">>="), NAME (">>"), NAME ("?:"), NAME ("^="),
2897 NAME ("|="), NAME ("||")
2898 };
2899
2900 static const token_t cxx_opers[] =
2901 {
2902 NAME ("->*"), NAME (".*"), NAME ("::"), NAME ("<=>")
2903 };
2904
2905 /* Common C/C++ keywords that are expected to be quoted within the format
2906 string. Keywords like auto, inline, or volatile are exccluded because
2907 they are sometimes used in common terms like /auto variables/, /inline
2908 function/, or /volatile access/ where they should not be quoted. */
2909
2910 static const token_t c_keywords[] =
2911 {
2912 #undef NAME
2913 #define NAME(name, alt) { name, sizeof name - 1, alt }
2914
2915 NAME ("alignas", NULL),
2916 NAME ("alignof", NULL),
2917 NAME ("asm", NULL),
2918 NAME ("bool", NULL),
2919 NAME ("char", NULL),
2920 NAME ("const %", NULL),
2921 NAME ("const-qualified", "%<const%>-qualified"),
2922 NAME ("float", NULL),
2923 NAME ("ifunc", NULL),
2924 NAME ("int", NULL),
2925 NAME ("long double", NULL),
2926 NAME ("long int", NULL),
2927 NAME ("long long", NULL),
2928 NAME ("malloc", NULL),
2929 NAME ("noclone", NULL),
2930 NAME ("noinline", NULL),
2931 NAME ("nonnull", NULL),
2932 NAME ("noreturn", NULL),
2933 NAME ("nothrow", NULL),
2934 NAME ("offsetof", NULL),
2935 NAME ("readonly", "read-only"),
2936 NAME ("readwrite", "read-write"),
2937 NAME ("restrict %", NULL),
2938 NAME ("restrict-qualified", "%<restrict%>-qualified"),
2939 NAME ("short int", NULL),
2940 NAME ("signed char", NULL),
2941 NAME ("signed int", NULL),
2942 NAME ("signed long", NULL),
2943 NAME ("signed short", NULL),
2944 NAME ("sizeof", NULL),
2945 NAME ("typeof", NULL),
2946 NAME ("unsigned char", NULL),
2947 NAME ("unsigned int", NULL),
2948 NAME ("unsigned long", NULL),
2949 NAME ("unsigned short", NULL),
2950 NAME ("volatile %", NULL),
2951 NAME ("volatile-qualified", "%<volatile%>-qualified"),
2952 NAME ("weakref", NULL),
2953 };
2954
2955 static const token_t cxx_keywords[] =
2956 {
2957 /* C++ only keywords and operators. */
2958 NAME ("catch", NULL),
2959 NAME ("constexpr if", NULL),
2960 NAME ("constexpr", NULL),
2961 NAME ("consteval", NULL),
2962 NAME ("decltype", NULL),
2963 NAME ("nullptr", NULL),
2964 NAME ("operator delete", NULL),
2965 NAME ("operator new", NULL),
2966 NAME ("typeid", NULL),
2967 NAME ("typeinfo", NULL)
2968 };
2969
2970 /* Blacklisted words such as misspellings that should be avoided in favor
2971 of the specified alternatives. */
2972 static const struct
2973 {
2974 const char *name; /* Bad word. */
2975 unsigned char len; /* Its length. */
2976 const char *alt; /* Preferred alternative. */
2977 } badwords[] =
2978 {
2979 NAME ("arg", "argument"),
2980 NAME ("bitfield", "bit-field"),
2981 NAME ("builtin function", "built-in function"),
2982 NAME ("can not", "cannot"),
2983 NAME ("commandline option", "command-line option"),
2984 NAME ("commandline", "command line"),
2985 NAME ("command line option", "command-line option"),
2986 NAME ("decl", "declaration"),
2987 NAME ("enumeral", "enumerated"),
2988 NAME ("floating point", "floating-point"),
2989 NAME ("non-zero", "nonzero"),
2990 NAME ("reg", "register"),
2991 NAME ("stmt", "statement"),
2992 };
2993
2994 /* Common contractions that should be avoided in favor of the specified
2995 alternatives. */
2996
2997 static const struct
2998 {
2999 const char *name; /* Contraction. */
3000 unsigned char len; /* Its length. */
3001 const char *alt; /* Preferred alternative. */
3002 } contrs[] =
3003 {
3004 NAME ("can't", "cannot"),
3005 NAME ("didn't", "did not"),
3006 /* These are commonly abused. Avoid diagnosing them for now.
3007 NAME ("isn't", "is not"),
3008 NAME ("don't", "is not"),
3009 */
3010 NAME ("mustn't", "must not"),
3011 NAME ("needn't", "need not"),
3012 NAME ("should't", "should not"),
3013 NAME ("that's", "that is"),
3014 NAME ("there's", "there is"),
3015 NAME ("they're", "they are"),
3016 NAME ("what's", "what is"),
3017 NAME ("won't", "will not")
3018 };
3019
3020 /* Check for unquoted TOKENS. FORMAT_STRING_LOC is the location of
3021 the format string, FORMAT_STRING_CST the format string itself (as
3022 a tree), ORIG_FORMAT_CHARS and FORMAT_CHARS are pointers to
3023 the beginning of the format string and the character currently
3024 being processed, and BALTOKS describes paired "tokens" within
3025 the format string that are expected to be balanced.
3026 Returns a pointer to the last processed character or null when
3027 nothing was done. */
3028
3029 static const char*
3030 check_tokens (const token_t *tokens, unsigned ntoks,
3031 location_t format_string_loc, tree format_string_cst,
3032 const char *orig_format_chars, const char *format_chars,
3033 baltoks_t &baltoks)
3034 {
3035 /* For brevity. */
3036 const int opt = OPT_Wformat_diag;
3037 /* Zero-based starting position of a problem sequence. */
3038 int fmtchrpos = format_chars - orig_format_chars;
3039
3040 /* For identifier-like "words," set to the word length. */
3041 unsigned wlen = 0;
3042 /* Set for an operator, clear for an identifier/word. */
3043 bool is_oper = false;
3044 bool underscore = false;
3045
3046 if (format_chars[0] == '_' || ISALPHA (format_chars[0]))
3047 {
3048 while (format_chars[wlen] == '_' || ISALNUM (format_chars[wlen]))
3049 {
3050 underscore |= format_chars[wlen] == '_';
3051 ++wlen;
3052 }
3053 }
3054 else
3055 is_oper = true;
3056
3057 for (unsigned i = 0; i != ntoks; ++i)
3058 {
3059 unsigned toklen = tokens[i].len;
3060
3061 if (toklen < wlen
3062 || strncmp (format_chars, tokens[i].name, toklen))
3063 continue;
3064
3065 if (toklen == 2
3066 && format_chars - orig_format_chars > 0
3067 && (TOUPPER (format_chars[-1]) == 'C'
3068 || TOUPPER (format_chars[-1]) == 'G'))
3069 return format_chars + toklen - 1; /* Reference to C++ or G++. */
3070
3071 if (ISPUNCT (format_chars[toklen - 1]))
3072 {
3073 if (format_chars[toklen - 1] == format_chars[toklen])
3074 return NULL; /* Operator followed by another punctuator. */
3075 }
3076 else if (ISALNUM (format_chars[toklen]))
3077 return NULL; /* Keyword prefix for a longer word. */
3078
3079 if (toklen == 2
3080 && format_chars[0] == '-'
3081 && format_chars[1] == '-'
3082 && ISALNUM (format_chars[2]))
3083 return NULL; /* Probably option like --help. */
3084
3085 /* Allow this ugly warning for the time being. */
3086 if (toklen == 2
3087 && format_chars - orig_format_chars > 6
3088 && !strncmp (format_chars - 7, " count >= width of ", 19))
3089 return format_chars + 10;
3090
3091 /* The token is a type if it ends in an alphabetic character. */
3092 bool is_type = (ISALPHA (tokens[i].name[toklen - 1])
3093 && strchr (tokens[i].name, ' '));
3094
3095 /* Backtrack to the last alphabetic character (for tokens whose
3096 names end in '%'). */
3097 if (!is_oper)
3098 while (!ISALPHA (tokens[i].name[toklen - 1]))
3099 --toklen;
3100
3101 if (format_warning_substr (format_string_loc, format_string_cst,
3102 fmtchrpos, fmtchrpos + toklen, opt,
3103 (is_type
3104 ? G_("unquoted type name %<%.*s%> in format")
3105 : (is_oper
3106 ? G_("unquoted operator %<%.*s%> in format")
3107 : G_("unquoted keyword %<%.*s%> in format"))),
3108 toklen, format_chars)
3109 && tokens[i].alt)
3110 inform (format_string_loc, "use %qs instead", tokens[i].alt);
3111
3112 return format_chars + toklen - 1;
3113 }
3114
3115 /* Diagnose unquoted __attribute__. Consider any parenthesized
3116 argument to the attribute to avoid redundant warnings for
3117 the double parentheses that might follow. */
3118 if (!strncmp (format_chars, "__attribute", sizeof "__attribute" - 1))
3119 {
3120 unsigned nchars = sizeof "__attribute" - 1;
3121 while ('_' == format_chars[nchars])
3122 ++nchars;
3123
3124 for (int i = nchars; format_chars[i]; ++i)
3125 if (' ' != format_chars[i])
3126 {
3127 nchars = i;
3128 break;
3129 }
3130
3131 if (format_chars[nchars] == '(')
3132 {
3133 baltoks.parens.safe_push (format_chars + nchars);
3134
3135 ++nchars;
3136 bool close = false;
3137 if (format_chars[nchars] == '(')
3138 {
3139 baltoks.parens.safe_push (format_chars + nchars);
3140 close = true;
3141 ++nchars;
3142 }
3143 for (int i = nchars; format_chars[i]; ++i)
3144 if (')' == format_chars[i])
3145 {
3146 if (baltoks.parens.length () > 0)
3147 baltoks.parens.pop ();
3148 nchars = i + 1;
3149 break;
3150 }
3151
3152 if (close && format_chars[nchars] == ')')
3153 {
3154 if (baltoks.parens.length () > 0)
3155 baltoks.parens.pop ();
3156 ++nchars;
3157 }
3158 }
3159
3160 format_warning_substr (format_string_loc, format_string_cst,
3161 fmtchrpos, fmtchrpos + nchars, opt,
3162 "unquoted attribute in format");
3163 return format_chars + nchars - 1;
3164 }
3165
3166 /* Diagnose unquoted built-ins. */
3167 if (format_chars[0] == '_'
3168 && format_chars[1] == '_'
3169 && (!strncmp (format_chars + 2, "atomic", sizeof "atomic" - 1)
3170 || !strncmp (format_chars + 2, "builtin", sizeof "builtin" - 1)
3171 || !strncmp (format_chars + 2, "sync", sizeof "sync" - 1)))
3172 {
3173 format_warning_substr (format_string_loc, format_string_cst,
3174 fmtchrpos, fmtchrpos + wlen, opt,
3175 "unquoted name of built-in function %<%.*s%> "
3176 "in format",
3177 wlen, format_chars);
3178 return format_chars + wlen - 1;
3179 }
3180
3181 /* Diagnose unquoted substrings of alphanumeric characters containing
3182 underscores. They most likely refer to identifiers and should be
3183 quoted. */
3184 if (underscore)
3185 format_warning_substr (format_string_loc, format_string_cst,
3186 format_chars - orig_format_chars,
3187 format_chars + wlen - orig_format_chars,
3188 opt,
3189 "unquoted identifier or keyword %<%.*s%> in format",
3190 wlen, format_chars);
3191 else
3192 {
3193 /* Diagnose some common missspellings. */
3194 for (unsigned i = 0; i != sizeof badwords / sizeof *badwords; ++i)
3195 {
3196 unsigned badwlen = strspn (badwords[i].name, " -");
3197 if (wlen >= badwlen
3198 && (wlen <= badwords[i].len
3199 || (wlen == badwords[i].len + 1U
3200 && TOUPPER (format_chars[wlen - 1]) == 'S'))
3201 && !strncasecmp (format_chars, badwords[i].name, badwords[i].len))
3202 {
3203 /* Handle singular as well as plural forms of all bad words
3204 even though the latter don't necessarily make sense for
3205 all of the former (like "can nots"). */
3206 badwlen = badwords[i].len;
3207 const char *plural = "";
3208 if (TOUPPER (format_chars[badwlen]) == 'S')
3209 {
3210 ++badwlen;
3211 plural = "s";
3212 }
3213
3214 format_warning_substr (format_string_loc, format_string_cst,
3215 fmtchrpos, fmtchrpos + badwords[i].len,
3216 opt,
3217 "misspelled term %<%.*s%> in format; "
3218 "use %<%s%s%> instead",
3219 badwlen, format_chars,
3220 badwords[i].alt, plural);
3221
3222 return format_chars + badwords[i].len - 1;
3223 }
3224 }
3225
3226 /* Skip C++/G++. */
3227 if (!strncasecmp (format_chars, "c++", 3)
3228 || !strncasecmp (format_chars, "g++", 3))
3229 return format_chars + 2;
3230 }
3231
3232 return wlen ? format_chars + wlen - 1 : NULL;
3233 }
3234
3235 /* Check plain text in a format string of a GCC diagnostic function
3236 for common quoting, punctuation, and spelling mistakes, and issue
3237 -Wformat-diag warnings if they are found. FORMAT_STRING_LOC is
3238 the location of the format string, FORMAT_STRING_CST the format
3239 string itself (as a tree), ORIG_FORMAT_CHARS and FORMAT_CHARS are
3240 pointers to the beginning of the format string and the character
3241 currently being processed, and BALTOKS describes paired "tokens"
3242 within the format string that are expected to be balanced.
3243 Returns a pointer to the last processed character. */
3244
3245 static const char*
3246 check_plain (location_t format_string_loc, tree format_string_cst,
3247 const char *orig_format_chars, const char *format_chars,
3248 baltoks_t &baltoks)
3249 {
3250 /* For brevity. */
3251 const int opt = OPT_Wformat_diag;
3252 /* Zero-based starting position of a problem sequence. */
3253 int fmtchrpos = format_chars - orig_format_chars;
3254
3255 if (*format_chars == '%')
3256 {
3257 /* Diagnose %<%s%> and suggest using %qs instead. */
3258 if (!strncmp (format_chars, "%<%s%>", 6))
3259 format_warning_substr (format_string_loc, format_string_cst,
3260 fmtchrpos, fmtchrpos + 6, opt,
3261 "quoted %qs directive in format; "
3262 "use %qs instead", "%s", "%qs");
3263 else if (format_chars - orig_format_chars > 2
3264 && !strncasecmp (format_chars - 3, "can%'t", 5)
3265 && !ISALPHA (format_chars[1]))
3266 format_warning_substr (format_string_loc,
3267 format_string_cst,
3268 fmtchrpos - 3, fmtchrpos + 3, opt,
3269 "contraction %<%.*s%> in format; "
3270 "use %qs instead",
3271 6, format_chars - 3, "cannot");
3272
3273 return format_chars;
3274 }
3275
3276 if (baltoks.quotdirs.length ())
3277 {
3278 /* Skip over all plain text within a quoting directive until
3279 the next directive. */
3280 while (*format_chars && '%' != *format_chars)
3281 ++format_chars;
3282
3283 return format_chars;
3284 }
3285
3286 /* The length of the problem sequence. */
3287 int nchars = 0;
3288
3289 /* Diagnose any whitespace characters other than <space> but only
3290 leading, trailing, and two or more consecutive <space>s. Do
3291 this before diagnosing control characters because whitespace
3292 is a subset of controls. */
3293 const char *other_than_space = NULL;
3294 while (ISSPACE (format_chars[nchars]))
3295 {
3296 if (format_chars[nchars] != ' ' && !other_than_space)
3297 other_than_space = format_chars + nchars;
3298 ++nchars;
3299 }
3300
3301 if (nchars)
3302 {
3303 /* This is the most common problem: go the extra mile to describe
3304 the problem in as much helpful detail as possible. */
3305 if (other_than_space)
3306 {
3307 format_warning_substr (format_string_loc, format_string_cst,
3308 fmtchrpos, fmtchrpos + nchars, opt,
3309 "unquoted whitespace character %qc in format",
3310 *other_than_space);
3311 return format_chars + nchars - 1;
3312 }
3313
3314 if (fmtchrpos == 0)
3315 /* Accept strings of leading spaces with no warning. */
3316 return format_chars + nchars - 1;
3317
3318 if (!format_chars[nchars])
3319 {
3320 format_warning_substr (format_string_loc, format_string_cst,
3321 fmtchrpos, fmtchrpos + nchars, opt,
3322 "spurious trailing space in format");
3323 return format_chars + nchars - 1;
3324 }
3325
3326 if (nchars > 1)
3327 {
3328 if (nchars == 2
3329 && orig_format_chars < format_chars
3330 && format_chars[-1] == '.'
3331 && format_chars[0] == ' '
3332 && format_chars[1] == ' ')
3333 {
3334 /* A period followed by two spaces. */
3335 if (ISUPPER (*orig_format_chars))
3336 {
3337 /* If the part before the period is a capitalized
3338 sentence check to make sure that what follows
3339 is also capitalized. */
3340 if (ISLOWER (format_chars[2]))
3341 format_warning_substr (format_string_loc, format_string_cst,
3342 fmtchrpos, fmtchrpos + nchars, opt,
3343 "inconsistent capitalization in "
3344 "format");
3345 }
3346 }
3347 else
3348 format_warning_substr (format_string_loc, format_string_cst,
3349 fmtchrpos, fmtchrpos + nchars, opt,
3350 "unquoted sequence of %i consecutive "
3351 "space characters in format", nchars);
3352 return format_chars + nchars - 1;
3353 }
3354
3355 format_chars += nchars;
3356 nchars = 0;
3357 }
3358
3359 fmtchrpos = format_chars - orig_format_chars;
3360
3361 /* Diagnose any unquoted control characters other than the terminating
3362 NUL. */
3363 while (format_chars[nchars] && ISCNTRL (format_chars[nchars]))
3364 ++nchars;
3365
3366 if (nchars > 1)
3367 {
3368 format_warning_substr (format_string_loc, format_string_cst,
3369 fmtchrpos, fmtchrpos + nchars, opt,
3370 "unquoted control characters in format");
3371 return format_chars + nchars - 1;
3372 }
3373 if (nchars)
3374 {
3375 format_warning_substr (format_string_loc, format_string_cst,
3376 fmtchrpos, fmtchrpos + nchars, opt,
3377 "unquoted control character %qc in format",
3378 *format_chars);
3379 return format_chars + nchars - 1;
3380 }
3381
3382 if (ISPUNCT (format_chars[0]))
3383 {
3384 size_t nelts = sizeof c_opers / sizeof *c_opers;
3385 if (const char *ret = check_tokens (c_opers, nelts,
3386 format_string_loc, format_string_cst,
3387 orig_format_chars, format_chars,
3388 baltoks))
3389 return ret;
3390
3391 nelts = c_dialect_cxx () ? sizeof cxx_opers / sizeof *cxx_opers : 0;
3392 if (const char *ret = check_tokens (cxx_opers, nelts,
3393 format_string_loc, format_string_cst,
3394 orig_format_chars, format_chars,
3395 baltoks))
3396 return ret;
3397 }
3398
3399 if (ISALPHA (format_chars[0]))
3400 {
3401 size_t nelts = sizeof c_keywords / sizeof *c_keywords;
3402 if (const char *ret = check_tokens (c_keywords, nelts,
3403 format_string_loc, format_string_cst,
3404 orig_format_chars, format_chars,
3405 baltoks))
3406 return ret;
3407
3408 nelts = c_dialect_cxx () ? sizeof cxx_keywords / sizeof *cxx_keywords : 0;
3409 if (const char *ret = check_tokens (cxx_keywords, nelts,
3410 format_string_loc, format_string_cst,
3411 orig_format_chars, format_chars,
3412 baltoks))
3413 return ret;
3414 }
3415
3416 nchars = 0;
3417
3418 /* Diagnose unquoted options. */
3419 if ((format_chars == orig_format_chars
3420 || format_chars[-1] == ' ')
3421 && format_chars[0] == '-'
3422 && ((format_chars[1] == '-'
3423 && ISALPHA (format_chars[2]))
3424 || ISALPHA (format_chars[1])))
3425 {
3426 nchars = 1;
3427 while (ISALNUM (format_chars[nchars])
3428 || '_' == format_chars[nchars]
3429 || '-' == format_chars[nchars]
3430 || '+' == format_chars[nchars])
3431 ++nchars;
3432
3433 format_warning_substr (format_string_loc, format_string_cst,
3434 fmtchrpos, fmtchrpos + nchars, opt,
3435 "unquoted option name %<%.*s%> in format",
3436 nchars, format_chars);
3437 return format_chars + nchars - 1;
3438 }
3439
3440 /* Diagnose leading, trailing, and two or more consecutive punctuation
3441 characters. */
3442 const char *unbalanced = NULL;
3443 while ('%' != format_chars[nchars]
3444 && ISPUNCT (format_chars[nchars])
3445 && !unbalanced)
3446 {
3447 switch (format_chars[nchars])
3448 {
3449 case '[':
3450 baltoks.brackets.safe_push (format_chars + nchars);
3451 break;
3452 case '{':
3453 baltoks.curly.safe_push (format_chars + nchars);
3454 break;
3455 case '(':
3456 baltoks.parens.safe_push (format_chars + nchars);
3457 break;
3458 case '<':
3459 baltoks.pointy.safe_push (format_chars + nchars);
3460 break;
3461
3462 case ']':
3463 if (baltoks.brackets.length () > 0)
3464 baltoks.brackets.pop ();
3465 else
3466 unbalanced = format_chars + nchars;
3467 break;
3468 case '}':
3469 if (baltoks.curly.length () > 0)
3470 baltoks.curly.pop ();
3471 else
3472 unbalanced = format_chars + nchars;
3473 break;
3474 case ')':
3475 if (baltoks.parens.length () > 0)
3476 baltoks.parens.pop ();
3477 else
3478 unbalanced = format_chars + nchars;
3479 break;
3480 case '>':
3481 if (baltoks.pointy.length () > 0)
3482 baltoks.pointy.pop ();
3483 else
3484 unbalanced = format_chars + nchars;
3485 break;
3486 }
3487
3488 ++nchars;
3489 }
3490
3491 if (unbalanced)
3492 {
3493 format_warning_substr (format_string_loc, format_string_cst,
3494 fmtchrpos, fmtchrpos + nchars, opt,
3495 "unbalanced punctuation character %qc in format",
3496 *unbalanced);
3497 return format_chars + nchars - 1;
3498 }
3499
3500 if (nchars)
3501 {
3502 /* Consider any identifier that follows the pound ('#') sign
3503 a preprocessing directive. */
3504 if (nchars == 1
3505 && format_chars[0] == '#'
3506 && ISALPHA (format_chars[1]))
3507 {
3508 while (ISALNUM (format_chars[nchars])
3509 || format_chars[nchars] == '_')
3510 ++nchars;
3511
3512 format_warning_substr (format_string_loc, format_string_cst,
3513 fmtchrpos, fmtchrpos + nchars, opt,
3514 "unquoted preprocessing directive %<%.*s%> "
3515 "in format", nchars, format_chars);
3516 return format_chars + nchars - 1;
3517 }
3518
3519 /* Diagnose a bare single quote. */
3520 if (nchars == 1
3521 && format_chars[0] == '\''
3522 && format_chars - orig_format_chars
3523 && ISALPHA (format_chars[-1])
3524 && ISALPHA (format_chars[1]))
3525 {
3526 /* Diagnose a subset of contractions that are best avoided. */
3527 for (unsigned i = 0; i != sizeof contrs / sizeof *contrs; ++i)
3528 {
3529 const char *apos = strchr (contrs[i].name, '\'');
3530 gcc_assert (apos != NULL);
3531 int off = apos - contrs[i].name;
3532
3533 if (format_chars - orig_format_chars >= off
3534 && !strncmp (format_chars - off,
3535 contrs[i].name, contrs[i].len))
3536 {
3537 format_warning_substr (format_string_loc,
3538 format_string_cst,
3539 fmtchrpos, fmtchrpos + nchars, opt,
3540 "contraction %<%.*s%> in format; "
3541 "use %qs instead",
3542 contrs[i].len, contrs[i].name,
3543 contrs[i].alt);
3544 return format_chars + nchars - 1;
3545 }
3546 }
3547
3548 if (format_warning_substr (format_string_loc, format_string_cst,
3549 fmtchrpos, fmtchrpos + nchars, opt,
3550 "bare apostrophe %<'%> in format"))
3551 inform (format_string_loc,
3552 "if avoiding the apostrophe is not feasible, enclose "
3553 "it in a pair of %qs and %qs directives instead",
3554 "%<", "%>");
3555 return format_chars + nchars - 1;
3556 }
3557
3558 /* Diagnose a backtick (grave accent). */
3559 if (nchars == 1
3560 && format_chars[0] == '`')
3561 {
3562 if (format_warning_substr (format_string_loc, format_string_cst,
3563 fmtchrpos, fmtchrpos + nchars, opt,
3564 "grave accent %<`%> in format"))
3565 inform (format_string_loc,
3566 "use the apostrophe directive %qs instead", "%'");
3567 return format_chars + nchars - 1;
3568 }
3569
3570 /* Diagnose a punctuation character after a space. */
3571 if (nchars == 1
3572 && format_chars - orig_format_chars
3573 && format_chars[-1] == ' '
3574 && strspn (format_chars, "!?:;.,") == 1)
3575 {
3576 format_warning_substr (format_string_loc, format_string_cst,
3577 fmtchrpos - 1, fmtchrpos, opt,
3578 "space followed by punctuation character "
3579 "%<%c%>", format_chars[0]);
3580 return format_chars;
3581 }
3582
3583 if (nchars == 1)
3584 {
3585 if (!strncmp (format_chars, "\"%s\"", 4))
3586 {
3587 if (format_warning_substr (format_string_loc, format_string_cst,
3588 fmtchrpos, fmtchrpos + 4, opt,
3589 "quoted %qs directive in format",
3590 "%s"))
3591 inform (format_string_loc, "if using %qs is not feasible, "
3592 "use %qs instead", "%qs", "\"%-s\"");
3593 }
3594
3595 if (format_chars[0] == '"')
3596 {
3597 baltoks.doublequote = baltoks.doublequote ? NULL : format_chars;
3598 return format_chars + nchars - 1;
3599 }
3600 if (format_chars[0] == '\'')
3601 {
3602 baltoks.singlequote = baltoks.singlequote ? NULL : format_chars;
3603 return format_chars + nchars - 1;
3604 }
3605 }
3606
3607 if (fmtchrpos == 0)
3608 {
3609 if (nchars == 1
3610 && format_chars[0] == '(')
3611 ; /* Text beginning in an open parenthesis. */
3612 else if (nchars == 3
3613 && !strncmp (format_chars, "...", 3)
3614 && format_chars[3])
3615 ; /* Text beginning in an ellipsis. */
3616 else
3617 {
3618 format_warning_substr (format_string_loc, format_string_cst,
3619 fmtchrpos, fmtchrpos + nchars, opt,
3620 "spurious leading punctuation sequence "
3621 "%<%.*s%> in format",
3622 nchars, format_chars);
3623 return format_chars + nchars - 1;
3624 }
3625 }
3626 else if (!format_chars[nchars])
3627 {
3628 if (nchars == 1
3629 && (format_chars[nchars - 1] == ':'
3630 || format_chars[nchars - 1] == ')'))
3631 ; /* Text ending in a colon or a closing parenthesis. */
3632 else if (nchars == 1
3633 && ((ISUPPER (*orig_format_chars)
3634 && format_chars[nchars - 1] == '.')
3635 || strspn (format_chars + nchars - 1, "?])") == 1))
3636 ; /* Capitalized sentence terminated by a single period,
3637 or text ending in a question mark, closing bracket,
3638 or parenthesis. */
3639 else if (nchars == 2
3640 && format_chars[0] == '?'
3641 && format_chars[1] == ')')
3642 ; /* A question mark after a closing parenthetical note. */
3643 else if (nchars == 2
3644 && format_chars[0] == ')'
3645 && (format_chars[1] == '?'
3646 || format_chars[1] == ';'
3647 || format_chars[1] == ':'
3648 || (ISUPPER (*orig_format_chars)
3649 && format_chars[1] == '.')))
3650 ; /* Closing parenthetical note followed by a question mark,
3651 semicolon, or colon at the end of the string, or by
3652 a period at the end of a capitalized sentence. */
3653 else if (nchars == 3
3654 && format_chars - orig_format_chars > 0
3655 && !strncmp (format_chars, "...", 3))
3656 ; /* Text ending in the ellipsis. */
3657 else
3658 format_warning_substr (format_string_loc, format_string_cst,
3659 fmtchrpos, fmtchrpos + nchars, opt,
3660 "spurious trailing punctuation sequence "
3661 "%<%.*s%> in format",
3662 nchars, format_chars);
3663
3664 return format_chars + nchars - 1;
3665 }
3666 else if (nchars == 2
3667 && format_chars[0] == ')'
3668 && (format_chars[1] == ':'
3669 || format_chars[1] == ';'
3670 || format_chars[1] == ',')
3671 && format_chars[2] == ' ')
3672 ; /* Closing parenthetical note followed by a colon, semicolon
3673 or a comma followed by a space in the middle of the string. */
3674 else if (nchars > 1)
3675 format_warning_substr (format_string_loc, format_string_cst,
3676 fmtchrpos, fmtchrpos + nchars, opt,
3677 "unquoted sequence of %i consecutive "
3678 "punctuation characters %q.*s in format",
3679 nchars, nchars, format_chars);
3680 return format_chars + nchars - 1;
3681 }
3682
3683 nchars = 0;
3684
3685 /* Finally, diagnose any unquoted non-graph, non-punctuation characters
3686 other than the terminating NUL. */
3687 while (format_chars[nchars]
3688 && '%' != format_chars[nchars]
3689 && !ISPUNCT (format_chars[nchars])
3690 && !ISGRAPH (format_chars[nchars]))
3691 ++nchars;
3692
3693 if (nchars > 1)
3694 {
3695 format_warning_substr (format_string_loc, format_string_cst,
3696 fmtchrpos, fmtchrpos + nchars, opt,
3697 "unquoted non-graph characters in format");
3698 return format_chars + nchars - 1;
3699 }
3700 if (nchars)
3701 {
3702 format_warning_substr (format_string_loc, format_string_cst,
3703 fmtchrpos, fmtchrpos + nchars, opt,
3704 "unquoted non-graph character %qc in format",
3705 *format_chars);
3706 return format_chars + nchars - 1;
3707 }
3708
3709 return format_chars;
3710 }
3711
3712 /* Diagnose unbalanced tokens described by BALTOKS in format string
3713 ORIG_FORMAT_CHARS and the corresponding FORMAT_STRING_CST. */
3714
3715 static void
3716 maybe_diag_unbalanced_tokens (location_t format_string_loc,
3717 const char *orig_format_chars,
3718 tree format_string_cst,
3719 baltoks_t &baltoks)
3720 {
3721 const char *unbalanced = NULL;
3722
3723 if (baltoks.brackets.length ())
3724 unbalanced = baltoks.brackets.pop ();
3725 else if (baltoks.curly.length ())
3726 unbalanced = baltoks.curly.pop ();
3727 else if (baltoks.parens.length ())
3728 unbalanced = baltoks.parens.pop ();
3729 else if (baltoks.pointy.length ())
3730 unbalanced = baltoks.pointy.pop ();
3731
3732 if (unbalanced)
3733 format_warning_at_char (format_string_loc, format_string_cst,
3734 unbalanced - orig_format_chars + 1,
3735 OPT_Wformat_diag,
3736 "unbalanced punctuation character %<%c%> in format",
3737 *unbalanced);
3738
3739 if (baltoks.quotdirs.length ())
3740 format_warning_at_char (format_string_loc, format_string_cst,
3741 baltoks.quotdirs.pop () - orig_format_chars,
3742 OPT_Wformat_,
3743 "unterminated quoting directive");
3744
3745 const char *quote
3746 = baltoks.singlequote ? baltoks.singlequote : baltoks.doublequote;
3747
3748 if (quote)
3749 format_warning_at_char (format_string_loc, format_string_cst,
3750 quote - orig_format_chars + 1,
3751 OPT_Wformat_diag,
3752 "unterminated quote character %<%c%> in format",
3753 *quote);
3754 }
3755
3756 /* Do the main part of checking a call to a format function. FORMAT_CHARS
3757 is the NUL-terminated format string (which at this point may contain
3758 internal NUL characters); FORMAT_LENGTH is its length (excluding the
3759 terminating NUL character). ARG_NUM is one less than the number of
3760 the first format argument to check; PARAMS points to that format
3761 argument in the list of arguments. */
3762
3763 static void
3764 check_format_info_main (format_check_results *res,
3765 function_format_info *info, const char *format_chars,
3766 location_t fmt_param_loc, tree format_string_cst,
3767 int format_length, tree params,
3768 unsigned HOST_WIDE_INT arg_num,
3769 object_allocator <format_wanted_type> &fwt_pool,
3770 vec<location_t> *arglocs)
3771 {
3772 const char * const orig_format_chars = format_chars;
3773 const tree first_fillin_param = params;
3774
3775 const format_kind_info * const fki = &format_types[info->format_type];
3776 const format_flag_spec * const flag_specs = fki->flag_specs;
3777 const location_t format_string_loc = res->format_string_loc;
3778
3779 /* -1 if no conversions taking an operand have been found; 0 if one has
3780 and it didn't use $; 1 if $ formats are in use. */
3781 int has_operand_number = -1;
3782
3783 /* Vectors of pointers to opening quoting directives (like GCC "%<"),
3784 opening braces, brackets, and parentheses. Used to detect unbalanced
3785 tokens. */
3786 baltoks_t baltoks;
3787
3788 /* Pointers to the most recent color directives (like GCC's "%r or %R").
3789 A starting color directive much be terminated before the end of
3790 the format string. A terminating directive makes no sense without
3791 a prior starting directive. */
3792 const char *color_begin = NULL;
3793 const char *color_end = NULL;
3794
3795 init_dollar_format_checking (info->first_arg_num, first_fillin_param);
3796
3797 /* In GCC diagnostic functions check plain directives (substrings within
3798 the format string that don't start with %) for quoting and punctuations
3799 problems. */
3800 bool ck_plain = (!info->is_raw
3801 && (info->format_type == gcc_diag_format_type
3802 || info->format_type == gcc_tdiag_format_type
3803 || info->format_type == gcc_cdiag_format_type
3804 || info->format_type == gcc_cxxdiag_format_type));
3805
3806 while (*format_chars != 0)
3807 {
3808 if (ck_plain)
3809 format_chars = check_plain (format_string_loc,
3810 format_string_cst,
3811 orig_format_chars, format_chars,
3812 baltoks);
3813
3814 if (*format_chars == 0 || *format_chars++ != '%')
3815 continue;
3816
3817 if (*format_chars == 0)
3818 {
3819 format_warning_at_char (format_string_loc, format_string_cst,
3820 format_chars - orig_format_chars,
3821 OPT_Wformat_,
3822 "spurious trailing %<%%%> in format");
3823 continue;
3824 }
3825 if (*format_chars == '%')
3826 {
3827 ++format_chars;
3828 continue;
3829 }
3830
3831 /* ARGUMENT_PARSER ctor takes FORMAT_CHARS by reference and calls
3832 to ARG_PARSER members may modify the variable. */
3833 flag_chars_t flag_chars;
3834 argument_parser arg_parser (info, format_chars, format_string_cst,
3835 orig_format_chars, format_string_loc,
3836 flag_chars, has_operand_number,
3837 first_fillin_param, fwt_pool, arglocs);
3838
3839 if (!arg_parser.read_any_dollar ())
3840 return;
3841
3842 if (!arg_parser.read_format_flags ())
3843 return;
3844
3845 /* Read any format width, possibly * or *m$. */
3846 if (!arg_parser.read_any_format_width (params, arg_num))
3847 return;
3848
3849 /* Read any format left precision (must be a number, not *). */
3850 arg_parser.read_any_format_left_precision ();
3851
3852 /* Read any format precision, possibly * or *m$. */
3853 if (!arg_parser.read_any_format_precision (params, arg_num))
3854 return;
3855
3856 const char *format_start = format_chars;
3857
3858 arg_parser.handle_alloc_chars ();
3859
3860 /* The rest of the conversion specification is the length modifier
3861 (if any), and the conversion specifier, so this is where the
3862 type information starts. If we need to issue a suggestion
3863 about a type mismatch, then we should preserve everything up
3864 to here. */
3865 const char *type_start = format_chars;
3866
3867 /* Read any length modifier, if this kind of format has them. */
3868 const length_modifier len_modifier
3869 = arg_parser.read_any_length_modifier ();
3870
3871 /* Read any modifier (strftime E/O). */
3872 arg_parser.read_any_other_modifier ();
3873
3874 char format_char = *format_chars;
3875 if (format_char == 0
3876 || (!(fki->flags & (int) FMT_FLAG_FANCY_PERCENT_OK)
3877 && format_char == '%'))
3878 {
3879 format_warning_at_char (format_string_loc, format_string_cst,
3880 format_chars - orig_format_chars,
3881 OPT_Wformat_,
3882 "conversion lacks type at end of format");
3883 continue;
3884 }
3885 format_chars++;
3886
3887 const format_char_info * const fci
3888 = arg_parser.find_format_char_info (format_char);
3889 if (!fci)
3890 continue;
3891
3892 flag_chars.validate (fki, fci, flag_specs, format_chars,
3893 format_string_cst,
3894 format_string_loc, orig_format_chars, format_char,
3895 baltoks.quotdirs.length () > 0);
3896
3897 const int alloc_flag = flag_chars.get_alloc_flag (fki);
3898 const bool suppressed = flag_chars.assignment_suppression_p (fki);
3899
3900 /* Diagnose nested or unmatched quoting directives such as GCC's
3901 "%<...%<" and "%>...%>". */
3902 bool quot_begin_p = strchr (fci->flags2, '<');
3903 bool quot_end_p = strchr (fci->flags2, '>');
3904
3905 if (quot_begin_p && !quot_end_p)
3906 {
3907 if (baltoks.quotdirs.length ())
3908 format_warning_at_char (format_string_loc, format_string_cst,
3909 format_chars - orig_format_chars,
3910 OPT_Wformat_,
3911 "nested quoting directive");
3912 baltoks.quotdirs.safe_push (format_chars);
3913 }
3914 else if (!quot_begin_p && quot_end_p)
3915 {
3916 if (baltoks.quotdirs.length ())
3917 baltoks.quotdirs.pop ();
3918 else
3919 format_warning_at_char (format_string_loc, format_string_cst,
3920 format_chars - orig_format_chars,
3921 OPT_Wformat_,
3922 "unmatched quoting directive");
3923 }
3924
3925 bool color_begin_p = strchr (fci->flags2, '/');
3926 if (color_begin_p)
3927 {
3928 color_begin = format_chars;
3929 color_end = NULL;
3930 }
3931 else if (strchr (fci->flags2, '\\'))
3932 {
3933 if (color_end)
3934 format_warning_at_char (format_string_loc, format_string_cst,
3935 format_chars - orig_format_chars,
3936 OPT_Wformat_,
3937 "%qc directive redundant after prior "
3938 "occurence of the same", format_char);
3939 else if (!color_begin)
3940 format_warning_at_char (format_string_loc, format_string_cst,
3941 format_chars - orig_format_chars,
3942 OPT_Wformat_,
3943 "unmatched color reset directive");
3944 color_end = format_chars;
3945 }
3946
3947 /* Diagnose directives that shouldn't appear in a quoted sequence.
3948 (They are denoted by a double quote in FLAGS2.) */
3949 if (baltoks.quotdirs.length ())
3950 {
3951 if (strchr (fci->flags2, '"'))
3952 format_warning_at_char (format_string_loc, format_string_cst,
3953 format_chars - orig_format_chars,
3954 OPT_Wformat_,
3955 "%qc conversion used within a quoted "
3956 "sequence",
3957 format_char);
3958 }
3959
3960 /* Validate the pairs of flags used. */
3961 arg_parser.validate_flag_pairs (fci, format_char);
3962
3963 arg_parser.give_y2k_warnings (fci, format_char);
3964
3965 arg_parser.parse_any_scan_set (fci);
3966
3967 tree wanted_type = NULL;
3968 const char *wanted_type_name = NULL;
3969
3970 if (!arg_parser.handle_conversions (fci, len_modifier,
3971 wanted_type, wanted_type_name,
3972 arg_num,
3973 params,
3974 format_char))
3975 continue;
3976
3977 arg_parser.main_wanted_type.next = NULL;
3978
3979 /* Finally. . .check type of argument against desired type! */
3980 if (!arg_parser.check_argument_type (fci, len_modifier,
3981 wanted_type, wanted_type_name,
3982 suppressed,
3983 arg_num, params,
3984 alloc_flag,
3985 format_start, type_start,
3986 fmt_param_loc,
3987 format_char))
3988 return;
3989 }
3990
3991 if (format_chars - orig_format_chars != format_length)
3992 format_warning_at_char (format_string_loc, format_string_cst,
3993 format_chars + 1 - orig_format_chars,
3994 OPT_Wformat_contains_nul,
3995 "embedded %<\\0%> in format");
3996 if (info->first_arg_num != 0 && params != 0
3997 && has_operand_number <= 0)
3998 {
3999 res->number_other--;
4000 res->number_extra_args++;
4001 }
4002 if (has_operand_number > 0)
4003 finish_dollar_format_checking (res, fki->flags & (int) FMT_FLAG_DOLLAR_GAP_POINTER_OK);
4004
4005 maybe_diag_unbalanced_tokens (format_string_loc, orig_format_chars,
4006 format_string_cst, baltoks);
4007
4008 if (color_begin && !color_end)
4009 format_warning_at_char (format_string_loc, format_string_cst,
4010 color_begin - orig_format_chars,
4011 OPT_Wformat_, "unterminated color directive");
4012 }
4013
4014 /* Check the argument types from a single format conversion (possibly
4015 including width and precision arguments).
4016
4017 FMT_LOC is the location of the format conversion.
4018
4019 TYPES is a singly-linked list expressing the parts of the format
4020 conversion that expect argument types, and the arguments they
4021 correspond to.
4022
4023 OFFSET_TO_TYPE_START is the offset within the execution-charset encoded
4024 format string to where type information begins for the conversion
4025 (the length modifier and conversion specifier).
4026
4027 CONVERSION_CHAR is the user-provided conversion specifier.
4028
4029 For example, given:
4030
4031 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
4032
4033 then FMT_LOC covers this range:
4034
4035 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
4036 ^^^^^^^^^
4037
4038 and TYPES in this case is a three-entry singly-linked list consisting of:
4039 (1) the check for the field width here:
4040 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
4041 ^ ^^^^
4042 against arg3, and
4043 (2) the check for the field precision here:
4044 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
4045 ^^ ^^^^
4046 against arg4, and
4047 (3) the check for the length modifier and conversion char here:
4048 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
4049 ^^^ ^^^^
4050 against arg5.
4051
4052 OFFSET_TO_TYPE_START is 13, the offset to the "lld" within the
4053 STRING_CST:
4054
4055 0000000000111111111122
4056 0123456789012345678901
4057 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
4058 ^ ^
4059 | ` CONVERSION_CHAR: 'd'
4060 type starts here. */
4061
4062 static void
4063 check_format_types (const substring_loc &fmt_loc,
4064 format_wanted_type *types, const format_kind_info *fki,
4065 int offset_to_type_start,
4066 char conversion_char,
4067 vec<location_t> *arglocs)
4068 {
4069 for (; types != 0; types = types->next)
4070 {
4071 tree cur_param;
4072 tree cur_type;
4073 tree orig_cur_type;
4074 tree wanted_type;
4075 int arg_num;
4076 int i;
4077 int char_type_flag;
4078
4079 wanted_type = types->wanted_type;
4080 arg_num = types->arg_num;
4081
4082 /* The following should not occur here. */
4083 gcc_assert (wanted_type);
4084 gcc_assert (wanted_type != void_type_node || types->pointer_count);
4085
4086 if (types->pointer_count == 0)
4087 wanted_type = lang_hooks.types.type_promotes_to (wanted_type);
4088
4089 wanted_type = TYPE_MAIN_VARIANT (wanted_type);
4090
4091 cur_param = types->param;
4092 if (!cur_param)
4093 {
4094 format_type_warning (fmt_loc, UNKNOWN_LOCATION, types, wanted_type,
4095 NULL, fki, offset_to_type_start,
4096 conversion_char);
4097 continue;
4098 }
4099
4100 cur_type = TREE_TYPE (cur_param);
4101 if (cur_type == error_mark_node)
4102 continue;
4103 orig_cur_type = cur_type;
4104 char_type_flag = 0;
4105
4106 location_t param_loc = UNKNOWN_LOCATION;
4107 if (EXPR_HAS_LOCATION (cur_param))
4108 param_loc = EXPR_LOCATION (cur_param);
4109 else if (arglocs)
4110 {
4111 /* arg_num is 1-based. */
4112 gcc_assert (types->arg_num > 0);
4113 param_loc = (*arglocs)[types->arg_num - 1];
4114 }
4115
4116 STRIP_NOPS (cur_param);
4117
4118 /* Check the types of any additional pointer arguments
4119 that precede the "real" argument. */
4120 for (i = 0; i < types->pointer_count; ++i)
4121 {
4122 if (TREE_CODE (cur_type) == POINTER_TYPE)
4123 {
4124 cur_type = TREE_TYPE (cur_type);
4125 if (cur_type == error_mark_node)
4126 break;
4127
4128 /* Check for writing through a NULL pointer. */
4129 if (types->writing_in_flag
4130 && i == 0
4131 && cur_param != 0
4132 && integer_zerop (cur_param))
4133 warning (OPT_Wformat_, "writing through null pointer "
4134 "(argument %d)", arg_num);
4135
4136 /* Check for reading through a NULL pointer. Ignore
4137 printf-family of functions as they are checked for
4138 null arguments by the middle-end. */
4139 if (fki->conversion_specs != print_char_table
4140 && types->reading_from_flag
4141 && i == 0
4142 && cur_param != 0
4143 && integer_zerop (cur_param))
4144 warning (OPT_Wformat_, "reading through null pointer "
4145 "(argument %d)", arg_num);
4146
4147 if (cur_param != 0 && TREE_CODE (cur_param) == ADDR_EXPR)
4148 cur_param = TREE_OPERAND (cur_param, 0);
4149 else
4150 cur_param = 0;
4151
4152 /* See if this is an attempt to write into a const type with
4153 scanf or with printf "%n". Note: the writing in happens
4154 at the first indirection only, if for example
4155 void * const * is passed to scanf %p; passing
4156 const void ** is simply passing an incompatible type. */
4157 if (types->writing_in_flag
4158 && i == 0
4159 && (TYPE_READONLY (cur_type)
4160 || (cur_param != 0
4161 && (CONSTANT_CLASS_P (cur_param)
4162 || (DECL_P (cur_param)
4163 && TREE_READONLY (cur_param))))))
4164 warning (OPT_Wformat_, "writing into constant object "
4165 "(argument %d)", arg_num);
4166
4167 /* If there are extra type qualifiers beyond the first
4168 indirection, then this makes the types technically
4169 incompatible. */
4170 if (i > 0
4171 && pedantic
4172 && (TYPE_READONLY (cur_type)
4173 || TYPE_VOLATILE (cur_type)
4174 || TYPE_ATOMIC (cur_type)
4175 || TYPE_RESTRICT (cur_type)))
4176 warning (OPT_Wformat_, "extra type qualifiers in format "
4177 "argument (argument %d)",
4178 arg_num);
4179
4180 }
4181 else
4182 {
4183 format_type_warning (fmt_loc, param_loc,
4184 types, wanted_type, orig_cur_type, fki,
4185 offset_to_type_start, conversion_char);
4186 break;
4187 }
4188 }
4189
4190 if (i < types->pointer_count)
4191 continue;
4192
4193 cur_type = TYPE_MAIN_VARIANT (cur_type);
4194
4195 /* Check whether the argument type is a character type. This leniency
4196 only applies to certain formats, flagged with 'c'. */
4197 if (types->char_lenient_flag)
4198 char_type_flag = (cur_type == char_type_node
4199 || cur_type == signed_char_type_node
4200 || cur_type == unsigned_char_type_node);
4201
4202 /* Check the type of the "real" argument, if there's a type we want. */
4203 if (lang_hooks.types_compatible_p (wanted_type, cur_type))
4204 continue;
4205 /* If we want 'void *', allow any pointer type.
4206 (Anything else would already have got a warning.)
4207 With -Wpedantic, only allow pointers to void and to character
4208 types. */
4209 if (wanted_type == void_type_node
4210 && (!pedantic || (i == 1 && char_type_flag)))
4211 continue;
4212 /* Don't warn about differences merely in signedness, unless
4213 -Wpedantic. With -Wpedantic, warn if the type is a pointer
4214 target and not a character type, and for character types at
4215 a second level of indirection. */
4216 if (TREE_CODE (wanted_type) == INTEGER_TYPE
4217 && TREE_CODE (cur_type) == INTEGER_TYPE
4218 && ((!pedantic && !warn_format_signedness)
4219 || (i == 0 && !warn_format_signedness)
4220 || (i == 1 && char_type_flag))
4221 && (TYPE_UNSIGNED (wanted_type)
4222 ? wanted_type == c_common_unsigned_type (cur_type)
4223 : wanted_type == c_common_signed_type (cur_type)))
4224 continue;
4225 /* Don't warn about differences merely in signedness if we know
4226 that the current type is integer-promoted and its original type
4227 was unsigned such as that it is in the range of WANTED_TYPE. */
4228 if (TREE_CODE (wanted_type) == INTEGER_TYPE
4229 && TREE_CODE (cur_type) == INTEGER_TYPE
4230 && warn_format_signedness
4231 && TYPE_UNSIGNED (wanted_type)
4232 && cur_param != NULL_TREE
4233 && TREE_CODE (cur_param) == NOP_EXPR)
4234 {
4235 tree t = TREE_TYPE (TREE_OPERAND (cur_param, 0));
4236 if (TYPE_UNSIGNED (t)
4237 && cur_type == lang_hooks.types.type_promotes_to (t))
4238 continue;
4239 }
4240 /* Likewise, "signed char", "unsigned char" and "char" are
4241 equivalent but the above test won't consider them equivalent. */
4242 if (wanted_type == char_type_node
4243 && (!pedantic || i < 2)
4244 && char_type_flag)
4245 continue;
4246 if (types->scalar_identity_flag
4247 && (TREE_CODE (cur_type) == TREE_CODE (wanted_type)
4248 || (INTEGRAL_TYPE_P (cur_type)
4249 && INTEGRAL_TYPE_P (wanted_type)))
4250 && TYPE_PRECISION (cur_type) == TYPE_PRECISION (wanted_type))
4251 continue;
4252 /* Now we have a type mismatch. */
4253 format_type_warning (fmt_loc, param_loc, types,
4254 wanted_type, orig_cur_type, fki,
4255 offset_to_type_start, conversion_char);
4256 }
4257 }
4258
4259 /* Given type TYPE, attempt to dereference the type N times
4260 (e.g. from ("int ***", 2) to "int *")
4261
4262 Return the derefenced type, with any qualifiers
4263 such as "const" stripped from the result, or
4264 NULL if unsuccessful (e.g. TYPE is not a pointer type). */
4265
4266 static tree
4267 deref_n_times (tree type, int n)
4268 {
4269 gcc_assert (type);
4270
4271 for (int i = n; i > 0; i--)
4272 {
4273 if (TREE_CODE (type) != POINTER_TYPE)
4274 return NULL_TREE;
4275 type = TREE_TYPE (type);
4276 }
4277 /* Strip off any "const" etc. */
4278 return build_qualified_type (type, 0);
4279 }
4280
4281 /* Lookup the format code for FORMAT_LEN within FLI,
4282 returning the string code for expressing it, or NULL
4283 if it is not found. */
4284
4285 static const char *
4286 get_modifier_for_format_len (const format_length_info *fli,
4287 enum format_lengths format_len)
4288 {
4289 for (; fli->name; fli++)
4290 {
4291 if (fli->index == format_len)
4292 return fli->name;
4293 if (fli->double_index == format_len)
4294 return fli->double_name;
4295 }
4296 return NULL;
4297 }
4298
4299 #if CHECKING_P
4300
4301 namespace selftest {
4302
4303 static void
4304 test_get_modifier_for_format_len ()
4305 {
4306 ASSERT_STREQ ("h",
4307 get_modifier_for_format_len (printf_length_specs, FMT_LEN_h));
4308 ASSERT_STREQ ("hh",
4309 get_modifier_for_format_len (printf_length_specs, FMT_LEN_hh));
4310 ASSERT_STREQ ("L",
4311 get_modifier_for_format_len (printf_length_specs, FMT_LEN_L));
4312 ASSERT_EQ (NULL,
4313 get_modifier_for_format_len (printf_length_specs, FMT_LEN_none));
4314 }
4315
4316 } // namespace selftest
4317
4318 #endif /* CHECKING_P */
4319
4320 /* Determine if SPEC_TYPE and ARG_TYPE are sufficiently similar for a
4321 format_type_detail using SPEC_TYPE to be offered as a suggestion for
4322 Wformat type errors where the argument has type ARG_TYPE. */
4323
4324 static bool
4325 matching_type_p (tree spec_type, tree arg_type)
4326 {
4327 gcc_assert (spec_type);
4328 gcc_assert (arg_type);
4329
4330 /* If any of the types requires structural equality, we can't compare
4331 their canonical types. */
4332 if (TYPE_STRUCTURAL_EQUALITY_P (spec_type)
4333 || TYPE_STRUCTURAL_EQUALITY_P (arg_type))
4334 return false;
4335
4336 spec_type = TYPE_CANONICAL (spec_type);
4337 arg_type = TYPE_CANONICAL (arg_type);
4338
4339 if (TREE_CODE (spec_type) == INTEGER_TYPE
4340 && TREE_CODE (arg_type) == INTEGER_TYPE
4341 && (TYPE_UNSIGNED (spec_type)
4342 ? spec_type == c_common_unsigned_type (arg_type)
4343 : spec_type == c_common_signed_type (arg_type)))
4344 return true;
4345
4346 return spec_type == arg_type;
4347 }
4348
4349 /* Subroutine of get_format_for_type.
4350
4351 Generate a string containing the length modifier and conversion specifier
4352 that should be used to format arguments of type ARG_TYPE within FKI
4353 (effectively the inverse of the checking code).
4354
4355 If CONVERSION_CHAR is not zero (the first pass), the resulting suggestion
4356 is required to use it, for correcting bogus length modifiers.
4357 If CONVERSION_CHAR is zero (the second pass), then allow any suggestion
4358 that matches ARG_TYPE.
4359
4360 If successful, returns a non-NULL string which should be freed
4361 by the caller.
4362 Otherwise, returns NULL. */
4363
4364 static char *
4365 get_format_for_type_1 (const format_kind_info *fki, tree arg_type,
4366 char conversion_char)
4367 {
4368 gcc_assert (arg_type);
4369
4370 const format_char_info *spec;
4371 for (spec = &fki->conversion_specs[0];
4372 spec->format_chars;
4373 spec++)
4374 {
4375 if (conversion_char)
4376 if (!strchr (spec->format_chars, conversion_char))
4377 continue;
4378
4379 tree effective_arg_type = deref_n_times (arg_type,
4380 spec->pointer_count);
4381 if (!effective_arg_type)
4382 continue;
4383 for (int i = 0; i < FMT_LEN_MAX; i++)
4384 {
4385 const format_type_detail *ftd = &spec->types[i];
4386 if (!ftd->type)
4387 continue;
4388 if (matching_type_p (*ftd->type, effective_arg_type))
4389 {
4390 const char *len_modifier
4391 = get_modifier_for_format_len (fki->length_char_specs,
4392 (enum format_lengths)i);
4393 if (!len_modifier)
4394 len_modifier = "";
4395
4396 if (conversion_char)
4397 /* We found a match, using the given conversion char - the
4398 length modifier was incorrect (or absent).
4399 Provide a suggestion using the conversion char with the
4400 correct length modifier for the type. */
4401 return xasprintf ("%s%c", len_modifier, conversion_char);
4402 else
4403 /* 2nd pass: no match was possible using the user-provided
4404 conversion char, but we do have a match without using it.
4405 Provide a suggestion using the first conversion char
4406 listed for the given type. */
4407 return xasprintf ("%s%c", len_modifier, spec->format_chars[0]);
4408 }
4409 }
4410 }
4411
4412 return NULL;
4413 }
4414
4415 /* Generate a string containing the length modifier and conversion specifier
4416 that should be used to format arguments of type ARG_TYPE within FKI
4417 (effectively the inverse of the checking code).
4418
4419 If successful, returns a non-NULL string which should be freed
4420 by the caller.
4421 Otherwise, returns NULL. */
4422
4423 static char *
4424 get_format_for_type (const format_kind_info *fki, tree arg_type,
4425 char conversion_char)
4426 {
4427 gcc_assert (arg_type);
4428 gcc_assert (conversion_char);
4429
4430 /* First pass: look for a format_char_info containing CONVERSION_CHAR
4431 If we find one, then presumably the length modifier was incorrect
4432 (or absent). */
4433 char *result = get_format_for_type_1 (fki, arg_type, conversion_char);
4434 if (result)
4435 return result;
4436
4437 /* Second pass: we didn't find a match for CONVERSION_CHAR, so try
4438 matching just on the type. */
4439 return get_format_for_type_1 (fki, arg_type, '\0');
4440 }
4441
4442 /* Attempt to get a string for use as a replacement fix-it hint for the
4443 source range in FMT_LOC.
4444
4445 Preserve all of the text within the range of FMT_LOC up to
4446 OFFSET_TO_TYPE_START, replacing the rest with an appropriate
4447 length modifier and conversion specifier for ARG_TYPE, attempting
4448 to keep the user-provided CONVERSION_CHAR if possible.
4449
4450 For example, given a long vs long long mismatch for arg5 here:
4451
4452 000000000111111111122222222223333333333|
4453 123456789012345678901234567890123456789` column numbers
4454 0000000000111111111122|
4455 0123456789012345678901` string offsets
4456 V~~~~~~~~ : range of FMT_LOC, from cols 23-31
4457 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5);
4458 ^ ^
4459 | ` CONVERSION_CHAR: 'd'
4460 type starts here
4461
4462 where OFFSET_TO_TYPE_START is 13 (the offset to the "lld" within the
4463 STRING_CST), where the user provided:
4464 %-+*.*lld
4465 the result (assuming "long" argument 5) should be:
4466 %-+*.*ld
4467
4468 If successful, returns a non-NULL string which should be freed
4469 by the caller.
4470 Otherwise, returns NULL. */
4471
4472 static char *
4473 get_corrected_substring (const substring_loc &fmt_loc,
4474 format_wanted_type *type, tree arg_type,
4475 const format_kind_info *fki,
4476 int offset_to_type_start, char conversion_char)
4477 {
4478 /* Attempt to provide hints for argument types, but not for field widths
4479 and precisions. */
4480 if (!arg_type)
4481 return NULL;
4482 if (type->kind != CF_KIND_FORMAT)
4483 return NULL;
4484
4485 /* Locate the current code within the source range, rejecting
4486 any awkward cases where the format string occupies more than
4487 one line.
4488 Lookup the place where the type starts (including any length
4489 modifiers), getting it as the caret location. */
4490 substring_loc type_loc (fmt_loc);
4491 type_loc.set_caret_index (offset_to_type_start);
4492
4493 location_t fmt_substring_loc;
4494 const char *err = type_loc.get_location (&fmt_substring_loc);
4495 if (err)
4496 return NULL;
4497
4498 source_range fmt_substring_range
4499 = get_range_from_loc (line_table, fmt_substring_loc);
4500
4501 expanded_location caret
4502 = expand_location_to_spelling_point (fmt_substring_loc);
4503 expanded_location start
4504 = expand_location_to_spelling_point (fmt_substring_range.m_start);
4505 expanded_location finish
4506 = expand_location_to_spelling_point (fmt_substring_range.m_finish);
4507 if (caret.file != start.file)
4508 return NULL;
4509 if (start.file != finish.file)
4510 return NULL;
4511 if (caret.line != start.line)
4512 return NULL;
4513 if (start.line != finish.line)
4514 return NULL;
4515 if (start.column > caret.column)
4516 return NULL;
4517 if (start.column > finish.column)
4518 return NULL;
4519 if (caret.column > finish.column)
4520 return NULL;
4521
4522 char_span line = location_get_source_line (start.file, start.line);
4523 if (!line)
4524 return NULL;
4525
4526 /* If we got this far, then we have the line containing the
4527 existing conversion specification.
4528
4529 Generate a trimmed copy, containing the prefix part of the conversion
4530 specification, up to the (but not including) the length modifier.
4531 In the above example, this would be "%-+*.*". */
4532 int length_up_to_type = caret.column - start.column;
4533 char_span prefix_span = line.subspan (start.column - 1, length_up_to_type);
4534 char *prefix = prefix_span.xstrdup ();
4535
4536 /* Now attempt to generate a suggestion for the rest of the specification
4537 (length modifier and conversion char), based on ARG_TYPE and
4538 CONVERSION_CHAR.
4539 In the above example, this would be "ld". */
4540 char *format_for_type = get_format_for_type (fki, arg_type, conversion_char);
4541 if (!format_for_type)
4542 {
4543 free (prefix);
4544 return NULL;
4545 }
4546
4547 /* Success. Generate the resulting suggestion for the whole range of
4548 FMT_LOC by concatenating the two strings.
4549 In the above example, this would be "%-+*.*ld". */
4550 char *result = concat (prefix, format_for_type, NULL);
4551 free (format_for_type);
4552 free (prefix);
4553 return result;
4554 }
4555
4556 /* Helper class for adding zero or more trailing '*' to types.
4557
4558 The format type and name exclude any '*' for pointers, so those
4559 must be formatted manually. For all the types we currently have,
4560 this is adequate, but formats taking pointers to functions or
4561 arrays would require the full type to be built up in order to
4562 print it with %T. */
4563
4564 class indirection_suffix
4565 {
4566 public:
4567 indirection_suffix (int pointer_count) : m_pointer_count (pointer_count) {}
4568
4569 /* Determine the size of the buffer (including NUL-terminator). */
4570
4571 size_t get_buffer_size () const
4572 {
4573 return m_pointer_count + 2;
4574 }
4575
4576 /* Write the '*' to DST and add a NUL-terminator. */
4577
4578 void fill_buffer (char *dst) const
4579 {
4580 if (m_pointer_count == 0)
4581 dst[0] = 0;
4582 else if (c_dialect_cxx ())
4583 {
4584 memset (dst, '*', m_pointer_count);
4585 dst[m_pointer_count] = 0;
4586 }
4587 else
4588 {
4589 dst[0] = ' ';
4590 memset (dst + 1, '*', m_pointer_count);
4591 dst[m_pointer_count + 1] = 0;
4592 }
4593 }
4594
4595 private:
4596 int m_pointer_count;
4597 };
4598
4599 /* Subclass of range_label for labelling the range in the format string
4600 with the type in question, adding trailing '*' for pointer_count. */
4601
4602 class range_label_for_format_type_mismatch
4603 : public range_label_for_type_mismatch
4604 {
4605 public:
4606 range_label_for_format_type_mismatch (tree labelled_type, tree other_type,
4607 int pointer_count)
4608 : range_label_for_type_mismatch (labelled_type, other_type),
4609 m_pointer_count (pointer_count)
4610 {
4611 }
4612
4613 label_text get_text (unsigned range_idx) const FINAL OVERRIDE
4614 {
4615 label_text text = range_label_for_type_mismatch::get_text (range_idx);
4616 if (text.m_buffer == NULL)
4617 return text;
4618
4619 indirection_suffix suffix (m_pointer_count);
4620 char *p = (char *) alloca (suffix.get_buffer_size ());
4621 suffix.fill_buffer (p);
4622
4623 char *result = concat (text.m_buffer, p, NULL);
4624 text.maybe_free ();
4625 return label_text (result, true);
4626 }
4627
4628 private:
4629 int m_pointer_count;
4630 };
4631
4632 /* Give a warning about a format argument of different type from that expected.
4633 The range of the diagnostic is taken from WHOLE_FMT_LOC; the caret location
4634 is based on the location of the char at TYPE->offset_loc.
4635 PARAM_LOC is the location of the relevant argument, or UNKNOWN_LOCATION
4636 if this is unavailable.
4637 WANTED_TYPE is the type the argument should have,
4638 possibly stripped of pointer dereferences. The description (such as "field
4639 precision"), the placement in the format string, a possibly more
4640 friendly name of WANTED_TYPE, and the number of pointer dereferences
4641 are taken from TYPE. ARG_TYPE is the type of the actual argument,
4642 or NULL if it is missing.
4643
4644 OFFSET_TO_TYPE_START is the offset within the execution-charset encoded
4645 format string to where type information begins for the conversion
4646 (the length modifier and conversion specifier).
4647 CONVERSION_CHAR is the user-provided conversion specifier.
4648
4649 For example, given a type mismatch for argument 5 here:
4650
4651 00000000011111111112222222222333333333344444444445555555555|
4652 12345678901234567890123456789012345678901234567890123456789` column numbers
4653 0000000000111111111122|
4654 0123456789012345678901` offsets within STRING_CST
4655 V~~~~~~~~ : range of WHOLE_FMT_LOC, from cols 23-31
4656 sprintf (d, "before %-+*.*lld after", int_expr, int_expr, long_expr);
4657 ^ ^ ^~~~~~~~~
4658 | ` CONVERSION_CHAR: 'd' PARAM_LOC
4659 type starts here
4660
4661 OFFSET_TO_TYPE_START is 13, the offset to the "lld" within the
4662 STRING_CST. */
4663
4664 static void
4665 format_type_warning (const substring_loc &whole_fmt_loc,
4666 location_t param_loc,
4667 format_wanted_type *type,
4668 tree wanted_type, tree arg_type,
4669 const format_kind_info *fki,
4670 int offset_to_type_start,
4671 char conversion_char)
4672 {
4673 enum format_specifier_kind kind = type->kind;
4674 const char *wanted_type_name = type->wanted_type_name;
4675 const char *format_start = type->format_start;
4676 int format_length = type->format_length;
4677 int pointer_count = type->pointer_count;
4678 int arg_num = type->arg_num;
4679
4680 /* If ARG_TYPE is a typedef with a misleading name (for example,
4681 size_t but not the standard size_t expected by printf %zu), avoid
4682 printing the typedef name. */
4683 if (wanted_type_name
4684 && arg_type
4685 && TYPE_NAME (arg_type)
4686 && TREE_CODE (TYPE_NAME (arg_type)) == TYPE_DECL
4687 && DECL_NAME (TYPE_NAME (arg_type))
4688 && !strcmp (wanted_type_name,
4689 lang_hooks.decl_printable_name (TYPE_NAME (arg_type), 2)))
4690 arg_type = TYPE_MAIN_VARIANT (arg_type);
4691
4692 indirection_suffix suffix (pointer_count);
4693 char *p = (char *) alloca (suffix.get_buffer_size ());
4694 suffix.fill_buffer (p);
4695
4696 /* WHOLE_FMT_LOC has the caret at the end of the range.
4697 Set the caret to be at the offset from TYPE. Subtract one
4698 from the offset for the same reason as in format_warning_at_char. */
4699 substring_loc fmt_loc (whole_fmt_loc);
4700 fmt_loc.set_caret_index (type->offset_loc - 1);
4701
4702 range_label_for_format_type_mismatch fmt_label (wanted_type, arg_type,
4703 pointer_count);
4704 range_label_for_type_mismatch param_label (arg_type, wanted_type);
4705
4706 /* Get a string for use as a replacement fix-it hint for the range in
4707 fmt_loc, or NULL. */
4708 char *corrected_substring
4709 = get_corrected_substring (fmt_loc, type, arg_type, fki,
4710 offset_to_type_start, conversion_char);
4711 format_string_diagnostic_t diag (fmt_loc, &fmt_label, param_loc, &param_label,
4712 corrected_substring);
4713 if (wanted_type_name)
4714 {
4715 if (arg_type)
4716 diag.emit_warning
4717 (OPT_Wformat_,
4718 "%s %<%s%.*s%> expects argument of type %<%s%s%>, "
4719 "but argument %d has type %qT",
4720 gettext (kind_descriptions[kind]),
4721 (kind == CF_KIND_FORMAT ? "%" : ""),
4722 format_length, format_start,
4723 wanted_type_name, p, arg_num, arg_type);
4724 else
4725 diag.emit_warning
4726 (OPT_Wformat_,
4727 "%s %<%s%.*s%> expects a matching %<%s%s%> argument",
4728 gettext (kind_descriptions[kind]),
4729 (kind == CF_KIND_FORMAT ? "%" : ""),
4730 format_length, format_start, wanted_type_name, p);
4731 }
4732 else
4733 {
4734 if (arg_type)
4735 diag.emit_warning
4736 (OPT_Wformat_,
4737 "%s %<%s%.*s%> expects argument of type %<%T%s%>, "
4738 "but argument %d has type %qT",
4739 gettext (kind_descriptions[kind]),
4740 (kind == CF_KIND_FORMAT ? "%" : ""),
4741 format_length, format_start,
4742 wanted_type, p, arg_num, arg_type);
4743 else
4744 diag.emit_warning
4745 (OPT_Wformat_,
4746 "%s %<%s%.*s%> expects a matching %<%T%s%> argument",
4747 gettext (kind_descriptions[kind]),
4748 (kind == CF_KIND_FORMAT ? "%" : ""),
4749 format_length, format_start, wanted_type, p);
4750 }
4751
4752 free (corrected_substring);
4753 }
4754
4755
4756 /* Given a format_char_info array FCI, and a character C, this function
4757 returns the index into the conversion_specs where that specifier's
4758 data is located. The character must exist. */
4759 static unsigned int
4760 find_char_info_specifier_index (const format_char_info *fci, int c)
4761 {
4762 unsigned i;
4763
4764 for (i = 0; fci->format_chars; i++, fci++)
4765 if (strchr (fci->format_chars, c))
4766 return i;
4767
4768 /* We shouldn't be looking for a non-existent specifier. */
4769 gcc_unreachable ();
4770 }
4771
4772 /* Given a format_length_info array FLI, and a character C, this
4773 function returns the index into the conversion_specs where that
4774 modifier's data is located. The character must exist. */
4775 static unsigned int
4776 find_length_info_modifier_index (const format_length_info *fli, int c)
4777 {
4778 unsigned i;
4779
4780 for (i = 0; fli->name; i++, fli++)
4781 if (strchr (fli->name, c))
4782 return i;
4783
4784 /* We shouldn't be looking for a non-existent modifier. */
4785 gcc_unreachable ();
4786 }
4787
4788 /* Determine the type of HOST_WIDE_INT in the code being compiled for
4789 use in GCC's __asm_fprintf__ custom format attribute. You must
4790 have set dynamic_format_types before calling this function. */
4791 static void
4792 init_dynamic_asm_fprintf_info (void)
4793 {
4794 static tree hwi;
4795
4796 if (!hwi)
4797 {
4798 format_length_info *new_asm_fprintf_length_specs;
4799 unsigned int i;
4800
4801 /* Find the underlying type for HOST_WIDE_INT. For the %w
4802 length modifier to work, one must have issued: "typedef
4803 HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code
4804 prior to using that modifier. */
4805 hwi = maybe_get_identifier ("__gcc_host_wide_int__");
4806 if (!hwi)
4807 {
4808 error ("%<__gcc_host_wide_int__%> is not defined as a type");
4809 return;
4810 }
4811 hwi = identifier_global_value (hwi);
4812 if (!hwi || TREE_CODE (hwi) != TYPE_DECL)
4813 {
4814 error ("%<__gcc_host_wide_int__%> is not defined as a type");
4815 return;
4816 }
4817 hwi = DECL_ORIGINAL_TYPE (hwi);
4818 gcc_assert (hwi);
4819 if (hwi != long_integer_type_node && hwi != long_long_integer_type_node)
4820 {
4821 error ("%<__gcc_host_wide_int__%> is not defined as %<long%>"
4822 " or %<long long%>");
4823 return;
4824 }
4825
4826 /* Create a new (writable) copy of asm_fprintf_length_specs. */
4827 new_asm_fprintf_length_specs = (format_length_info *)
4828 xmemdup (asm_fprintf_length_specs,
4829 sizeof (asm_fprintf_length_specs),
4830 sizeof (asm_fprintf_length_specs));
4831
4832 /* HOST_WIDE_INT must be one of 'long' or 'long long'. */
4833 i = find_length_info_modifier_index (new_asm_fprintf_length_specs, 'w');
4834 if (hwi == long_integer_type_node)
4835 new_asm_fprintf_length_specs[i].index = FMT_LEN_l;
4836 else if (hwi == long_long_integer_type_node)
4837 new_asm_fprintf_length_specs[i].index = FMT_LEN_ll;
4838 else
4839 gcc_unreachable ();
4840
4841 /* Assign the new data for use. */
4842 dynamic_format_types[asm_fprintf_format_type].length_char_specs =
4843 new_asm_fprintf_length_specs;
4844 }
4845 }
4846
4847 /* Determine the type of a "locus" in the code being compiled for use
4848 in GCC's __gcc_gfc__ custom format attribute. You must have set
4849 dynamic_format_types before calling this function. */
4850 static void
4851 init_dynamic_gfc_info (void)
4852 {
4853 if (!locus)
4854 {
4855 static format_char_info *gfc_fci;
4856
4857 /* For the GCC __gcc_gfc__ custom format specifier to work, one
4858 must have declared 'locus' prior to using this attribute. If
4859 we haven't seen this declarations then you shouldn't use the
4860 specifier requiring that type. */
4861 if ((locus = maybe_get_identifier ("locus")))
4862 {
4863 locus = identifier_global_value (locus);
4864 if (locus)
4865 {
4866 if (TREE_CODE (locus) != TYPE_DECL
4867 || TREE_TYPE (locus) == error_mark_node)
4868 {
4869 error ("%<locus%> is not defined as a type");
4870 locus = 0;
4871 }
4872 else
4873 locus = TREE_TYPE (locus);
4874 }
4875 }
4876
4877 /* Assign the new data for use. */
4878
4879 /* Handle the __gcc_gfc__ format specifics. */
4880 if (!gfc_fci)
4881 dynamic_format_types[gcc_gfc_format_type].conversion_specs =
4882 gfc_fci = (format_char_info *)
4883 xmemdup (gcc_gfc_char_table,
4884 sizeof (gcc_gfc_char_table),
4885 sizeof (gcc_gfc_char_table));
4886 if (locus)
4887 {
4888 const unsigned i = find_char_info_specifier_index (gfc_fci, 'L');
4889 gfc_fci[i].types[0].type = &locus;
4890 gfc_fci[i].pointer_count = 1;
4891 }
4892 }
4893 }
4894
4895 /* Lookup the type named NAME and return a pointer-to-NAME type if found.
4896 Otherwise, return void_type_node if NAME has not been used yet, or NULL_TREE if
4897 NAME is not a type (issuing an error). */
4898
4899 static tree
4900 get_pointer_to_named_type (const char *name)
4901 {
4902 tree result;
4903 if ((result = maybe_get_identifier (name)))
4904 {
4905 result = identifier_global_value (result);
4906 if (result)
4907 {
4908 if (TREE_CODE (result) != TYPE_DECL)
4909 {
4910 error ("%qs is not defined as a type", name);
4911 result = NULL_TREE;
4912 }
4913 else
4914 result = TREE_TYPE (result);
4915 }
4916 }
4917 else
4918 result = void_type_node;
4919 return result;
4920 }
4921
4922 /* Determine the types of "tree" and "location_t" in the code being
4923 compiled for use in GCC's diagnostic custom format attributes. You
4924 must have set dynamic_format_types before calling this function. */
4925 static void
4926 init_dynamic_diag_info (void)
4927 {
4928 /* For the GCC-diagnostics custom format specifiers to work, one
4929 must have declared 'tree' and 'location_t' prior to using those
4930 attributes. If we haven't seen these declarations then
4931 the specifiers requiring these types shouldn't be used.
4932 However we don't force a hard ICE because we may see only one
4933 or the other type. */
4934 if (tree loc = maybe_get_identifier ("location_t"))
4935 {
4936 loc = identifier_global_value (loc);
4937 if (loc && TREE_CODE (loc) != TYPE_DECL)
4938 error ("%<location_t%> is not defined as a type");
4939 }
4940
4941 /* Initialize the global tree node type local to this file. */
4942 if (!local_tree_type_node
4943 || local_tree_type_node == void_type_node)
4944 {
4945 /* We need to grab the underlying 'union tree_node' so peek into
4946 an extra type level. */
4947 if ((local_tree_type_node = maybe_get_identifier ("tree")))
4948 {
4949 local_tree_type_node = identifier_global_value (local_tree_type_node);
4950 if (local_tree_type_node)
4951 {
4952 if (TREE_CODE (local_tree_type_node) != TYPE_DECL)
4953 {
4954 error ("%<tree%> is not defined as a type");
4955 local_tree_type_node = 0;
4956 }
4957 else if (TREE_CODE (TREE_TYPE (local_tree_type_node))
4958 != POINTER_TYPE)
4959 {
4960 error ("%<tree%> is not defined as a pointer type");
4961 local_tree_type_node = 0;
4962 }
4963 else
4964 local_tree_type_node =
4965 TREE_TYPE (TREE_TYPE (local_tree_type_node));
4966 }
4967 }
4968 else
4969 local_tree_type_node = void_type_node;
4970 }
4971
4972 /* Similar to the above but for gimple*. */
4973 if (!local_gimple_ptr_node
4974 || local_gimple_ptr_node == void_type_node)
4975 local_gimple_ptr_node = get_pointer_to_named_type ("gimple");
4976
4977 /* Similar to the above but for cgraph_node*. */
4978 if (!local_cgraph_node_ptr_node
4979 || local_cgraph_node_ptr_node == void_type_node)
4980 local_cgraph_node_ptr_node = get_pointer_to_named_type ("cgraph_node");
4981
4982 static tree hwi;
4983
4984 if (!hwi)
4985 {
4986 static format_length_info *diag_ls;
4987 unsigned int i;
4988
4989 /* Find the underlying type for HOST_WIDE_INT. For the 'w'
4990 length modifier to work, one must have issued: "typedef
4991 HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code
4992 prior to using that modifier. */
4993 if ((hwi = maybe_get_identifier ("__gcc_host_wide_int__")))
4994 {
4995 hwi = identifier_global_value (hwi);
4996 if (hwi)
4997 {
4998 if (TREE_CODE (hwi) != TYPE_DECL)
4999 {
5000 error ("%<__gcc_host_wide_int__%> is not defined as a type");
5001 hwi = 0;
5002 }
5003 else
5004 {
5005 hwi = DECL_ORIGINAL_TYPE (hwi);
5006 gcc_assert (hwi);
5007 if (hwi != long_integer_type_node
5008 && hwi != long_long_integer_type_node)
5009 {
5010 error ("%<__gcc_host_wide_int__%> is not defined"
5011 " as %<long%> or %<long long%>");
5012 hwi = 0;
5013 }
5014 }
5015 }
5016 }
5017
5018 /* Assign the new data for use. */
5019
5020 /* All the GCC diag formats use the same length specs. */
5021 if (!diag_ls)
5022 dynamic_format_types[gcc_diag_format_type].length_char_specs =
5023 dynamic_format_types[gcc_tdiag_format_type].length_char_specs =
5024 dynamic_format_types[gcc_cdiag_format_type].length_char_specs =
5025 dynamic_format_types[gcc_cxxdiag_format_type].length_char_specs =
5026 dynamic_format_types[gcc_dump_printf_format_type].length_char_specs =
5027 diag_ls = (format_length_info *)
5028 xmemdup (gcc_diag_length_specs,
5029 sizeof (gcc_diag_length_specs),
5030 sizeof (gcc_diag_length_specs));
5031 if (hwi)
5032 {
5033 /* HOST_WIDE_INT must be one of 'long' or 'long long'. */
5034 i = find_length_info_modifier_index (diag_ls, 'w');
5035 if (hwi == long_integer_type_node)
5036 diag_ls[i].index = FMT_LEN_l;
5037 else if (hwi == long_long_integer_type_node)
5038 diag_ls[i].index = FMT_LEN_ll;
5039 else
5040 gcc_unreachable ();
5041 }
5042 }
5043
5044 /* It's safe to "re-initialize these to the same values. */
5045 dynamic_format_types[gcc_diag_format_type].conversion_specs =
5046 gcc_diag_char_table;
5047 dynamic_format_types[gcc_tdiag_format_type].conversion_specs =
5048 gcc_tdiag_char_table;
5049 dynamic_format_types[gcc_cdiag_format_type].conversion_specs =
5050 gcc_cdiag_char_table;
5051 dynamic_format_types[gcc_cxxdiag_format_type].conversion_specs =
5052 gcc_cxxdiag_char_table;
5053 dynamic_format_types[gcc_dump_printf_format_type].conversion_specs =
5054 gcc_dump_printf_char_table;
5055 }
5056
5057 #ifdef TARGET_FORMAT_TYPES
5058 extern const format_kind_info TARGET_FORMAT_TYPES[];
5059 #endif
5060
5061 #ifdef TARGET_OVERRIDES_FORMAT_ATTRIBUTES
5062 extern const target_ovr_attr TARGET_OVERRIDES_FORMAT_ATTRIBUTES[];
5063 #endif
5064 #ifdef TARGET_OVERRIDES_FORMAT_INIT
5065 extern void TARGET_OVERRIDES_FORMAT_INIT (void);
5066 #endif
5067
5068 /* Attributes such as "printf" are equivalent to those such as
5069 "gnu_printf" unless this is overridden by a target. */
5070 static const target_ovr_attr gnu_target_overrides_format_attributes[] =
5071 {
5072 { "gnu_printf", "printf" },
5073 { "gnu_scanf", "scanf" },
5074 { "gnu_strftime", "strftime" },
5075 { "gnu_strfmon", "strfmon" },
5076 { NULL, NULL }
5077 };
5078
5079 /* Translate to unified attribute name. This is used in decode_format_type and
5080 decode_format_attr. In attr_name the user specified argument is passed. It
5081 returns the unified format name from TARGET_OVERRIDES_FORMAT_ATTRIBUTES
5082 or the attr_name passed to this function, if there is no matching entry. */
5083 static const char *
5084 convert_format_name_to_system_name (const char *attr_name)
5085 {
5086 int i;
5087
5088 if (attr_name == NULL || *attr_name == 0
5089 || strncmp (attr_name, "gcc_", 4) == 0)
5090 return attr_name;
5091 #ifdef TARGET_OVERRIDES_FORMAT_INIT
5092 TARGET_OVERRIDES_FORMAT_INIT ();
5093 #endif
5094
5095 #ifdef TARGET_OVERRIDES_FORMAT_ATTRIBUTES
5096 /* Check if format attribute is overridden by target. */
5097 if (TARGET_OVERRIDES_FORMAT_ATTRIBUTES != NULL
5098 && TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT > 0)
5099 {
5100 for (i = 0; i < TARGET_OVERRIDES_FORMAT_ATTRIBUTES_COUNT; ++i)
5101 {
5102 if (cmp_attribs (TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_src,
5103 attr_name))
5104 return attr_name;
5105 if (cmp_attribs (TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_dst,
5106 attr_name))
5107 return TARGET_OVERRIDES_FORMAT_ATTRIBUTES[i].named_attr_src;
5108 }
5109 }
5110 #endif
5111 /* Otherwise default to gnu format. */
5112 for (i = 0;
5113 gnu_target_overrides_format_attributes[i].named_attr_src != NULL;
5114 ++i)
5115 {
5116 if (cmp_attribs (gnu_target_overrides_format_attributes[i].named_attr_src,
5117 attr_name))
5118 return attr_name;
5119 if (cmp_attribs (gnu_target_overrides_format_attributes[i].named_attr_dst,
5120 attr_name))
5121 return gnu_target_overrides_format_attributes[i].named_attr_src;
5122 }
5123
5124 return attr_name;
5125 }
5126
5127 /* Handle a "format" attribute; arguments as in
5128 struct attribute_spec.handler. */
5129 tree
5130 handle_format_attribute (tree *node, tree atname, tree args,
5131 int flags, bool *no_add_attrs)
5132 {
5133 const_tree type = *node;
5134 function_format_info info;
5135
5136 #ifdef TARGET_FORMAT_TYPES
5137 /* If the target provides additional format types, we need to
5138 add them to FORMAT_TYPES at first use. */
5139 if (TARGET_FORMAT_TYPES != NULL && !dynamic_format_types)
5140 {
5141 dynamic_format_types = XNEWVEC (format_kind_info,
5142 n_format_types + TARGET_N_FORMAT_TYPES);
5143 memcpy (dynamic_format_types, format_types_orig,
5144 sizeof (format_types_orig));
5145 memcpy (&dynamic_format_types[n_format_types], TARGET_FORMAT_TYPES,
5146 TARGET_N_FORMAT_TYPES * sizeof (dynamic_format_types[0]));
5147
5148 format_types = dynamic_format_types;
5149 /* Provide a reference for the first potential external type. */
5150 first_target_format_type = n_format_types;
5151 n_format_types += TARGET_N_FORMAT_TYPES;
5152 }
5153 #endif
5154
5155 /* Canonicalize name of format function. */
5156 if (TREE_CODE (TREE_VALUE (args)) == IDENTIFIER_NODE)
5157 TREE_VALUE (args) = canonicalize_attr_name (TREE_VALUE (args));
5158
5159 if (!decode_format_attr (type, atname, args, &info, /* validated_p = */false))
5160 {
5161 *no_add_attrs = true;
5162 return NULL_TREE;
5163 }
5164
5165 if (prototype_p (type))
5166 {
5167 if (!check_format_string (type, info.format_num, flags,
5168 no_add_attrs, info.format_type))
5169 return NULL_TREE;
5170
5171 if (info.first_arg_num != 0)
5172 {
5173 unsigned HOST_WIDE_INT arg_num = 1;
5174 function_args_iterator iter;
5175 tree arg_type;
5176
5177 /* Verify that first_arg_num points to the last arg,
5178 the ... */
5179 FOREACH_FUNCTION_ARGS (type, arg_type, iter)
5180 arg_num++;
5181
5182 if (arg_num != info.first_arg_num)
5183 {
5184 if (!(flags & (int) ATTR_FLAG_BUILT_IN))
5185 error ("argument to be formatted is not %<...%>");
5186 *no_add_attrs = true;
5187 return NULL_TREE;
5188 }
5189 }
5190 }
5191
5192 /* Check if this is a strftime variant. Just for this variant
5193 FMT_FLAG_ARG_CONVERT is not set. */
5194 if ((format_types[info.format_type].flags & (int) FMT_FLAG_ARG_CONVERT) == 0
5195 && info.first_arg_num != 0)
5196 {
5197 error ("strftime formats cannot format arguments");
5198 *no_add_attrs = true;
5199 return NULL_TREE;
5200 }
5201
5202 /* If this is a custom GCC-internal format type, we have to
5203 initialize certain bits at runtime. */
5204 if (info.format_type == asm_fprintf_format_type
5205 || info.format_type == gcc_gfc_format_type
5206 || info.format_type == gcc_diag_format_type
5207 || info.format_type == gcc_tdiag_format_type
5208 || info.format_type == gcc_cdiag_format_type
5209 || info.format_type == gcc_cxxdiag_format_type
5210 || info.format_type == gcc_dump_printf_format_type)
5211 {
5212 /* Our first time through, we have to make sure that our
5213 format_type data is allocated dynamically and is modifiable. */
5214 if (!dynamic_format_types)
5215 format_types = dynamic_format_types = (format_kind_info *)
5216 xmemdup (format_types_orig, sizeof (format_types_orig),
5217 sizeof (format_types_orig));
5218
5219 /* If this is format __asm_fprintf__, we have to initialize
5220 GCC's notion of HOST_WIDE_INT for checking %wd. */
5221 if (info.format_type == asm_fprintf_format_type)
5222 init_dynamic_asm_fprintf_info ();
5223 /* If this is format __gcc_gfc__, we have to initialize GCC's
5224 notion of 'locus' at runtime for %L. */
5225 else if (info.format_type == gcc_gfc_format_type)
5226 init_dynamic_gfc_info ();
5227 /* If this is one of the diagnostic attributes, then we have to
5228 initialize 'location_t' and 'tree' at runtime. */
5229 else if (info.format_type == gcc_diag_format_type
5230 || info.format_type == gcc_tdiag_format_type
5231 || info.format_type == gcc_cdiag_format_type
5232 || info.format_type == gcc_cxxdiag_format_type
5233 || info.format_type == gcc_dump_printf_format_type)
5234 init_dynamic_diag_info ();
5235 else
5236 gcc_unreachable ();
5237 }
5238
5239 return NULL_TREE;
5240 }
5241
5242 #if CHECKING_P
5243
5244 namespace selftest {
5245
5246 /* Selftests of location handling. */
5247
5248 /* Get the format_kind_info with the given name. */
5249
5250 static const format_kind_info *
5251 get_info (const char *name)
5252 {
5253 int idx = decode_format_type (name);
5254 const format_kind_info *fki = &format_types[idx];
5255 ASSERT_STREQ (fki->name, name);
5256 return fki;
5257 }
5258
5259 /* Verify that get_format_for_type (FKI, TYPE, CONVERSION_CHAR)
5260 is EXPECTED_FORMAT. */
5261
5262 static void
5263 assert_format_for_type_streq (const location &loc, const format_kind_info *fki,
5264 const char *expected_format, tree type,
5265 char conversion_char)
5266 {
5267 gcc_assert (fki);
5268 gcc_assert (expected_format);
5269 gcc_assert (type);
5270
5271 char *actual_format = get_format_for_type (fki, type, conversion_char);
5272 ASSERT_STREQ_AT (loc, expected_format, actual_format);
5273 free (actual_format);
5274 }
5275
5276 /* Selftests for get_format_for_type. */
5277
5278 #define ASSERT_FORMAT_FOR_TYPE_STREQ(EXPECTED_FORMAT, TYPE, CONVERSION_CHAR) \
5279 assert_format_for_type_streq (SELFTEST_LOCATION, (fki), (EXPECTED_FORMAT), \
5280 (TYPE), (CONVERSION_CHAR))
5281
5282 /* Selftest for get_format_for_type for "printf"-style functions. */
5283
5284 static void
5285 test_get_format_for_type_printf ()
5286 {
5287 const format_kind_info *fki = get_info ("gnu_printf");
5288 ASSERT_NE (fki, NULL);
5289
5290 ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node, 'i');
5291 ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node, 'i');
5292 ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node, 'o');
5293 ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node, 'o');
5294 ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node, 'x');
5295 ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node, 'x');
5296 ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node, 'X');
5297 ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node, 'X');
5298 ASSERT_FORMAT_FOR_TYPE_STREQ ("d", integer_type_node, 'd');
5299 ASSERT_FORMAT_FOR_TYPE_STREQ ("i", integer_type_node, 'i');
5300 ASSERT_FORMAT_FOR_TYPE_STREQ ("o", integer_type_node, 'o');
5301 ASSERT_FORMAT_FOR_TYPE_STREQ ("x", integer_type_node, 'x');
5302 ASSERT_FORMAT_FOR_TYPE_STREQ ("X", integer_type_node, 'X');
5303 ASSERT_FORMAT_FOR_TYPE_STREQ ("d", unsigned_type_node, 'd');
5304 ASSERT_FORMAT_FOR_TYPE_STREQ ("i", unsigned_type_node, 'i');
5305 ASSERT_FORMAT_FOR_TYPE_STREQ ("o", unsigned_type_node, 'o');
5306 ASSERT_FORMAT_FOR_TYPE_STREQ ("x", unsigned_type_node, 'x');
5307 ASSERT_FORMAT_FOR_TYPE_STREQ ("X", unsigned_type_node, 'X');
5308 ASSERT_FORMAT_FOR_TYPE_STREQ ("ld", long_integer_type_node, 'd');
5309 ASSERT_FORMAT_FOR_TYPE_STREQ ("li", long_integer_type_node, 'i');
5310 ASSERT_FORMAT_FOR_TYPE_STREQ ("lx", long_integer_type_node, 'x');
5311 ASSERT_FORMAT_FOR_TYPE_STREQ ("lo", long_unsigned_type_node, 'o');
5312 ASSERT_FORMAT_FOR_TYPE_STREQ ("lx", long_unsigned_type_node, 'x');
5313 ASSERT_FORMAT_FOR_TYPE_STREQ ("lld", long_long_integer_type_node, 'd');
5314 ASSERT_FORMAT_FOR_TYPE_STREQ ("lli", long_long_integer_type_node, 'i');
5315 ASSERT_FORMAT_FOR_TYPE_STREQ ("llo", long_long_unsigned_type_node, 'o');
5316 ASSERT_FORMAT_FOR_TYPE_STREQ ("llx", long_long_unsigned_type_node, 'x');
5317 ASSERT_FORMAT_FOR_TYPE_STREQ ("s", build_pointer_type (char_type_node), 'i');
5318 }
5319
5320 /* Selftest for get_format_for_type for "scanf"-style functions. */
5321
5322 static void
5323 test_get_format_for_type_scanf ()
5324 {
5325 const format_kind_info *fki = get_info ("gnu_scanf");
5326 ASSERT_NE (fki, NULL);
5327 ASSERT_FORMAT_FOR_TYPE_STREQ ("d", build_pointer_type (integer_type_node), 'd');
5328 ASSERT_FORMAT_FOR_TYPE_STREQ ("u", build_pointer_type (unsigned_type_node), 'u');
5329 ASSERT_FORMAT_FOR_TYPE_STREQ ("ld",
5330 build_pointer_type (long_integer_type_node), 'd');
5331 ASSERT_FORMAT_FOR_TYPE_STREQ ("lu",
5332 build_pointer_type (long_unsigned_type_node), 'u');
5333 ASSERT_FORMAT_FOR_TYPE_STREQ
5334 ("lld", build_pointer_type (long_long_integer_type_node), 'd');
5335 ASSERT_FORMAT_FOR_TYPE_STREQ
5336 ("llu", build_pointer_type (long_long_unsigned_type_node), 'u');
5337 ASSERT_FORMAT_FOR_TYPE_STREQ ("e", build_pointer_type (float_type_node), 'e');
5338 ASSERT_FORMAT_FOR_TYPE_STREQ ("le", build_pointer_type (double_type_node), 'e');
5339 }
5340
5341 #undef ASSERT_FORMAT_FOR_TYPE_STREQ
5342
5343 /* Exercise the type-printing label code, to give some coverage
5344 under "make selftest-valgrind" (in particular, to ensure that
5345 the label-printing machinery doesn't leak). */
5346
5347 static void
5348 test_type_mismatch_range_labels ()
5349 {
5350 /* Create a tempfile and write some text to it.
5351 ....................0000000001 11111111 12 22222222
5352 ....................1234567890 12345678 90 12345678. */
5353 const char *content = " printf (\"msg: %i\\n\", msg);\n";
5354 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
5355 line_table_test ltt;
5356
5357 linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1);
5358
5359 location_t c17 = linemap_position_for_column (line_table, 17);
5360 ASSERT_EQ (LOCATION_COLUMN (c17), 17);
5361 location_t c18 = linemap_position_for_column (line_table, 18);
5362 location_t c24 = linemap_position_for_column (line_table, 24);
5363 location_t c26 = linemap_position_for_column (line_table, 26);
5364
5365 /* Don't attempt to run the tests if column data might be unavailable. */
5366 if (c26 > LINE_MAP_MAX_LOCATION_WITH_COLS)
5367 return;
5368
5369 location_t fmt = make_location (c18, c17, c18);
5370 ASSERT_EQ (LOCATION_COLUMN (fmt), 18);
5371
5372 location_t param = make_location (c24, c24, c26);
5373 ASSERT_EQ (LOCATION_COLUMN (param), 24);
5374
5375 range_label_for_format_type_mismatch fmt_label (char_type_node,
5376 integer_type_node, 1);
5377 range_label_for_type_mismatch param_label (integer_type_node,
5378 char_type_node);
5379 gcc_rich_location richloc (fmt, &fmt_label);
5380 richloc.add_range (param, SHOW_RANGE_WITHOUT_CARET, &param_label);
5381
5382 test_diagnostic_context dc;
5383 diagnostic_show_locus (&dc, &richloc, DK_ERROR);
5384 if (c_dialect_cxx ())
5385 /* "char*", without a space. */
5386 ASSERT_STREQ ("\n"
5387 " printf (\"msg: %i\\n\", msg);\n"
5388 " ~^ ~~~\n"
5389 " | |\n"
5390 " char* int\n",
5391 pp_formatted_text (dc.printer));
5392 else
5393 /* "char *", with a space. */
5394 ASSERT_STREQ ("\n"
5395 " printf (\"msg: %i\\n\", msg);\n"
5396 " ~^ ~~~\n"
5397 " | |\n"
5398 " | int\n"
5399 " char *\n",
5400 pp_formatted_text (dc.printer));
5401 }
5402
5403 /* Run all of the selftests within this file. */
5404
5405 void
5406 c_format_c_tests ()
5407 {
5408 test_get_modifier_for_format_len ();
5409 test_get_format_for_type_printf ();
5410 test_get_format_for_type_scanf ();
5411 test_type_mismatch_range_labels ();
5412 }
5413
5414 } // namespace selftest
5415
5416 #endif /* CHECKING_P */
5417
5418 #include "gt-c-family-c-format.h"