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