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