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