Mercurial > hg > CbC > CbC_gcc
comparison gcc/c-family/c-format.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | 561a7518be6b |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* Check calls to formatted I/O functions (-Wformat). | 1 /* Check calls to formatted I/O functions (-Wformat). |
2 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, | 2 Copyright (C) 1992-2017 Free Software Foundation, Inc. |
3 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 | |
4 Free Software Foundation, Inc. | |
5 | 3 |
6 This file is part of GCC. | 4 This file is part of GCC. |
7 | 5 |
8 GCC is free software; you can redistribute it and/or modify it under | 6 GCC is free software; you can redistribute it and/or modify it under |
9 the terms of the GNU General Public License as published by the Free | 7 the terms of the GNU General Public License as published by the Free |
21 | 19 |
22 #include "config.h" | 20 #include "config.h" |
23 #include "system.h" | 21 #include "system.h" |
24 #include "coretypes.h" | 22 #include "coretypes.h" |
25 #include "tm.h" | 23 #include "tm.h" |
26 #include "tree.h" | 24 #include "c-target.h" |
27 #include "flags.h" | |
28 #include "c-common.h" | 25 #include "c-common.h" |
26 #include "alloc-pool.h" | |
27 #include "stringpool.h" | |
29 #include "c-objc.h" | 28 #include "c-objc.h" |
30 #include "intl.h" | 29 #include "intl.h" |
31 #include "diagnostic-core.h" | |
32 #include "langhooks.h" | 30 #include "langhooks.h" |
33 #include "c-format.h" | 31 #include "c-format.h" |
34 #include "alloc-pool.h" | 32 #include "diagnostic.h" |
35 #include "target.h" | 33 #include "substring-locations.h" |
36 | 34 #include "selftest.h" |
37 /* Set format warning options according to a -Wformat=n option. */ | 35 #include "builtins.h" |
38 | 36 #include "attribs.h" |
39 void | 37 |
40 set_Wformat (int setting) | |
41 { | |
42 warn_format = setting; | |
43 warn_format_extra_args = setting; | |
44 warn_format_zero_length = setting; | |
45 warn_format_contains_nul = setting; | |
46 if (setting != 1) | |
47 { | |
48 warn_format_nonliteral = setting; | |
49 warn_format_security = setting; | |
50 warn_format_y2k = setting; | |
51 } | |
52 /* Make sure not to disable -Wnonnull if -Wformat=0 is specified. */ | |
53 if (setting) | |
54 warn_nonnull = setting; | |
55 } | |
56 | |
57 | |
58 /* Handle attributes associated with format checking. */ | 38 /* Handle attributes associated with format checking. */ |
59 | 39 |
60 /* This must be in the same order as format_types, except for | 40 /* This must be in the same order as format_types, except for |
61 format_type_error. Target-specific format types do not have | 41 format_type_error. Target-specific format types do not have |
62 matching enum values. */ | 42 matching enum values. */ |
65 gcc_cdiag_format_type, | 45 gcc_cdiag_format_type, |
66 gcc_cxxdiag_format_type, gcc_gfc_format_type, | 46 gcc_cxxdiag_format_type, gcc_gfc_format_type, |
67 gcc_objc_string_format_type, | 47 gcc_objc_string_format_type, |
68 format_type_error = -1}; | 48 format_type_error = -1}; |
69 | 49 |
70 typedef struct function_format_info | 50 struct function_format_info |
71 { | 51 { |
72 int format_type; /* type of format (printf, scanf, etc.) */ | 52 int format_type; /* type of format (printf, scanf, etc.) */ |
73 unsigned HOST_WIDE_INT format_num; /* number of format argument */ | 53 unsigned HOST_WIDE_INT format_num; /* number of format argument */ |
74 unsigned HOST_WIDE_INT first_arg_num; /* number of first arg (zero for varargs) */ | 54 unsigned HOST_WIDE_INT first_arg_num; /* number of first arg (zero for varargs) */ |
75 } function_format_info; | 55 }; |
56 | |
57 /* Initialized in init_dynamic_diag_info. */ | |
58 static GTY(()) tree local_tree_type_node; | |
59 static GTY(()) tree local_gcall_ptr_node; | |
60 static GTY(()) tree locus; | |
76 | 61 |
77 static bool decode_format_attr (tree, function_format_info *, int); | 62 static bool decode_format_attr (tree, function_format_info *, int); |
78 static int decode_format_type (const char *); | 63 static int decode_format_type (const char *); |
79 | 64 |
80 static bool check_format_string (tree argument, | 65 static bool check_format_string (tree argument, |
82 int flags, bool *no_add_attrs, | 67 int flags, bool *no_add_attrs, |
83 int expected_format_type); | 68 int expected_format_type); |
84 static bool get_constant (tree expr, unsigned HOST_WIDE_INT *value, | 69 static bool get_constant (tree expr, unsigned HOST_WIDE_INT *value, |
85 int validated_p); | 70 int validated_p); |
86 static const char *convert_format_name_to_system_name (const char *attr_name); | 71 static const char *convert_format_name_to_system_name (const char *attr_name); |
87 static bool cmp_attribs (const char *tattr_name, const char *attr_name); | |
88 | 72 |
89 static int first_target_format_type; | 73 static int first_target_format_type; |
90 static const char *format_name (int format_num); | 74 static const char *format_name (int format_num); |
91 static int format_flags (int format_num); | 75 static int format_flags (int format_num); |
76 | |
77 /* Emit a warning as per format_warning_va, but construct the substring_loc | |
78 for the character at offset (CHAR_IDX - 1) within a string constant | |
79 FORMAT_STRING_CST at FMT_STRING_LOC. */ | |
80 | |
81 ATTRIBUTE_GCC_DIAG (5,6) | |
82 static bool | |
83 format_warning_at_char (location_t fmt_string_loc, tree format_string_cst, | |
84 int char_idx, int opt, const char *gmsgid, ...) | |
85 { | |
86 va_list ap; | |
87 va_start (ap, gmsgid); | |
88 tree string_type = TREE_TYPE (format_string_cst); | |
89 | |
90 /* The callers are of the form: | |
91 format_warning (format_string_loc, format_string_cst, | |
92 format_chars - orig_format_chars, | |
93 where format_chars has already been incremented, so that | |
94 CHAR_IDX is one character beyond where the warning should | |
95 be emitted. Fix it. */ | |
96 char_idx -= 1; | |
97 | |
98 substring_loc fmt_loc (fmt_string_loc, string_type, char_idx, char_idx, | |
99 char_idx); | |
100 bool warned = format_warning_va (fmt_loc, UNKNOWN_LOCATION, NULL, opt, | |
101 gmsgid, &ap); | |
102 va_end (ap); | |
103 | |
104 return warned; | |
105 } | |
92 | 106 |
93 /* Check that we have a pointer to a string suitable for use as a format. | 107 /* Check that we have a pointer to a string suitable for use as a format. |
94 The default is to check for a char type. | 108 The default is to check for a char type. |
95 For objective-c dialects, this is extended to include references to string | 109 For objective-c dialects, this is extended to include references to string |
96 objects validated by objc_string_ref_type_p (). | 110 objects validated by objc_string_ref_type_p (). |
118 tree args, int flags, bool *no_add_attrs) | 132 tree args, int flags, bool *no_add_attrs) |
119 { | 133 { |
120 tree type = *node; | 134 tree type = *node; |
121 tree format_num_expr = TREE_VALUE (args); | 135 tree format_num_expr = TREE_VALUE (args); |
122 unsigned HOST_WIDE_INT format_num = 0; | 136 unsigned HOST_WIDE_INT format_num = 0; |
123 tree argument; | |
124 | 137 |
125 if (!get_constant (format_num_expr, &format_num, 0)) | 138 if (!get_constant (format_num_expr, &format_num, 0)) |
126 { | 139 { |
127 error ("format string has invalid operand number"); | 140 error ("format string has invalid operand number"); |
128 *no_add_attrs = true; | 141 *no_add_attrs = true; |
129 return NULL_TREE; | 142 return NULL_TREE; |
130 } | 143 } |
131 | 144 |
132 argument = TYPE_ARG_TYPES (type); | 145 if (prototype_p (type)) |
133 if (argument) | |
134 { | 146 { |
135 /* The format arg can be any string reference valid for the language and | 147 /* The format arg can be any string reference valid for the language and |
136 target. We cannot be more specific in this case. */ | 148 target. We cannot be more specific in this case. */ |
137 if (!check_format_string (argument, format_num, flags, no_add_attrs, -1)) | 149 if (!check_format_string (type, format_num, flags, no_add_attrs, -1)) |
138 return NULL_TREE; | 150 return NULL_TREE; |
139 } | 151 } |
140 | 152 |
141 if (!valid_stringptr_type_p (TREE_TYPE (type))) | 153 if (!valid_stringptr_type_p (TREE_TYPE (type))) |
142 { | 154 { |
152 /* Verify that the format_num argument is actually a string reference suitable, | 164 /* Verify that the format_num argument is actually a string reference suitable, |
153 for the language dialect and target (in case the format attribute is in | 165 for the language dialect and target (in case the format attribute is in |
154 error). When we know the specific reference type expected, this is also | 166 error). When we know the specific reference type expected, this is also |
155 checked. */ | 167 checked. */ |
156 static bool | 168 static bool |
157 check_format_string (tree argument, unsigned HOST_WIDE_INT format_num, | 169 check_format_string (tree fntype, unsigned HOST_WIDE_INT format_num, |
158 int flags, bool *no_add_attrs, int expected_format_type) | 170 int flags, bool *no_add_attrs, int expected_format_type) |
159 { | 171 { |
160 unsigned HOST_WIDE_INT i; | 172 unsigned HOST_WIDE_INT i; |
161 bool is_objc_sref, is_target_sref, is_char_ref; | 173 bool is_objc_sref, is_target_sref, is_char_ref; |
162 tree ref; | 174 tree ref; |
163 int fmt_flags; | 175 int fmt_flags; |
164 | 176 function_args_iterator iter; |
165 for (i = 1; i != format_num; i++) | 177 |
166 { | 178 i = 1; |
167 if (argument == 0) | 179 FOREACH_FUNCTION_ARGS (fntype, ref, iter) |
180 { | |
181 if (i == format_num) | |
168 break; | 182 break; |
169 argument = TREE_CHAIN (argument); | 183 i++; |
170 } | 184 } |
171 | 185 |
172 if (!argument | 186 if (!ref |
173 || !(ref = TREE_VALUE (argument)) | |
174 || !valid_stringptr_type_p (ref)) | 187 || !valid_stringptr_type_p (ref)) |
175 { | 188 { |
176 if (!(flags & (int) ATTR_FLAG_BUILT_IN)) | 189 if (!(flags & (int) ATTR_FLAG_BUILT_IN)) |
177 error ("format string argument is not a string type"); | 190 error ("format string argument is not a string type"); |
178 *no_add_attrs = true; | 191 *no_add_attrs = true; |
198 return true; /* OK, we expected a char and found one. */ | 211 return true; /* OK, we expected a char and found one. */ |
199 else | 212 else |
200 { | 213 { |
201 /* We expected a char but found an extended string type. */ | 214 /* We expected a char but found an extended string type. */ |
202 if (is_objc_sref) | 215 if (is_objc_sref) |
203 error ("found a %<%s%> reference but the format argument should" | 216 error ("found a %qs reference but the format argument should" |
204 " be a string", format_name (gcc_objc_string_format_type)); | 217 " be a string", format_name (gcc_objc_string_format_type)); |
205 else | 218 else |
206 error ("found a %qT but the format argument should be a string", | 219 error ("found a %qT but the format argument should be a string", |
207 ref); | 220 ref); |
208 *no_add_attrs = true; | 221 *no_add_attrs = true; |
211 } | 224 } |
212 | 225 |
213 /* We expect a string object type as the format arg. */ | 226 /* We expect a string object type as the format arg. */ |
214 if (is_char_ref) | 227 if (is_char_ref) |
215 { | 228 { |
216 error ("format argument should be a %<%s%> reference but" | 229 error ("format argument should be a %qs reference but" |
217 " a string was found", format_name (expected_format_type)); | 230 " a string was found", format_name (expected_format_type)); |
218 *no_add_attrs = true; | 231 *no_add_attrs = true; |
219 return false; | 232 return false; |
220 } | 233 } |
221 | 234 |
233 && expected_format_type >= first_target_format_type | 246 && expected_format_type >= first_target_format_type |
234 && is_target_sref) | 247 && is_target_sref) |
235 return true; | 248 return true; |
236 else | 249 else |
237 { | 250 { |
238 error ("format argument should be a %<%s%> reference", | 251 error ("format argument should be a %qs reference", |
239 format_name (expected_format_type)); | 252 format_name (expected_format_type)); |
240 *no_add_attrs = true; | 253 *no_add_attrs = true; |
241 return false; | 254 return false; |
242 } | 255 } |
243 | 256 |
248 If validated_p is true there should be no errors. | 261 If validated_p is true there should be no errors. |
249 Returns true on success, false otherwise. */ | 262 Returns true on success, false otherwise. */ |
250 static bool | 263 static bool |
251 get_constant (tree expr, unsigned HOST_WIDE_INT *value, int validated_p) | 264 get_constant (tree expr, unsigned HOST_WIDE_INT *value, int validated_p) |
252 { | 265 { |
253 if (TREE_CODE (expr) != INTEGER_CST || TREE_INT_CST_HIGH (expr) != 0) | 266 if (!tree_fits_uhwi_p (expr)) |
254 { | 267 { |
255 gcc_assert (!validated_p); | 268 gcc_assert (!validated_p); |
256 return false; | 269 return false; |
257 } | 270 } |
258 | 271 |
292 | 305 |
293 if (!c_dialect_objc () | 306 if (!c_dialect_objc () |
294 && info->format_type == gcc_objc_string_format_type) | 307 && info->format_type == gcc_objc_string_format_type) |
295 { | 308 { |
296 gcc_assert (!validated_p); | 309 gcc_assert (!validated_p); |
297 warning (OPT_Wformat, "%qE is only allowed in Objective-C dialects", | 310 warning (OPT_Wformat_, "%qE is only allowed in Objective-C dialects", |
298 format_type_id); | 311 format_type_id); |
299 info->format_type = format_type_error; | 312 info->format_type = format_type_error; |
300 return false; | 313 return false; |
301 } | 314 } |
302 | 315 |
303 if (info->format_type == format_type_error) | 316 if (info->format_type == format_type_error) |
304 { | 317 { |
305 gcc_assert (!validated_p); | 318 gcc_assert (!validated_p); |
306 warning (OPT_Wformat, "%qE is an unrecognized format function type", | 319 warning (OPT_Wformat_, "%qE is an unrecognized format function type", |
307 format_type_id); | 320 format_type_id); |
308 return false; | 321 return false; |
309 } | 322 } |
310 } | 323 } |
311 | 324 |
333 | 346 |
334 /* Check a call to a format function against a parameter list. */ | 347 /* Check a call to a format function against a parameter list. */ |
335 | 348 |
336 /* The C standard version C++ is treated as equivalent to | 349 /* The C standard version C++ is treated as equivalent to |
337 or inheriting from, for the purpose of format features supported. */ | 350 or inheriting from, for the purpose of format features supported. */ |
338 #define CPLUSPLUS_STD_VER STD_C94 | 351 #define CPLUSPLUS_STD_VER (cxx_dialect < cxx11 ? STD_C94 : STD_C99) |
339 /* The C standard version we are checking formats against when pedantic. */ | 352 /* The C standard version we are checking formats against when pedantic. */ |
340 #define C_STD_VER ((int) (c_dialect_cxx () \ | 353 #define C_STD_VER ((int) (c_dialect_cxx () \ |
341 ? CPLUSPLUS_STD_VER \ | 354 ? CPLUSPLUS_STD_VER \ |
342 : (flag_isoc99 \ | 355 : (flag_isoc99 \ |
343 ? STD_C99 \ | 356 ? STD_C99 \ |
344 : (flag_isoc94 ? STD_C94 : STD_C89)))) | 357 : (flag_isoc94 ? STD_C94 : STD_C89)))) |
345 /* The name to give to the standard version we are warning about when | 358 /* The name to give to the standard version we are warning about when |
346 pedantic. FEATURE_VER is the version in which the feature warned out | 359 pedantic. FEATURE_VER is the version in which the feature warned out |
347 appeared, which is higher than C_STD_VER. */ | 360 appeared, which is higher than C_STD_VER. */ |
348 #define C_STD_NAME(FEATURE_VER) (c_dialect_cxx () \ | 361 #define C_STD_NAME(FEATURE_VER) (c_dialect_cxx () \ |
349 ? "ISO C++" \ | 362 ? (cxx_dialect < cxx11 ? "ISO C++98" \ |
363 : "ISO C++11") \ | |
350 : ((FEATURE_VER) == STD_EXT \ | 364 : ((FEATURE_VER) == STD_EXT \ |
351 ? "ISO C" \ | 365 ? "ISO C" \ |
352 : "ISO C90")) | 366 : "ISO C90")) |
353 /* Adjust a C standard version, which may be STD_C9L, to account for | 367 /* Adjust a C standard version, which may be STD_C9L, to account for |
354 -Wno-long-long. Returns other standard versions unchanged. */ | 368 -Wno-long-long. Returns other standard versions unchanged. */ |
370 N_("field precision specifier") | 384 N_("field precision specifier") |
371 }; | 385 }; |
372 | 386 |
373 /* Structure describing details of a type expected in format checking, | 387 /* Structure describing details of a type expected in format checking, |
374 and the type to check against it. */ | 388 and the type to check against it. */ |
375 typedef struct format_wanted_type | 389 struct format_wanted_type |
376 { | 390 { |
377 /* The type wanted. */ | 391 /* The type wanted. */ |
378 tree wanted_type; | 392 tree wanted_type; |
379 /* The name of this type to use in diagnostics. */ | 393 /* The name of this type to use in diagnostics. */ |
380 const char *wanted_type_name; | 394 const char *wanted_type_name; |
400 int format_length; | 414 int format_length; |
401 /* The actual parameter to check against the wanted type. */ | 415 /* The actual parameter to check against the wanted type. */ |
402 tree param; | 416 tree param; |
403 /* The argument number of that parameter. */ | 417 /* The argument number of that parameter. */ |
404 int arg_num; | 418 int arg_num; |
419 /* The offset location of this argument with respect to the format | |
420 string location. */ | |
421 unsigned int offset_loc; | |
405 /* The next type to check for this format conversion, or NULL if none. */ | 422 /* The next type to check for this format conversion, or NULL if none. */ |
406 struct format_wanted_type *next; | 423 struct format_wanted_type *next; |
407 } format_wanted_type; | 424 }; |
408 | 425 |
409 /* Convenience macro for format_length_info meaning unused. */ | 426 /* Convenience macro for format_length_info meaning unused. */ |
410 #define NO_FMT NULL, FMT_LEN_none, STD_C89 | 427 #define NO_FMT NULL, FMT_LEN_none, STD_C89 |
411 | 428 |
412 static const format_length_info printf_length_specs[] = | 429 static const format_length_info printf_length_specs[] = |
479 }; | 496 }; |
480 | 497 |
481 | 498 |
482 static const format_flag_spec printf_flag_specs[] = | 499 static const format_flag_spec printf_flag_specs[] = |
483 { | 500 { |
484 { ' ', 0, 0, N_("' ' flag"), N_("the ' ' printf flag"), STD_C89 }, | 501 { ' ', 0, 0, 0, N_("' ' flag"), N_("the ' ' printf flag"), STD_C89 }, |
485 { '+', 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89 }, | 502 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89 }, |
486 { '#', 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89 }, | 503 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89 }, |
487 { '0', 0, 0, N_("'0' flag"), N_("the '0' printf flag"), STD_C89 }, | 504 { '0', 0, 0, 0, N_("'0' flag"), N_("the '0' printf flag"), STD_C89 }, |
488 { '-', 0, 0, N_("'-' flag"), N_("the '-' printf flag"), STD_C89 }, | 505 { '-', 0, 0, 0, N_("'-' flag"), N_("the '-' printf flag"), STD_C89 }, |
489 { '\'', 0, 0, N_("''' flag"), N_("the ''' printf flag"), STD_EXT }, | 506 { '\'', 0, 0, 0, N_("''' flag"), N_("the ''' printf flag"), STD_EXT }, |
490 { 'I', 0, 0, N_("'I' flag"), N_("the 'I' printf flag"), STD_EXT }, | 507 { 'I', 0, 0, 0, N_("'I' flag"), N_("the 'I' printf flag"), STD_EXT }, |
491 { 'w', 0, 0, N_("field width"), N_("field width in printf format"), STD_C89 }, | 508 { 'w', 0, 0, 0, N_("field width"), N_("field width in printf format"), STD_C89 }, |
492 { 'p', 0, 0, N_("precision"), N_("precision in printf format"), STD_C89 }, | 509 { 'p', 0, 0, 0, N_("precision"), N_("precision in printf format"), STD_C89 }, |
493 { 'L', 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 }, | 510 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 }, |
494 { 0, 0, 0, NULL, NULL, STD_C89 } | 511 { 0, 0, 0, 0, NULL, NULL, STD_C89 } |
495 }; | 512 }; |
496 | 513 |
497 | 514 |
498 static const format_flag_pair printf_flag_pairs[] = | 515 static const format_flag_pair printf_flag_pairs[] = |
499 { | 516 { |
503 { 0, 0, 0, 0 } | 520 { 0, 0, 0, 0 } |
504 }; | 521 }; |
505 | 522 |
506 static const format_flag_spec asm_fprintf_flag_specs[] = | 523 static const format_flag_spec asm_fprintf_flag_specs[] = |
507 { | 524 { |
508 { ' ', 0, 0, N_("' ' flag"), N_("the ' ' printf flag"), STD_C89 }, | 525 { ' ', 0, 0, 0, N_("' ' flag"), N_("the ' ' printf flag"), STD_C89 }, |
509 { '+', 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89 }, | 526 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89 }, |
510 { '#', 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89 }, | 527 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89 }, |
511 { '0', 0, 0, N_("'0' flag"), N_("the '0' printf flag"), STD_C89 }, | 528 { '0', 0, 0, 0, N_("'0' flag"), N_("the '0' printf flag"), STD_C89 }, |
512 { '-', 0, 0, N_("'-' flag"), N_("the '-' printf flag"), STD_C89 }, | 529 { '-', 0, 0, 0, N_("'-' flag"), N_("the '-' printf flag"), STD_C89 }, |
513 { 'w', 0, 0, N_("field width"), N_("field width in printf format"), STD_C89 }, | 530 { 'w', 0, 0, 0, N_("field width"), N_("field width in printf format"), STD_C89 }, |
514 { 'p', 0, 0, N_("precision"), N_("precision in printf format"), STD_C89 }, | 531 { 'p', 0, 0, 0, N_("precision"), N_("precision in printf format"), STD_C89 }, |
515 { 'L', 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 }, | 532 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 }, |
516 { 0, 0, 0, NULL, NULL, STD_C89 } | 533 { 0, 0, 0, 0, NULL, NULL, STD_C89 } |
517 }; | 534 }; |
518 | 535 |
519 static const format_flag_pair asm_fprintf_flag_pairs[] = | 536 static const format_flag_pair asm_fprintf_flag_pairs[] = |
520 { | 537 { |
521 { ' ', '+', 1, 0 }, | 538 { ' ', '+', 1, 0 }, |
530 }; | 547 }; |
531 | 548 |
532 #define gcc_tdiag_flag_pairs gcc_diag_flag_pairs | 549 #define gcc_tdiag_flag_pairs gcc_diag_flag_pairs |
533 #define gcc_cdiag_flag_pairs gcc_diag_flag_pairs | 550 #define gcc_cdiag_flag_pairs gcc_diag_flag_pairs |
534 #define gcc_cxxdiag_flag_pairs gcc_diag_flag_pairs | 551 #define gcc_cxxdiag_flag_pairs gcc_diag_flag_pairs |
535 | 552 #define gcc_gfc_flag_pairs gcc_diag_flag_pairs |
536 static const format_flag_pair gcc_gfc_flag_pairs[] = | |
537 { | |
538 { 0, 0, 0, 0 } | |
539 }; | |
540 | 553 |
541 static const format_flag_spec gcc_diag_flag_specs[] = | 554 static const format_flag_spec gcc_diag_flag_specs[] = |
542 { | 555 { |
543 { '+', 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89 }, | 556 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89 }, |
544 { '#', 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89 }, | 557 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89 }, |
545 { 'q', 0, 0, N_("'q' flag"), N_("the 'q' diagnostic flag"), STD_C89 }, | 558 { 'q', 0, 0, 1, N_("'q' flag"), N_("the 'q' diagnostic flag"), STD_C89 }, |
546 { 'p', 0, 0, N_("precision"), N_("precision in printf format"), STD_C89 }, | 559 { 'p', 0, 0, 0, N_("precision"), N_("precision in printf format"), STD_C89 }, |
547 { 'L', 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 }, | 560 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 }, |
548 { 0, 0, 0, NULL, NULL, STD_C89 } | 561 { 0, 0, 0, 0, NULL, NULL, STD_C89 } |
549 }; | 562 }; |
550 | 563 |
551 #define gcc_tdiag_flag_specs gcc_diag_flag_specs | 564 #define gcc_tdiag_flag_specs gcc_diag_flag_specs |
552 #define gcc_cdiag_flag_specs gcc_diag_flag_specs | 565 #define gcc_cdiag_flag_specs gcc_diag_flag_specs |
553 #define gcc_cxxdiag_flag_specs gcc_diag_flag_specs | 566 #define gcc_cxxdiag_flag_specs gcc_diag_flag_specs |
567 #define gcc_gfc_flag_specs gcc_diag_flag_specs | |
554 | 568 |
555 static const format_flag_spec scanf_flag_specs[] = | 569 static const format_flag_spec scanf_flag_specs[] = |
556 { | 570 { |
557 { '*', 0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89 }, | 571 { '*', 0, 0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89 }, |
558 { 'a', 0, 0, N_("'a' flag"), N_("the 'a' scanf flag"), STD_EXT }, | 572 { 'a', 0, 0, 0, N_("'a' flag"), N_("the 'a' scanf flag"), STD_EXT }, |
559 { 'm', 0, 0, N_("'m' flag"), N_("the 'm' scanf flag"), STD_EXT }, | 573 { 'm', 0, 0, 0, N_("'m' flag"), N_("the 'm' scanf flag"), STD_EXT }, |
560 { 'w', 0, 0, N_("field width"), N_("field width in scanf format"), STD_C89 }, | 574 { 'w', 0, 0, 0, N_("field width"), N_("field width in scanf format"), STD_C89 }, |
561 { 'L', 0, 0, N_("length modifier"), N_("length modifier in scanf format"), STD_C89 }, | 575 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in scanf format"), STD_C89 }, |
562 { '\'', 0, 0, N_("''' flag"), N_("the ''' scanf flag"), STD_EXT }, | 576 { '\'', 0, 0, 0, N_("''' flag"), N_("the ''' scanf flag"), STD_EXT }, |
563 { 'I', 0, 0, N_("'I' flag"), N_("the 'I' scanf flag"), STD_EXT }, | 577 { 'I', 0, 0, 0, N_("'I' flag"), N_("the 'I' scanf flag"), STD_EXT }, |
564 { 0, 0, 0, NULL, NULL, STD_C89 } | 578 { 0, 0, 0, 0, NULL, NULL, STD_C89 } |
565 }; | 579 }; |
566 | 580 |
567 | 581 |
568 static const format_flag_pair scanf_flag_pairs[] = | 582 static const format_flag_pair scanf_flag_pairs[] = |
569 { | 583 { |
573 }; | 587 }; |
574 | 588 |
575 | 589 |
576 static const format_flag_spec strftime_flag_specs[] = | 590 static const format_flag_spec strftime_flag_specs[] = |
577 { | 591 { |
578 { '_', 0, 0, N_("'_' flag"), N_("the '_' strftime flag"), STD_EXT }, | 592 { '_', 0, 0, 0, N_("'_' flag"), N_("the '_' strftime flag"), STD_EXT }, |
579 { '-', 0, 0, N_("'-' flag"), N_("the '-' strftime flag"), STD_EXT }, | 593 { '-', 0, 0, 0, N_("'-' flag"), N_("the '-' strftime flag"), STD_EXT }, |
580 { '0', 0, 0, N_("'0' flag"), N_("the '0' strftime flag"), STD_EXT }, | 594 { '0', 0, 0, 0, N_("'0' flag"), N_("the '0' strftime flag"), STD_EXT }, |
581 { '^', 0, 0, N_("'^' flag"), N_("the '^' strftime flag"), STD_EXT }, | 595 { '^', 0, 0, 0, N_("'^' flag"), N_("the '^' strftime flag"), STD_EXT }, |
582 { '#', 0, 0, N_("'#' flag"), N_("the '#' strftime flag"), STD_EXT }, | 596 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' strftime flag"), STD_EXT }, |
583 { 'w', 0, 0, N_("field width"), N_("field width in strftime format"), STD_EXT }, | 597 { 'w', 0, 0, 0, N_("field width"), N_("field width in strftime format"), STD_EXT }, |
584 { 'E', 0, 0, N_("'E' modifier"), N_("the 'E' strftime modifier"), STD_C99 }, | 598 { 'E', 0, 0, 0, N_("'E' modifier"), N_("the 'E' strftime modifier"), STD_C99 }, |
585 { 'O', 0, 0, N_("'O' modifier"), N_("the 'O' strftime modifier"), STD_C99 }, | 599 { 'O', 0, 0, 0, N_("'O' modifier"), N_("the 'O' strftime modifier"), STD_C99 }, |
586 { 'O', 'o', 0, NULL, N_("the 'O' modifier"), STD_EXT }, | 600 { 'O', 'o', 0, 0, NULL, N_("the 'O' modifier"), STD_EXT }, |
587 { 0, 0, 0, NULL, NULL, STD_C89 } | 601 { 0, 0, 0, 0, NULL, NULL, STD_C89 } |
588 }; | 602 }; |
589 | 603 |
590 | 604 |
591 static const format_flag_pair strftime_flag_pairs[] = | 605 static const format_flag_pair strftime_flag_pairs[] = |
592 { | 606 { |
599 }; | 613 }; |
600 | 614 |
601 | 615 |
602 static const format_flag_spec strfmon_flag_specs[] = | 616 static const format_flag_spec strfmon_flag_specs[] = |
603 { | 617 { |
604 { '=', 0, 1, N_("fill character"), N_("fill character in strfmon format"), STD_C89 }, | 618 { '=', 0, 1, 0, N_("fill character"), N_("fill character in strfmon format"), STD_C89 }, |
605 { '^', 0, 0, N_("'^' flag"), N_("the '^' strfmon flag"), STD_C89 }, | 619 { '^', 0, 0, 0, N_("'^' flag"), N_("the '^' strfmon flag"), STD_C89 }, |
606 { '+', 0, 0, N_("'+' flag"), N_("the '+' strfmon flag"), STD_C89 }, | 620 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' strfmon flag"), STD_C89 }, |
607 { '(', 0, 0, N_("'(' flag"), N_("the '(' strfmon flag"), STD_C89 }, | 621 { '(', 0, 0, 0, N_("'(' flag"), N_("the '(' strfmon flag"), STD_C89 }, |
608 { '!', 0, 0, N_("'!' flag"), N_("the '!' strfmon flag"), STD_C89 }, | 622 { '!', 0, 0, 0, N_("'!' flag"), N_("the '!' strfmon flag"), STD_C89 }, |
609 { '-', 0, 0, N_("'-' flag"), N_("the '-' strfmon flag"), STD_C89 }, | 623 { '-', 0, 0, 0, N_("'-' flag"), N_("the '-' strfmon flag"), STD_C89 }, |
610 { 'w', 0, 0, N_("field width"), N_("field width in strfmon format"), STD_C89 }, | 624 { 'w', 0, 0, 0, N_("field width"), N_("field width in strfmon format"), STD_C89 }, |
611 { '#', 0, 0, N_("left precision"), N_("left precision in strfmon format"), STD_C89 }, | 625 { '#', 0, 0, 0, N_("left precision"), N_("left precision in strfmon format"), STD_C89 }, |
612 { 'p', 0, 0, N_("right precision"), N_("right precision in strfmon format"), STD_C89 }, | 626 { 'p', 0, 0, 0, N_("right precision"), N_("right precision in strfmon format"), STD_C89 }, |
613 { 'L', 0, 0, N_("length modifier"), N_("length modifier in strfmon format"), STD_C89 }, | 627 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in strfmon format"), STD_C89 }, |
614 { 0, 0, 0, NULL, NULL, STD_C89 } | 628 { 0, 0, 0, 0, NULL, NULL, STD_C89 } |
615 }; | 629 }; |
616 | 630 |
617 static const format_flag_pair strfmon_flag_pairs[] = | 631 static const format_flag_pair strfmon_flag_pairs[] = |
618 { | 632 { |
619 { '+', '(', 0, 0 }, | 633 { '+', '(', 0, 0 }, |
658 { "R", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | 672 { "R", 0, STD_C89, NOARGUMENTS, "", "", NULL }, |
659 { "I", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | 673 { "I", 0, STD_C89, NOARGUMENTS, "", "", NULL }, |
660 { "L", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | 674 { "L", 0, STD_C89, NOARGUMENTS, "", "", NULL }, |
661 { "U", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | 675 { "U", 0, STD_C89, NOARGUMENTS, "", "", NULL }, |
662 { "r", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", NULL }, | 676 { "r", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", NULL }, |
677 { "z", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | |
663 { "@", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | 678 { "@", 0, STD_C89, NOARGUMENTS, "", "", NULL }, |
664 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } | 679 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } |
665 }; | 680 }; |
666 | 681 |
667 static const format_char_info gcc_diag_char_table[] = | 682 static const format_char_info gcc_diag_char_table[] = |
674 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL }, | 689 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL }, |
675 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, | 690 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, |
676 | 691 |
677 /* Custom conversion specifiers. */ | 692 /* Custom conversion specifiers. */ |
678 | 693 |
679 /* These will require a "tree" at runtime. */ | 694 /* G requires a "gcall*" argument at runtime. */ |
680 { "K", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | 695 { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, |
681 | 696 /* K requires a "tree" argument at runtime. */ |
682 { "<>'", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | 697 { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, |
698 | |
699 { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "//cR", NULL }, | |
700 { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL }, | |
701 { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL }, | |
702 { "'" , 0, STD_C89, NOARGUMENTS, "", "", NULL }, | |
703 { "R", 0, STD_C89, NOARGUMENTS, "", "\\", NULL }, | |
683 { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, | 704 { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, |
684 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } | 705 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } |
685 }; | 706 }; |
686 | 707 |
687 static const format_char_info gcc_tdiag_char_table[] = | 708 static const format_char_info gcc_tdiag_char_table[] = |
695 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, | 716 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, |
696 | 717 |
697 /* Custom conversion specifiers. */ | 718 /* Custom conversion specifiers. */ |
698 | 719 |
699 /* These will require a "tree" at runtime. */ | 720 /* These will require a "tree" at runtime. */ |
700 { "DFKTEV", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL }, | 721 { "DFTV", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "'", NULL }, |
701 | 722 { "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL }, |
702 { "v", 0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL }, | 723 { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, |
703 | 724 |
704 { "<>'", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | 725 /* G requires a "gcall*" argument at runtime. */ |
726 { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, | |
727 | |
728 { "v", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL }, | |
729 | |
730 { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "/cR", NULL }, | |
731 { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL }, | |
732 { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL }, | |
733 { "'", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | |
734 { "R", 0, STD_C89, NOARGUMENTS, "", "\\", NULL }, | |
705 { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, | 735 { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, |
736 { "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_tdiag_char_table[0] }, | |
706 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } | 737 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } |
707 }; | 738 }; |
708 | 739 |
709 static const format_char_info gcc_cdiag_char_table[] = | 740 static const format_char_info gcc_cdiag_char_table[] = |
710 { | 741 { |
717 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, | 748 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, |
718 | 749 |
719 /* Custom conversion specifiers. */ | 750 /* Custom conversion specifiers. */ |
720 | 751 |
721 /* These will require a "tree" at runtime. */ | 752 /* These will require a "tree" at runtime. */ |
722 { "DEFKTV", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL }, | 753 { "DFTV", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "'", NULL }, |
723 | 754 { "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL }, |
724 { "v", 0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL }, | 755 { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, |
725 | 756 |
726 { "<>'", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | 757 /* G requires a "gcall*" argument at runtime. */ |
758 { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, | |
759 | |
760 { "v", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL }, | |
761 | |
762 { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "/cR", NULL }, | |
763 { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL }, | |
764 { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL }, | |
765 { "'", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | |
766 { "R", 0, STD_C89, NOARGUMENTS, "", "\\", NULL }, | |
727 { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, | 767 { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, |
768 { "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_tdiag_char_table[0] }, | |
728 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } | 769 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } |
729 }; | 770 }; |
730 | 771 |
731 static const format_char_info gcc_cxxdiag_char_table[] = | 772 static const format_char_info gcc_cxxdiag_char_table[] = |
732 { | 773 { |
739 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, | 780 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, |
740 | 781 |
741 /* Custom conversion specifiers. */ | 782 /* Custom conversion specifiers. */ |
742 | 783 |
743 /* These will require a "tree" at runtime. */ | 784 /* These will require a "tree" at runtime. */ |
744 { "ADEFKTV",0,STD_C89,{ T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL }, | 785 { "ADFHISTVX",1,STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "'", NULL }, |
745 | 786 { "E", 1,STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL }, |
787 { "K", 1, STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, | |
746 { "v", 0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL }, | 788 { "v", 0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL }, |
789 | |
790 /* G requires a "gcall*" argument at runtime. */ | |
791 { "G", 1, STD_C89,{ T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, | |
747 | 792 |
748 /* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.) */ | 793 /* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.) */ |
749 { "CLOPQ",0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | 794 { "CLOPQ",0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, |
750 | 795 |
751 { "<>'", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | 796 { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "/cR", NULL }, |
797 { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL }, | |
798 { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL }, | |
799 { "'", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | |
800 { "R", 0, STD_C89, NOARGUMENTS, "", "\\", NULL }, | |
752 { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, | 801 { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, |
802 { "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_tdiag_char_table[0] }, | |
753 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } | 803 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } |
754 }; | 804 }; |
755 | 805 |
756 static const format_char_info gcc_gfc_char_table[] = | 806 static const format_char_info gcc_gfc_char_table[] = |
757 { | 807 { |
758 /* C89 conversion specifiers. */ | 808 /* C89 conversion specifiers. */ |
759 { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", NULL }, | 809 { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, |
760 { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", NULL }, | 810 { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, |
761 { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", NULL }, | 811 { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, |
762 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "cR", NULL }, | 812 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "cR", NULL }, |
763 | 813 |
764 /* gfc conversion specifiers. */ | 814 /* gfc conversion specifiers. */ |
765 | 815 |
766 { "C", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | 816 { "C", 0, STD_C89, NOARGUMENTS, "", "", NULL }, |
767 | 817 |
768 /* This will require a "locus" at runtime. */ | 818 /* This will require a "locus" at runtime. */ |
769 { "L", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "R", NULL }, | 819 { "L", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "R", NULL }, |
770 | 820 |
821 /* These will require nothing. */ | |
822 { "<>",0, STD_C89, NOARGUMENTS, "", "", NULL }, | |
771 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } | 823 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } |
772 }; | 824 }; |
773 | 825 |
774 static const format_char_info scan_char_table[] = | 826 static const format_char_info scan_char_table[] = |
775 { | 827 { |
862 gcc_cxxdiag_flag_specs, gcc_cxxdiag_flag_pairs, | 914 gcc_cxxdiag_flag_specs, gcc_cxxdiag_flag_pairs, |
863 FMT_FLAG_ARG_CONVERT, | 915 FMT_FLAG_ARG_CONVERT, |
864 0, 0, 'p', 0, 'L', 0, | 916 0, 0, 'p', 0, 'L', 0, |
865 NULL, &integer_type_node | 917 NULL, &integer_type_node |
866 }, | 918 }, |
867 { "gcc_gfc", gcc_gfc_length_specs, gcc_gfc_char_table, "", NULL, | 919 { "gcc_gfc", gcc_gfc_length_specs, gcc_gfc_char_table, "q+#", NULL, |
868 NULL, gcc_gfc_flag_pairs, | 920 gcc_gfc_flag_specs, gcc_gfc_flag_pairs, |
869 FMT_FLAG_ARG_CONVERT, | 921 FMT_FLAG_ARG_CONVERT, |
870 0, 0, 0, 0, 0, 0, | 922 0, 0, 0, 0, 0, 0, |
871 NULL, NULL | 923 NULL, NULL |
872 }, | 924 }, |
873 { "NSString", NULL, NULL, NULL, NULL, | 925 { "NSString", NULL, NULL, NULL, NULL, |
904 static int n_format_types = ARRAY_SIZE (format_types_orig); | 956 static int n_format_types = ARRAY_SIZE (format_types_orig); |
905 | 957 |
906 /* Structure detailing the results of checking a format function call | 958 /* Structure detailing the results of checking a format function call |
907 where the format expression may be a conditional expression with | 959 where the format expression may be a conditional expression with |
908 many leaves resulting from nested conditional expressions. */ | 960 many leaves resulting from nested conditional expressions. */ |
909 typedef struct | 961 struct format_check_results |
910 { | 962 { |
911 /* Number of leaves of the format argument that could not be checked | 963 /* Number of leaves of the format argument that could not be checked |
912 as they were not string literals. */ | 964 as they were not string literals. */ |
913 int number_non_literal; | 965 int number_non_literal; |
914 /* Number of leaves of the format argument that were null pointers or | 966 /* Number of leaves of the format argument that were null pointers or |
915 string literals, but had extra format arguments. */ | 967 string literals, but had extra format arguments. */ |
916 int number_extra_args; | 968 int number_extra_args; |
969 location_t extra_arg_loc; | |
917 /* Number of leaves of the format argument that were null pointers or | 970 /* Number of leaves of the format argument that were null pointers or |
918 string literals, but had extra format arguments and used $ operand | 971 string literals, but had extra format arguments and used $ operand |
919 numbers. */ | 972 numbers. */ |
920 int number_dollar_extra_args; | 973 int number_dollar_extra_args; |
921 /* Number of leaves of the format argument that were wide string | 974 /* Number of leaves of the format argument that were wide string |
926 /* Number of leaves of the format argument that were unterminated | 979 /* Number of leaves of the format argument that were unterminated |
927 strings. */ | 980 strings. */ |
928 int number_unterminated; | 981 int number_unterminated; |
929 /* Number of leaves of the format argument that were not counted above. */ | 982 /* Number of leaves of the format argument that were not counted above. */ |
930 int number_other; | 983 int number_other; |
931 } format_check_results; | 984 /* Location of the format string. */ |
932 | 985 location_t format_string_loc; |
933 typedef struct | 986 }; |
987 | |
988 struct format_check_context | |
934 { | 989 { |
935 format_check_results *res; | 990 format_check_results *res; |
936 function_format_info *info; | 991 function_format_info *info; |
937 tree params; | 992 tree params; |
938 } format_check_context; | 993 vec<location_t> *arglocs; |
994 }; | |
939 | 995 |
940 /* Return the format name (as specified in the original table) for the format | 996 /* Return the format name (as specified in the original table) for the format |
941 type indicated by format_num. */ | 997 type indicated by format_num. */ |
942 static const char * | 998 static const char * |
943 format_name (int format_num) | 999 format_name (int format_num) |
955 if (format_num >= 0 && format_num < n_format_types) | 1011 if (format_num >= 0 && format_num < n_format_types) |
956 return format_types[format_num].flags; | 1012 return format_types[format_num].flags; |
957 gcc_unreachable (); | 1013 gcc_unreachable (); |
958 } | 1014 } |
959 | 1015 |
960 static void check_format_info (function_format_info *, tree); | 1016 static void check_format_info (function_format_info *, tree, |
1017 vec<location_t> *); | |
961 static void check_format_arg (void *, tree, unsigned HOST_WIDE_INT); | 1018 static void check_format_arg (void *, tree, unsigned HOST_WIDE_INT); |
962 static void check_format_info_main (format_check_results *, | 1019 static void check_format_info_main (format_check_results *, |
963 function_format_info *, | 1020 function_format_info *, const char *, |
964 const char *, int, tree, | 1021 location_t, tree, |
965 unsigned HOST_WIDE_INT, alloc_pool); | 1022 int, tree, |
1023 unsigned HOST_WIDE_INT, | |
1024 object_allocator<format_wanted_type> &, | |
1025 vec<location_t> *); | |
966 | 1026 |
967 static void init_dollar_format_checking (int, tree); | 1027 static void init_dollar_format_checking (int, tree); |
968 static int maybe_read_dollar_number (const char **, int, | 1028 static int maybe_read_dollar_number (const char **, int, |
969 tree, tree *, const format_kind_info *); | 1029 tree, tree *, const format_kind_info *); |
970 static bool avoid_dollar_number (const char *); | 1030 static bool avoid_dollar_number (const char *); |
971 static void finish_dollar_format_checking (format_check_results *, int); | 1031 static void finish_dollar_format_checking (format_check_results *, int); |
972 | 1032 |
973 static const format_flag_spec *get_flag_spec (const format_flag_spec *, | 1033 static const format_flag_spec *get_flag_spec (const format_flag_spec *, |
974 int, const char *); | 1034 int, const char *); |
975 | 1035 |
976 static void check_format_types (format_wanted_type *); | 1036 static void check_format_types (const substring_loc &fmt_loc, |
977 static void format_type_warning (format_wanted_type *, tree, tree); | 1037 format_wanted_type *, |
1038 const format_kind_info *fki, | |
1039 int offset_to_type_start, | |
1040 char conversion_char, | |
1041 vec<location_t> *arglocs); | |
1042 static void format_type_warning (const substring_loc &fmt_loc, | |
1043 location_t param_loc, | |
1044 format_wanted_type *, tree, | |
1045 tree, | |
1046 const format_kind_info *fki, | |
1047 int offset_to_type_start, | |
1048 char conversion_char); | |
978 | 1049 |
979 /* Decode a format type from a string, returning the type, or | 1050 /* Decode a format type from a string, returning the type, or |
980 format_type_error if not valid, in which case the caller should print an | 1051 format_type_error if not valid, in which case the caller should print an |
981 error message. */ | 1052 error message. */ |
982 static int | 1053 static int |
1003 | 1074 |
1004 | 1075 |
1005 /* Check the argument list of a call to printf, scanf, etc. | 1076 /* Check the argument list of a call to printf, scanf, etc. |
1006 ATTRS are the attributes on the function type. There are NARGS argument | 1077 ATTRS are the attributes on the function type. There are NARGS argument |
1007 values in the array ARGARRAY. | 1078 values in the array ARGARRAY. |
1008 Also, if -Wmissing-format-attribute, | 1079 Also, if -Wsuggest-attribute=format, |
1009 warn for calls to vprintf or vscanf in functions with no such format | 1080 warn for calls to vprintf or vscanf in functions with no such format |
1010 attribute themselves. */ | 1081 attribute themselves. */ |
1011 | 1082 |
1012 void | 1083 void |
1013 check_function_format (tree attrs, int nargs, tree *argarray) | 1084 check_function_format (tree attrs, int nargs, tree *argarray, |
1085 vec<location_t> *arglocs) | |
1014 { | 1086 { |
1015 tree a; | 1087 tree a; |
1016 | 1088 |
1017 /* See if this function has any format attributes. */ | 1089 /* See if this function has any format attributes. */ |
1018 for (a = attrs; a; a = TREE_CHAIN (a)) | 1090 for (a = attrs; a; a = TREE_CHAIN (a)) |
1019 { | 1091 { |
1020 if (is_attribute_p ("format", TREE_PURPOSE (a))) | 1092 if (is_attribute_p ("format", TREE_PURPOSE (a))) |
1021 { | 1093 { |
1022 /* Yup; check it. */ | 1094 /* Yup; check it. */ |
1023 function_format_info info; | 1095 function_format_info info; |
1024 decode_format_attr (TREE_VALUE (a), &info, 1); | 1096 decode_format_attr (TREE_VALUE (a), &info, /*validated=*/true); |
1025 if (warn_format) | 1097 if (warn_format) |
1026 { | 1098 { |
1027 /* FIXME: Rewrite all the internal functions in this file | 1099 /* FIXME: Rewrite all the internal functions in this file |
1028 to use the ARGARRAY directly instead of constructing this | 1100 to use the ARGARRAY directly instead of constructing this |
1029 temporary list. */ | 1101 temporary list. */ |
1030 tree params = NULL_TREE; | 1102 tree params = NULL_TREE; |
1031 int i; | 1103 int i; |
1032 for (i = nargs - 1; i >= 0; i--) | 1104 for (i = nargs - 1; i >= 0; i--) |
1033 params = tree_cons (NULL_TREE, argarray[i], params); | 1105 params = tree_cons (NULL_TREE, argarray[i], params); |
1034 check_format_info (&info, params); | 1106 check_format_info (&info, params, arglocs); |
1035 } | 1107 } |
1036 if (warn_missing_format_attribute && info.first_arg_num == 0 | 1108 |
1109 /* Attempt to detect whether the current function might benefit | |
1110 from the format attribute if the called function is decorated | |
1111 with it. Avoid using calls with string literal formats for | |
1112 guidance since those are unlikely to be viable candidates. */ | |
1113 if (warn_suggest_attribute_format && info.first_arg_num == 0 | |
1037 && (format_types[info.format_type].flags | 1114 && (format_types[info.format_type].flags |
1038 & (int) FMT_FLAG_ARG_CONVERT)) | 1115 & (int) FMT_FLAG_ARG_CONVERT) |
1116 /* c_strlen will fail for a function parameter but succeed | |
1117 for a literal or constant array. */ | |
1118 && !c_strlen (argarray[info.format_num - 1], 1)) | |
1039 { | 1119 { |
1040 tree c; | 1120 tree c; |
1041 for (c = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); | 1121 for (c = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); |
1042 c; | 1122 c; |
1043 c = TREE_CHAIN (c)) | 1123 c = TREE_CHAIN (c)) |
1061 && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (args))) | 1141 && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (args))) |
1062 == char_type_node)) | 1142 == char_type_node)) |
1063 break; | 1143 break; |
1064 } | 1144 } |
1065 if (args != 0) | 1145 if (args != 0) |
1066 warning (OPT_Wmissing_format_attribute, "function might " | 1146 warning (OPT_Wsuggest_attribute_format, "function %qD " |
1067 "be possible candidate for %qs format attribute", | 1147 "might be a candidate for %qs format attribute", |
1148 current_function_decl, | |
1068 format_types[info.format_type].name); | 1149 format_types[info.format_type].name); |
1069 } | 1150 } |
1070 } | 1151 } |
1071 } | 1152 } |
1072 } | 1153 } |
1105 params = TREE_CHAIN (params); | 1186 params = TREE_CHAIN (params); |
1106 } | 1187 } |
1107 } | 1188 } |
1108 if (dollar_arguments_alloc < dollar_arguments_count) | 1189 if (dollar_arguments_alloc < dollar_arguments_count) |
1109 { | 1190 { |
1110 if (dollar_arguments_used) | 1191 free (dollar_arguments_used); |
1111 free (dollar_arguments_used); | 1192 free (dollar_arguments_pointer_p); |
1112 if (dollar_arguments_pointer_p) | |
1113 free (dollar_arguments_pointer_p); | |
1114 dollar_arguments_alloc = dollar_arguments_count; | 1193 dollar_arguments_alloc = dollar_arguments_count; |
1115 dollar_arguments_used = XNEWVEC (char, dollar_arguments_alloc); | 1194 dollar_arguments_used = XNEWVEC (char, dollar_arguments_alloc); |
1116 dollar_arguments_pointer_p = XNEWVEC (char, dollar_arguments_alloc); | 1195 dollar_arguments_pointer_p = XNEWVEC (char, dollar_arguments_alloc); |
1117 } | 1196 } |
1118 if (dollar_arguments_alloc) | 1197 if (dollar_arguments_alloc) |
1153 const char *fcp = *format; | 1232 const char *fcp = *format; |
1154 if (!ISDIGIT (*fcp)) | 1233 if (!ISDIGIT (*fcp)) |
1155 { | 1234 { |
1156 if (dollar_needed) | 1235 if (dollar_needed) |
1157 { | 1236 { |
1158 warning (OPT_Wformat, "missing $ operand number in format"); | 1237 warning (OPT_Wformat_, "missing $ operand number in format"); |
1159 return -1; | 1238 return -1; |
1160 } | 1239 } |
1161 else | 1240 else |
1162 return 0; | 1241 return 0; |
1163 } | 1242 } |
1174 } | 1253 } |
1175 if (*fcp != '$') | 1254 if (*fcp != '$') |
1176 { | 1255 { |
1177 if (dollar_needed) | 1256 if (dollar_needed) |
1178 { | 1257 { |
1179 warning (OPT_Wformat, "missing $ operand number in format"); | 1258 warning (OPT_Wformat_, "missing $ operand number in format"); |
1180 return -1; | 1259 return -1; |
1181 } | 1260 } |
1182 else | 1261 else |
1183 return 0; | 1262 return 0; |
1184 } | 1263 } |
1185 *format = fcp + 1; | 1264 *format = fcp + 1; |
1186 if (pedantic && !dollar_format_warned) | 1265 if (pedantic && !dollar_format_warned) |
1187 { | 1266 { |
1188 warning (OPT_Wformat, "%s does not support %%n$ operand number formats", | 1267 warning (OPT_Wformat_, "%s does not support %%n$ operand number formats", |
1189 C_STD_NAME (STD_EXT)); | 1268 C_STD_NAME (STD_EXT)); |
1190 dollar_format_warned = 1; | 1269 dollar_format_warned = 1; |
1191 } | 1270 } |
1192 if (overflow_flag || argnum == 0 | 1271 if (overflow_flag || argnum == 0 |
1193 || (dollar_first_arg_num && argnum > dollar_arguments_count)) | 1272 || (dollar_first_arg_num && argnum > dollar_arguments_count)) |
1194 { | 1273 { |
1195 warning (OPT_Wformat, "operand number out of range in format"); | 1274 warning (OPT_Wformat_, "operand number out of range in format"); |
1196 return -1; | 1275 return -1; |
1197 } | 1276 } |
1198 if (argnum > dollar_max_arg_used) | 1277 if (argnum > dollar_max_arg_used) |
1199 dollar_max_arg_used = argnum; | 1278 dollar_max_arg_used = argnum; |
1200 /* For vprintf-style functions we may need to allocate more memory to | 1279 /* For vprintf-style functions we may need to allocate more memory to |
1213 } | 1292 } |
1214 if (!(fki->flags & (int) FMT_FLAG_DOLLAR_MULTIPLE) | 1293 if (!(fki->flags & (int) FMT_FLAG_DOLLAR_MULTIPLE) |
1215 && dollar_arguments_used[argnum - 1] == 1) | 1294 && dollar_arguments_used[argnum - 1] == 1) |
1216 { | 1295 { |
1217 dollar_arguments_used[argnum - 1] = 2; | 1296 dollar_arguments_used[argnum - 1] = 2; |
1218 warning (OPT_Wformat, "format argument %d used more than once in %s format", | 1297 warning (OPT_Wformat_, "format argument %d used more than once in %s format", |
1219 argnum, fki->name); | 1298 argnum, fki->name); |
1220 } | 1299 } |
1221 else | 1300 else |
1222 dollar_arguments_used[argnum - 1] = 1; | 1301 dollar_arguments_used[argnum - 1] = 1; |
1223 if (dollar_first_arg_num) | 1302 if (dollar_first_arg_num) |
1245 return false; | 1324 return false; |
1246 while (ISDIGIT (*format)) | 1325 while (ISDIGIT (*format)) |
1247 format++; | 1326 format++; |
1248 if (*format == '$') | 1327 if (*format == '$') |
1249 { | 1328 { |
1250 warning (OPT_Wformat, "$ operand number used after format without operand number"); | 1329 warning (OPT_Wformat_, "$ operand number used after format without operand number"); |
1251 return true; | 1330 return true; |
1252 } | 1331 } |
1253 return false; | 1332 return false; |
1254 } | 1333 } |
1255 | 1334 |
1275 { | 1354 { |
1276 if (pointer_gap_ok && (dollar_first_arg_num == 0 | 1355 if (pointer_gap_ok && (dollar_first_arg_num == 0 |
1277 || dollar_arguments_pointer_p[i])) | 1356 || dollar_arguments_pointer_p[i])) |
1278 found_pointer_gap = true; | 1357 found_pointer_gap = true; |
1279 else | 1358 else |
1280 warning (OPT_Wformat, | 1359 warning_at (res->format_string_loc, OPT_Wformat_, |
1281 "format argument %d unused before used argument %d in $-style format", | 1360 "format argument %d unused before used argument %d in $-style format", |
1282 i + 1, dollar_max_arg_used); | 1361 i + 1, dollar_max_arg_used); |
1283 } | 1362 } |
1284 } | 1363 } |
1285 if (found_pointer_gap | 1364 if (found_pointer_gap |
1286 || (dollar_first_arg_num | 1365 || (dollar_first_arg_num |
1287 && dollar_max_arg_used < dollar_arguments_count)) | 1366 && dollar_max_arg_used < dollar_arguments_count)) |
1325 /* Check the argument list of a call to printf, scanf, etc. | 1404 /* Check the argument list of a call to printf, scanf, etc. |
1326 INFO points to the function_format_info structure. | 1405 INFO points to the function_format_info structure. |
1327 PARAMS is the list of argument values. */ | 1406 PARAMS is the list of argument values. */ |
1328 | 1407 |
1329 static void | 1408 static void |
1330 check_format_info (function_format_info *info, tree params) | 1409 check_format_info (function_format_info *info, tree params, |
1410 vec<location_t> *arglocs) | |
1331 { | 1411 { |
1332 format_check_context format_ctx; | 1412 format_check_context format_ctx; |
1333 unsigned HOST_WIDE_INT arg_num; | 1413 unsigned HOST_WIDE_INT arg_num; |
1334 tree format_tree; | 1414 tree format_tree; |
1335 format_check_results res; | 1415 format_check_results res; |
1348 if (format_tree == 0) | 1428 if (format_tree == 0) |
1349 return; | 1429 return; |
1350 | 1430 |
1351 res.number_non_literal = 0; | 1431 res.number_non_literal = 0; |
1352 res.number_extra_args = 0; | 1432 res.number_extra_args = 0; |
1433 res.extra_arg_loc = UNKNOWN_LOCATION; | |
1353 res.number_dollar_extra_args = 0; | 1434 res.number_dollar_extra_args = 0; |
1354 res.number_wide = 0; | 1435 res.number_wide = 0; |
1355 res.number_empty = 0; | 1436 res.number_empty = 0; |
1356 res.number_unterminated = 0; | 1437 res.number_unterminated = 0; |
1357 res.number_other = 0; | 1438 res.number_other = 0; |
1439 res.format_string_loc = input_location; | |
1358 | 1440 |
1359 format_ctx.res = &res; | 1441 format_ctx.res = &res; |
1360 format_ctx.info = info; | 1442 format_ctx.info = info; |
1361 format_ctx.params = params; | 1443 format_ctx.params = params; |
1444 format_ctx.arglocs = arglocs; | |
1362 | 1445 |
1363 check_function_arguments_recurse (check_format_arg, &format_ctx, | 1446 check_function_arguments_recurse (check_format_arg, &format_ctx, |
1364 format_tree, arg_num); | 1447 format_tree, arg_num); |
1448 | |
1449 location_t loc = format_ctx.res->format_string_loc; | |
1365 | 1450 |
1366 if (res.number_non_literal > 0) | 1451 if (res.number_non_literal > 0) |
1367 { | 1452 { |
1368 /* Functions taking a va_list normally pass a non-literal format | 1453 /* Functions taking a va_list normally pass a non-literal format |
1369 string. These functions typically are declared with | 1454 string. These functions typically are declared with |
1370 first_arg_num == 0, so avoid warning in those cases. */ | 1455 first_arg_num == 0, so avoid warning in those cases. */ |
1371 if (!(format_types[info->format_type].flags & (int) FMT_FLAG_ARG_CONVERT)) | 1456 if (!(format_types[info->format_type].flags & (int) FMT_FLAG_ARG_CONVERT)) |
1372 { | 1457 { |
1373 /* For strftime-like formats, warn for not checking the format | 1458 /* For strftime-like formats, warn for not checking the format |
1374 string; but there are no arguments to check. */ | 1459 string; but there are no arguments to check. */ |
1375 warning (OPT_Wformat_nonliteral, | 1460 warning_at (loc, OPT_Wformat_nonliteral, |
1376 "format not a string literal, format string not checked"); | 1461 "format not a string literal, format string not checked"); |
1377 } | 1462 } |
1378 else if (info->first_arg_num != 0) | 1463 else if (info->first_arg_num != 0) |
1379 { | 1464 { |
1380 /* If there are no arguments for the format at all, we may have | 1465 /* If there are no arguments for the format at all, we may have |
1381 printf (foo) which is likely to be a security hole. */ | 1466 printf (foo) which is likely to be a security hole. */ |
1385 break; | 1470 break; |
1386 params = TREE_CHAIN (params); | 1471 params = TREE_CHAIN (params); |
1387 ++arg_num; | 1472 ++arg_num; |
1388 } | 1473 } |
1389 if (params == 0 && warn_format_security) | 1474 if (params == 0 && warn_format_security) |
1390 warning (OPT_Wformat_security, | 1475 warning_at (loc, OPT_Wformat_security, |
1391 "format not a string literal and no format arguments"); | 1476 "format not a string literal and no format arguments"); |
1392 else if (params == 0 && warn_format_nonliteral) | 1477 else if (params == 0 && warn_format_nonliteral) |
1393 warning (OPT_Wformat_nonliteral, | 1478 warning_at (loc, OPT_Wformat_nonliteral, |
1394 "format not a string literal and no format arguments"); | 1479 "format not a string literal and no format arguments"); |
1395 else | 1480 else |
1396 warning (OPT_Wformat_nonliteral, | 1481 warning_at (loc, OPT_Wformat_nonliteral, |
1397 "format not a string literal, argument types not checked"); | 1482 "format not a string literal, argument types not checked"); |
1398 } | 1483 } |
1399 } | 1484 } |
1400 | 1485 |
1401 /* If there were extra arguments to the format, normally warn. However, | 1486 /* If there were extra arguments to the format, normally warn. However, |
1402 the standard does say extra arguments are ignored, so in the specific | 1487 the standard does say extra arguments are ignored, so in the specific |
1405 arguments, but was otherwise OK (either non-literal or checked OK). | 1490 arguments, but was otherwise OK (either non-literal or checked OK). |
1406 If the format is an empty string, this should be counted similarly to the | 1491 If the format is an empty string, this should be counted similarly to the |
1407 case of extra format arguments. */ | 1492 case of extra format arguments. */ |
1408 if (res.number_extra_args > 0 && res.number_non_literal == 0 | 1493 if (res.number_extra_args > 0 && res.number_non_literal == 0 |
1409 && res.number_other == 0) | 1494 && res.number_other == 0) |
1410 warning (OPT_Wformat_extra_args, "too many arguments for format"); | 1495 { |
1496 if (res.extra_arg_loc == UNKNOWN_LOCATION) | |
1497 res.extra_arg_loc = loc; | |
1498 warning_at (res.extra_arg_loc, OPT_Wformat_extra_args, | |
1499 "too many arguments for format"); | |
1500 } | |
1411 if (res.number_dollar_extra_args > 0 && res.number_non_literal == 0 | 1501 if (res.number_dollar_extra_args > 0 && res.number_non_literal == 0 |
1412 && res.number_other == 0) | 1502 && res.number_other == 0) |
1413 warning (OPT_Wformat_extra_args, "unused arguments in $-style format"); | 1503 warning_at (loc, OPT_Wformat_extra_args, "unused arguments in $-style format"); |
1414 if (res.number_empty > 0 && res.number_non_literal == 0 | 1504 if (res.number_empty > 0 && res.number_non_literal == 0 |
1415 && res.number_other == 0) | 1505 && res.number_other == 0) |
1416 warning (OPT_Wformat_zero_length, "zero-length %s format string", | 1506 warning_at (loc, OPT_Wformat_zero_length, "zero-length %s format string", |
1417 format_types[info->format_type].name); | 1507 format_types[info->format_type].name); |
1418 | 1508 |
1419 if (res.number_wide > 0) | 1509 if (res.number_wide > 0) |
1420 warning (OPT_Wformat, "format is a wide character string"); | 1510 warning_at (loc, OPT_Wformat_, "format is a wide character string"); |
1421 | 1511 |
1422 if (res.number_unterminated > 0) | 1512 if (res.number_unterminated > 0) |
1423 warning (OPT_Wformat, "unterminated format string"); | 1513 warning_at (loc, OPT_Wformat_, "unterminated format string"); |
1424 } | 1514 } |
1425 | 1515 |
1426 /* Callback from check_function_arguments_recurse to check a | 1516 /* Callback from check_function_arguments_recurse to check a |
1427 format string. FORMAT_TREE is the format parameter. ARG_NUM | 1517 format string. FORMAT_TREE is the format parameter. ARG_NUM |
1428 is the number of the format argument. CTX points to a | 1518 is the number of the format argument. CTX points to a |
1434 { | 1524 { |
1435 format_check_context *format_ctx = (format_check_context *) ctx; | 1525 format_check_context *format_ctx = (format_check_context *) ctx; |
1436 format_check_results *res = format_ctx->res; | 1526 format_check_results *res = format_ctx->res; |
1437 function_format_info *info = format_ctx->info; | 1527 function_format_info *info = format_ctx->info; |
1438 tree params = format_ctx->params; | 1528 tree params = format_ctx->params; |
1529 vec<location_t> *arglocs = format_ctx->arglocs; | |
1439 | 1530 |
1440 int format_length; | 1531 int format_length; |
1441 HOST_WIDE_INT offset; | 1532 HOST_WIDE_INT offset; |
1442 const char *format_chars; | 1533 const char *format_chars; |
1443 tree array_size = 0; | 1534 tree array_size = 0; |
1444 tree array_init; | 1535 tree array_init; |
1445 alloc_pool fwt_pool; | 1536 |
1537 location_t fmt_param_loc = EXPR_LOC_OR_LOC (format_tree, input_location); | |
1538 | |
1539 if (VAR_P (format_tree)) | |
1540 { | |
1541 /* Pull out a constant value if the front end didn't. */ | |
1542 format_tree = decl_constant_value (format_tree); | |
1543 STRIP_NOPS (format_tree); | |
1544 } | |
1446 | 1545 |
1447 if (integer_zerop (format_tree)) | 1546 if (integer_zerop (format_tree)) |
1448 { | 1547 { |
1449 /* Skip to first argument to check, so we can see if this format | 1548 /* Skip to first argument to check, so we can see if this format |
1450 has any arguments (it shouldn't). */ | 1549 has any arguments (it shouldn't). */ |
1456 ++arg_num; | 1555 ++arg_num; |
1457 } | 1556 } |
1458 | 1557 |
1459 if (params == 0) | 1558 if (params == 0) |
1460 res->number_other++; | 1559 res->number_other++; |
1461 else | 1560 else |
1462 res->number_extra_args++; | 1561 { |
1463 | 1562 if (res->number_extra_args == 0) |
1563 res->extra_arg_loc = EXPR_LOC_OR_LOC (TREE_VALUE (params), | |
1564 input_location); | |
1565 res->number_extra_args++; | |
1566 } | |
1464 return; | 1567 return; |
1465 } | 1568 } |
1466 | 1569 |
1467 offset = 0; | 1570 offset = 0; |
1468 if (TREE_CODE (format_tree) == POINTER_PLUS_EXPR) | 1571 if (TREE_CODE (format_tree) == POINTER_PLUS_EXPR) |
1478 else | 1581 else |
1479 { | 1582 { |
1480 res->number_non_literal++; | 1583 res->number_non_literal++; |
1481 return; | 1584 return; |
1482 } | 1585 } |
1483 if (!host_integerp (arg1, 0) | 1586 /* POINTER_PLUS_EXPR offsets are to be interpreted signed. */ |
1484 || (offset = tree_low_cst (arg1, 0)) < 0) | 1587 if (!cst_and_fits_in_hwi (arg1)) |
1485 { | 1588 { |
1486 res->number_non_literal++; | 1589 res->number_non_literal++; |
1487 return; | 1590 return; |
1488 } | 1591 } |
1592 offset = int_cst_value (arg1); | |
1489 } | 1593 } |
1490 if (TREE_CODE (format_tree) != ADDR_EXPR) | 1594 if (TREE_CODE (format_tree) != ADDR_EXPR) |
1491 { | 1595 { |
1492 res->number_non_literal++; | 1596 res->number_non_literal++; |
1493 return; | 1597 return; |
1494 } | 1598 } |
1599 res->format_string_loc = EXPR_LOC_OR_LOC (format_tree, input_location); | |
1495 format_tree = TREE_OPERAND (format_tree, 0); | 1600 format_tree = TREE_OPERAND (format_tree, 0); |
1496 if (format_types[info->format_type].flags | 1601 if (format_types[info->format_type].flags |
1497 & (int) FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL) | 1602 & (int) FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL) |
1498 { | 1603 { |
1499 bool objc_str = (info->format_type == gcc_objc_string_format_type); | 1604 bool objc_str = (info->format_type == gcc_objc_string_format_type); |
1500 /* We cannot examine this string here - but we can check that it is | 1605 /* We cannot examine this string here - but we can check that it is |
1501 a valid type. */ | 1606 a valid type. */ |
1502 if (TREE_CODE (format_tree) != CONST_DECL | 1607 if (TREE_CODE (format_tree) != CONST_DECL |
1503 || !((objc_str && objc_string_ref_type_p (TREE_TYPE (format_tree))) | 1608 || !((objc_str && objc_string_ref_type_p (TREE_TYPE (format_tree))) |
1504 || (*targetcm.string_object_ref_type_p) | 1609 || (*targetcm.string_object_ref_type_p) |
1505 ((const_tree) TREE_TYPE (format_tree)))) | 1610 ((const_tree) TREE_TYPE (format_tree)))) |
1506 { | 1611 { |
1514 return; | 1619 return; |
1515 params = TREE_CHAIN (params); | 1620 params = TREE_CHAIN (params); |
1516 ++arg_num; | 1621 ++arg_num; |
1517 } | 1622 } |
1518 /* So, we have a valid literal string object and one or more params. | 1623 /* So, we have a valid literal string object and one or more params. |
1519 We need to use an external helper to parse the string into format | 1624 We need to use an external helper to parse the string into format |
1520 info. For Objective-C variants we provide the resource within the | 1625 info. For Objective-C variants we provide the resource within the |
1521 objc tree, for target variants, via a hook. */ | 1626 objc tree, for target variants, via a hook. */ |
1522 if (objc_str) | 1627 if (objc_str) |
1523 objc_check_format_arg (format_tree, params); | 1628 objc_check_format_arg (format_tree, params); |
1524 else if (targetcm.check_string_object_format_arg) | 1629 else if (targetcm.check_string_object_format_arg) |
1525 (*targetcm.check_string_object_format_arg) (format_tree, params); | 1630 (*targetcm.check_string_object_format_arg) (format_tree, params); |
1526 /* Else we can't handle it and retire quietly. */ | 1631 /* Else we can't handle it and retire quietly. */ |
1527 return; | 1632 return; |
1528 } | 1633 } |
1529 if (TREE_CODE (format_tree) == ARRAY_REF | 1634 if (TREE_CODE (format_tree) == ARRAY_REF |
1530 && host_integerp (TREE_OPERAND (format_tree, 1), 0) | 1635 && tree_fits_shwi_p (TREE_OPERAND (format_tree, 1)) |
1531 && (offset += tree_low_cst (TREE_OPERAND (format_tree, 1), 0)) >= 0) | 1636 && (offset += tree_to_shwi (TREE_OPERAND (format_tree, 1))) >= 0) |
1532 format_tree = TREE_OPERAND (format_tree, 0); | 1637 format_tree = TREE_OPERAND (format_tree, 0); |
1533 if (TREE_CODE (format_tree) == VAR_DECL | 1638 if (offset < 0) |
1639 { | |
1640 res->number_non_literal++; | |
1641 return; | |
1642 } | |
1643 if (VAR_P (format_tree) | |
1534 && TREE_CODE (TREE_TYPE (format_tree)) == ARRAY_TYPE | 1644 && TREE_CODE (TREE_TYPE (format_tree)) == ARRAY_TYPE |
1535 && (array_init = decl_constant_value (format_tree)) != format_tree | 1645 && (array_init = decl_constant_value (format_tree)) != format_tree |
1536 && TREE_CODE (array_init) == STRING_CST) | 1646 && TREE_CODE (array_init) == STRING_CST) |
1537 { | 1647 { |
1538 /* Extract the string constant initializer. Note that this may include | 1648 /* Extract the string constant initializer. Note that this may include |
1556 if (array_size != 0) | 1666 if (array_size != 0) |
1557 { | 1667 { |
1558 /* Variable length arrays can't be initialized. */ | 1668 /* Variable length arrays can't be initialized. */ |
1559 gcc_assert (TREE_CODE (array_size) == INTEGER_CST); | 1669 gcc_assert (TREE_CODE (array_size) == INTEGER_CST); |
1560 | 1670 |
1561 if (host_integerp (array_size, 0)) | 1671 if (tree_fits_shwi_p (array_size)) |
1562 { | 1672 { |
1563 HOST_WIDE_INT array_size_value = TREE_INT_CST_LOW (array_size); | 1673 HOST_WIDE_INT array_size_value = tree_to_shwi (array_size); |
1564 if (array_size_value > 0 | 1674 if (array_size_value > 0 |
1565 && array_size_value == (int) array_size_value | 1675 && array_size_value == (int) array_size_value |
1566 && format_length > array_size_value) | 1676 && format_length > array_size_value) |
1567 format_length = array_size_value; | 1677 format_length = array_size_value; |
1568 } | 1678 } |
1598 } | 1708 } |
1599 /* Provisionally increment res->number_other; check_format_info_main | 1709 /* Provisionally increment res->number_other; check_format_info_main |
1600 will decrement it if it finds there are extra arguments, but this way | 1710 will decrement it if it finds there are extra arguments, but this way |
1601 need not adjust it for every return. */ | 1711 need not adjust it for every return. */ |
1602 res->number_other++; | 1712 res->number_other++; |
1603 fwt_pool = create_alloc_pool ("format_wanted_type pool", | 1713 object_allocator <format_wanted_type> fwt_pool ("format_wanted_type pool"); |
1604 sizeof (format_wanted_type), 10); | 1714 check_format_info_main (res, info, format_chars, fmt_param_loc, format_tree, |
1605 check_format_info_main (res, info, format_chars, format_length, | 1715 format_length, params, arg_num, fwt_pool, arglocs); |
1606 params, arg_num, fwt_pool); | 1716 } |
1607 free_alloc_pool (fwt_pool); | 1717 |
1608 } | 1718 /* Support class for argument_parser and check_format_info_main. |
1609 | 1719 Tracks any flag characters that have been applied to the |
1720 current argument. */ | |
1721 | |
1722 class flag_chars_t | |
1723 { | |
1724 public: | |
1725 flag_chars_t (); | |
1726 bool has_char_p (char ch) const; | |
1727 void add_char (char ch); | |
1728 void validate (const format_kind_info *fki, | |
1729 const format_char_info *fci, | |
1730 const format_flag_spec *flag_specs, | |
1731 const char * const format_chars, | |
1732 tree format_string_cst, | |
1733 location_t format_string_loc, | |
1734 const char * const orig_format_chars, | |
1735 char format_char, | |
1736 bool quoted); | |
1737 int get_alloc_flag (const format_kind_info *fki); | |
1738 int assignment_suppression_p (const format_kind_info *fki); | |
1739 | |
1740 private: | |
1741 char m_flag_chars[256]; | |
1742 }; | |
1743 | |
1744 /* Support struct for argument_parser and check_format_info_main. | |
1745 Encapsulates any length modifier applied to the current argument. */ | |
1746 | |
1747 struct length_modifier | |
1748 { | |
1749 length_modifier () | |
1750 : chars (NULL), val (FMT_LEN_none), std (STD_C89), | |
1751 scalar_identity_flag (0) | |
1752 { | |
1753 } | |
1754 | |
1755 length_modifier (const char *chars_, | |
1756 enum format_lengths val_, | |
1757 enum format_std_version std_, | |
1758 int scalar_identity_flag_) | |
1759 : chars (chars_), val (val_), std (std_), | |
1760 scalar_identity_flag (scalar_identity_flag_) | |
1761 { | |
1762 } | |
1763 | |
1764 const char *chars; | |
1765 enum format_lengths val; | |
1766 enum format_std_version std; | |
1767 int scalar_identity_flag; | |
1768 }; | |
1769 | |
1770 /* Parsing one argument within a format string. */ | |
1771 | |
1772 class argument_parser | |
1773 { | |
1774 public: | |
1775 argument_parser (function_format_info *info, const char *&format_chars, | |
1776 tree format_string_cst, | |
1777 const char * const orig_format_chars, | |
1778 location_t format_string_loc, flag_chars_t &flag_chars, | |
1779 int &has_operand_number, tree first_fillin_param, | |
1780 object_allocator <format_wanted_type> &fwt_pool_, | |
1781 vec<location_t> *arglocs); | |
1782 | |
1783 bool read_any_dollar (); | |
1784 | |
1785 bool read_format_flags (); | |
1786 | |
1787 bool | |
1788 read_any_format_width (tree ¶ms, | |
1789 unsigned HOST_WIDE_INT &arg_num); | |
1790 | |
1791 void | |
1792 read_any_format_left_precision (); | |
1793 | |
1794 bool | |
1795 read_any_format_precision (tree ¶ms, | |
1796 unsigned HOST_WIDE_INT &arg_num); | |
1797 | |
1798 void handle_alloc_chars (); | |
1799 | |
1800 length_modifier read_any_length_modifier (); | |
1801 | |
1802 void read_any_other_modifier (); | |
1803 | |
1804 const format_char_info *find_format_char_info (char format_char); | |
1805 | |
1806 void | |
1807 validate_flag_pairs (const format_char_info *fci, | |
1808 char format_char); | |
1809 | |
1810 void | |
1811 give_y2k_warnings (const format_char_info *fci, | |
1812 char format_char); | |
1813 | |
1814 void parse_any_scan_set (const format_char_info *fci); | |
1815 | |
1816 bool handle_conversions (const format_char_info *fci, | |
1817 const length_modifier &len_modifier, | |
1818 tree &wanted_type, | |
1819 const char *&wanted_type_name, | |
1820 unsigned HOST_WIDE_INT &arg_num, | |
1821 tree ¶ms, | |
1822 char format_char); | |
1823 | |
1824 bool | |
1825 check_argument_type (const format_char_info *fci, | |
1826 const length_modifier &len_modifier, | |
1827 tree &wanted_type, | |
1828 const char *&wanted_type_name, | |
1829 const bool suppressed, | |
1830 unsigned HOST_WIDE_INT &arg_num, | |
1831 tree ¶ms, | |
1832 const int alloc_flag, | |
1833 const char * const format_start, | |
1834 const char * const type_start, | |
1835 location_t fmt_param_loc, | |
1836 char conversion_char); | |
1837 | |
1838 private: | |
1839 const function_format_info *const info; | |
1840 const format_kind_info * const fki; | |
1841 const format_flag_spec * const flag_specs; | |
1842 const char *start_of_this_format; | |
1843 const char *&format_chars; | |
1844 const tree format_string_cst; | |
1845 const char * const orig_format_chars; | |
1846 const location_t format_string_loc; | |
1847 object_allocator <format_wanted_type> &fwt_pool; | |
1848 flag_chars_t &flag_chars; | |
1849 int main_arg_num; | |
1850 tree main_arg_params; | |
1851 int &has_operand_number; | |
1852 const tree first_fillin_param; | |
1853 format_wanted_type width_wanted_type; | |
1854 format_wanted_type precision_wanted_type; | |
1855 public: | |
1856 format_wanted_type main_wanted_type; | |
1857 private: | |
1858 format_wanted_type *first_wanted_type; | |
1859 format_wanted_type *last_wanted_type; | |
1860 vec<location_t> *arglocs; | |
1861 }; | |
1862 | |
1863 /* flag_chars_t's constructor. */ | |
1864 | |
1865 flag_chars_t::flag_chars_t () | |
1866 { | |
1867 m_flag_chars[0] = 0; | |
1868 } | |
1869 | |
1870 /* Has CH been seen as a flag within the current argument? */ | |
1871 | |
1872 bool | |
1873 flag_chars_t::has_char_p (char ch) const | |
1874 { | |
1875 return strchr (m_flag_chars, ch) != 0; | |
1876 } | |
1877 | |
1878 /* Add CH to the flags seen within the current argument. */ | |
1879 | |
1880 void | |
1881 flag_chars_t::add_char (char ch) | |
1882 { | |
1883 int i = strlen (m_flag_chars); | |
1884 m_flag_chars[i++] = ch; | |
1885 m_flag_chars[i] = 0; | |
1886 } | |
1887 | |
1888 /* Validate the individual flags used, removing any that are invalid. */ | |
1889 | |
1890 void | |
1891 flag_chars_t::validate (const format_kind_info *fki, | |
1892 const format_char_info *fci, | |
1893 const format_flag_spec *flag_specs, | |
1894 const char * const format_chars, | |
1895 tree format_string_cst, | |
1896 location_t format_string_loc, | |
1897 const char * const orig_format_chars, | |
1898 char format_char, | |
1899 bool quoted) | |
1900 { | |
1901 int i; | |
1902 int d = 0; | |
1903 bool quotflag = false; | |
1904 | |
1905 for (i = 0; m_flag_chars[i] != 0; i++) | |
1906 { | |
1907 const format_flag_spec *s = get_flag_spec (flag_specs, | |
1908 m_flag_chars[i], NULL); | |
1909 m_flag_chars[i - d] = m_flag_chars[i]; | |
1910 if (m_flag_chars[i] == fki->length_code_char) | |
1911 continue; | |
1912 | |
1913 /* Remember if a quoting flag is seen. */ | |
1914 quotflag |= s->quoting; | |
1915 | |
1916 if (strchr (fci->flag_chars, m_flag_chars[i]) == 0) | |
1917 { | |
1918 format_warning_at_char (format_string_loc, format_string_cst, | |
1919 format_chars - orig_format_chars, | |
1920 OPT_Wformat_, | |
1921 "%s used with %<%%%c%> %s format", | |
1922 _(s->name), format_char, fki->name); | |
1923 d++; | |
1924 continue; | |
1925 } | |
1926 if (pedantic) | |
1927 { | |
1928 const format_flag_spec *t; | |
1929 if (ADJ_STD (s->std) > C_STD_VER) | |
1930 warning_at (format_string_loc, OPT_Wformat_, | |
1931 "%s does not support %s", | |
1932 C_STD_NAME (s->std), _(s->long_name)); | |
1933 t = get_flag_spec (flag_specs, m_flag_chars[i], fci->flags2); | |
1934 if (t != NULL && ADJ_STD (t->std) > ADJ_STD (s->std)) | |
1935 { | |
1936 const char *long_name = (t->long_name != NULL | |
1937 ? t->long_name | |
1938 : s->long_name); | |
1939 if (ADJ_STD (t->std) > C_STD_VER) | |
1940 warning_at (format_string_loc, OPT_Wformat_, | |
1941 "%s does not support %s with" | |
1942 " the %<%%%c%> %s format", | |
1943 C_STD_NAME (t->std), _(long_name), | |
1944 format_char, fki->name); | |
1945 } | |
1946 } | |
1947 | |
1948 /* Detect quoting directives used within a quoted sequence, such | |
1949 as GCC's "%<...%qE". */ | |
1950 if (quoted && s->quoting) | |
1951 { | |
1952 format_warning_at_char (format_string_loc, format_string_cst, | |
1953 format_chars - orig_format_chars - 1, | |
1954 OPT_Wformat_, | |
1955 "%s used within a quoted sequence", | |
1956 _(s->name)); | |
1957 } | |
1958 } | |
1959 m_flag_chars[i - d] = 0; | |
1960 | |
1961 if (!quoted | |
1962 && !quotflag | |
1963 && strchr (fci->flags2, '\'')) | |
1964 { | |
1965 format_warning_at_char (format_string_loc, format_string_cst, | |
1966 format_chars - orig_format_chars, | |
1967 OPT_Wformat_, | |
1968 "%qc conversion used unquoted", | |
1969 format_char); | |
1970 } | |
1971 } | |
1972 | |
1973 /* Determine if an assignment-allocation has been set, requiring | |
1974 an extra char ** for writing back a dynamically-allocated char *. | |
1975 This is for handling the optional 'm' character in scanf. */ | |
1976 | |
1977 int | |
1978 flag_chars_t::get_alloc_flag (const format_kind_info *fki) | |
1979 { | |
1980 if ((fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE) | |
1981 && has_char_p ('a')) | |
1982 return 1; | |
1983 if (fki->alloc_char && has_char_p (fki->alloc_char)) | |
1984 return 1; | |
1985 return 0; | |
1986 } | |
1987 | |
1988 /* Determine if an assignment-suppression character was seen. | |
1989 ('*' in scanf, for discarding the converted input). */ | |
1990 | |
1991 int | |
1992 flag_chars_t::assignment_suppression_p (const format_kind_info *fki) | |
1993 { | |
1994 if (fki->suppression_char | |
1995 && has_char_p (fki->suppression_char)) | |
1996 return 1; | |
1997 return 0; | |
1998 } | |
1999 | |
2000 /* Constructor for argument_parser. Initialize for parsing one | |
2001 argument within a format string. */ | |
2002 | |
2003 argument_parser:: | |
2004 argument_parser (function_format_info *info_, const char *&format_chars_, | |
2005 tree format_string_cst_, | |
2006 const char * const orig_format_chars_, | |
2007 location_t format_string_loc_, | |
2008 flag_chars_t &flag_chars_, | |
2009 int &has_operand_number_, | |
2010 tree first_fillin_param_, | |
2011 object_allocator <format_wanted_type> &fwt_pool_, | |
2012 vec<location_t> *arglocs_) | |
2013 : info (info_), | |
2014 fki (&format_types[info->format_type]), | |
2015 flag_specs (fki->flag_specs), | |
2016 start_of_this_format (format_chars_), | |
2017 format_chars (format_chars_), | |
2018 format_string_cst (format_string_cst_), | |
2019 orig_format_chars (orig_format_chars_), | |
2020 format_string_loc (format_string_loc_), | |
2021 fwt_pool (fwt_pool_), | |
2022 flag_chars (flag_chars_), | |
2023 main_arg_num (0), | |
2024 main_arg_params (NULL), | |
2025 has_operand_number (has_operand_number_), | |
2026 first_fillin_param (first_fillin_param_), | |
2027 first_wanted_type (NULL), | |
2028 last_wanted_type (NULL), | |
2029 arglocs (arglocs_) | |
2030 { | |
2031 } | |
2032 | |
2033 /* Handle dollars at the start of format arguments, setting up main_arg_params | |
2034 and main_arg_num. | |
2035 | |
2036 Return true if format parsing is to continue, false otherwise. */ | |
2037 | |
2038 bool | |
2039 argument_parser::read_any_dollar () | |
2040 { | |
2041 if ((fki->flags & (int) FMT_FLAG_USE_DOLLAR) && has_operand_number != 0) | |
2042 { | |
2043 /* Possibly read a $ operand number at the start of the format. | |
2044 If one was previously used, one is required here. If one | |
2045 is not used here, we can't immediately conclude this is a | |
2046 format without them, since it could be printf %m or scanf %*. */ | |
2047 int opnum; | |
2048 opnum = maybe_read_dollar_number (&format_chars, 0, | |
2049 first_fillin_param, | |
2050 &main_arg_params, fki); | |
2051 if (opnum == -1) | |
2052 return false; | |
2053 else if (opnum > 0) | |
2054 { | |
2055 has_operand_number = 1; | |
2056 main_arg_num = opnum + info->first_arg_num - 1; | |
2057 } | |
2058 } | |
2059 else if (fki->flags & FMT_FLAG_USE_DOLLAR) | |
2060 { | |
2061 if (avoid_dollar_number (format_chars)) | |
2062 return false; | |
2063 } | |
2064 return true; | |
2065 } | |
2066 | |
2067 /* Read any format flags, but do not yet validate them beyond removing | |
2068 duplicates, since in general validation depends on the rest of | |
2069 the format. | |
2070 | |
2071 Return true if format parsing is to continue, false otherwise. */ | |
2072 | |
2073 bool | |
2074 argument_parser::read_format_flags () | |
2075 { | |
2076 while (*format_chars != 0 | |
2077 && strchr (fki->flag_chars, *format_chars) != 0) | |
2078 { | |
2079 const format_flag_spec *s = get_flag_spec (flag_specs, | |
2080 *format_chars, NULL); | |
2081 if (flag_chars.has_char_p (*format_chars)) | |
2082 { | |
2083 format_warning_at_char (format_string_loc, format_string_cst, | |
2084 format_chars + 1 - orig_format_chars, | |
2085 OPT_Wformat_, | |
2086 "repeated %s in format", _(s->name)); | |
2087 } | |
2088 else | |
2089 flag_chars.add_char (*format_chars); | |
2090 | |
2091 if (s->skip_next_char) | |
2092 { | |
2093 ++format_chars; | |
2094 if (*format_chars == 0) | |
2095 { | |
2096 warning_at (format_string_loc, OPT_Wformat_, | |
2097 "missing fill character at end of strfmon format"); | |
2098 return false; | |
2099 } | |
2100 } | |
2101 ++format_chars; | |
2102 } | |
2103 | |
2104 return true; | |
2105 } | |
2106 | |
2107 /* Read any format width, possibly * or *m$. | |
2108 | |
2109 Return true if format parsing is to continue, false otherwise. */ | |
2110 | |
2111 bool | |
2112 argument_parser:: | |
2113 read_any_format_width (tree ¶ms, | |
2114 unsigned HOST_WIDE_INT &arg_num) | |
2115 { | |
2116 if (!fki->width_char) | |
2117 return true; | |
2118 | |
2119 if (fki->width_type != NULL && *format_chars == '*') | |
2120 { | |
2121 flag_chars.add_char (fki->width_char); | |
2122 /* "...a field width...may be indicated by an asterisk. | |
2123 In this case, an int argument supplies the field width..." */ | |
2124 ++format_chars; | |
2125 if (has_operand_number != 0) | |
2126 { | |
2127 int opnum; | |
2128 opnum = maybe_read_dollar_number (&format_chars, | |
2129 has_operand_number == 1, | |
2130 first_fillin_param, | |
2131 ¶ms, fki); | |
2132 if (opnum == -1) | |
2133 return false; | |
2134 else if (opnum > 0) | |
2135 { | |
2136 has_operand_number = 1; | |
2137 arg_num = opnum + info->first_arg_num - 1; | |
2138 } | |
2139 else | |
2140 has_operand_number = 0; | |
2141 } | |
2142 else | |
2143 { | |
2144 if (avoid_dollar_number (format_chars)) | |
2145 return false; | |
2146 } | |
2147 if (info->first_arg_num != 0) | |
2148 { | |
2149 tree cur_param; | |
2150 if (params == 0) | |
2151 cur_param = NULL; | |
2152 else | |
2153 { | |
2154 cur_param = TREE_VALUE (params); | |
2155 if (has_operand_number <= 0) | |
2156 { | |
2157 params = TREE_CHAIN (params); | |
2158 ++arg_num; | |
2159 } | |
2160 } | |
2161 width_wanted_type.wanted_type = *fki->width_type; | |
2162 width_wanted_type.wanted_type_name = NULL; | |
2163 width_wanted_type.pointer_count = 0; | |
2164 width_wanted_type.char_lenient_flag = 0; | |
2165 width_wanted_type.scalar_identity_flag = 0; | |
2166 width_wanted_type.writing_in_flag = 0; | |
2167 width_wanted_type.reading_from_flag = 0; | |
2168 width_wanted_type.kind = CF_KIND_FIELD_WIDTH; | |
2169 width_wanted_type.format_start = format_chars - 1; | |
2170 width_wanted_type.format_length = 1; | |
2171 width_wanted_type.param = cur_param; | |
2172 width_wanted_type.arg_num = arg_num; | |
2173 width_wanted_type.offset_loc = | |
2174 format_chars - orig_format_chars; | |
2175 width_wanted_type.next = NULL; | |
2176 if (last_wanted_type != 0) | |
2177 last_wanted_type->next = &width_wanted_type; | |
2178 if (first_wanted_type == 0) | |
2179 first_wanted_type = &width_wanted_type; | |
2180 last_wanted_type = &width_wanted_type; | |
2181 } | |
2182 } | |
2183 else | |
2184 { | |
2185 /* Possibly read a numeric width. If the width is zero, | |
2186 we complain if appropriate. */ | |
2187 int non_zero_width_char = FALSE; | |
2188 int found_width = FALSE; | |
2189 while (ISDIGIT (*format_chars)) | |
2190 { | |
2191 found_width = TRUE; | |
2192 if (*format_chars != '0') | |
2193 non_zero_width_char = TRUE; | |
2194 ++format_chars; | |
2195 } | |
2196 if (found_width && !non_zero_width_char && | |
2197 (fki->flags & (int) FMT_FLAG_ZERO_WIDTH_BAD)) | |
2198 warning_at (format_string_loc, OPT_Wformat_, | |
2199 "zero width in %s format", fki->name); | |
2200 if (found_width) | |
2201 flag_chars.add_char (fki->width_char); | |
2202 } | |
2203 | |
2204 return true; | |
2205 } | |
2206 | |
2207 /* Read any format left precision (must be a number, not *). */ | |
2208 void | |
2209 argument_parser::read_any_format_left_precision () | |
2210 { | |
2211 if (fki->left_precision_char == 0) | |
2212 return; | |
2213 if (*format_chars != '#') | |
2214 return; | |
2215 | |
2216 ++format_chars; | |
2217 flag_chars.add_char (fki->left_precision_char); | |
2218 if (!ISDIGIT (*format_chars)) | |
2219 format_warning_at_char (format_string_loc, format_string_cst, | |
2220 format_chars - orig_format_chars, | |
2221 OPT_Wformat_, | |
2222 "empty left precision in %s format", fki->name); | |
2223 while (ISDIGIT (*format_chars)) | |
2224 ++format_chars; | |
2225 } | |
2226 | |
2227 /* Read any format precision, possibly * or *m$. | |
2228 | |
2229 Return true if format parsing is to continue, false otherwise. */ | |
2230 | |
2231 bool | |
2232 argument_parser:: | |
2233 read_any_format_precision (tree ¶ms, | |
2234 unsigned HOST_WIDE_INT &arg_num) | |
2235 { | |
2236 if (fki->precision_char == 0) | |
2237 return true; | |
2238 if (*format_chars != '.') | |
2239 return true; | |
2240 | |
2241 ++format_chars; | |
2242 flag_chars.add_char (fki->precision_char); | |
2243 if (fki->precision_type != NULL && *format_chars == '*') | |
2244 { | |
2245 /* "...a...precision...may be indicated by an asterisk. | |
2246 In this case, an int argument supplies the...precision." */ | |
2247 ++format_chars; | |
2248 if (has_operand_number != 0) | |
2249 { | |
2250 int opnum; | |
2251 opnum = maybe_read_dollar_number (&format_chars, | |
2252 has_operand_number == 1, | |
2253 first_fillin_param, | |
2254 ¶ms, fki); | |
2255 if (opnum == -1) | |
2256 return false; | |
2257 else if (opnum > 0) | |
2258 { | |
2259 has_operand_number = 1; | |
2260 arg_num = opnum + info->first_arg_num - 1; | |
2261 } | |
2262 else | |
2263 has_operand_number = 0; | |
2264 } | |
2265 else | |
2266 { | |
2267 if (avoid_dollar_number (format_chars)) | |
2268 return false; | |
2269 } | |
2270 if (info->first_arg_num != 0) | |
2271 { | |
2272 tree cur_param; | |
2273 if (params == 0) | |
2274 cur_param = NULL; | |
2275 else | |
2276 { | |
2277 cur_param = TREE_VALUE (params); | |
2278 if (has_operand_number <= 0) | |
2279 { | |
2280 params = TREE_CHAIN (params); | |
2281 ++arg_num; | |
2282 } | |
2283 } | |
2284 precision_wanted_type.wanted_type = *fki->precision_type; | |
2285 precision_wanted_type.wanted_type_name = NULL; | |
2286 precision_wanted_type.pointer_count = 0; | |
2287 precision_wanted_type.char_lenient_flag = 0; | |
2288 precision_wanted_type.scalar_identity_flag = 0; | |
2289 precision_wanted_type.writing_in_flag = 0; | |
2290 precision_wanted_type.reading_from_flag = 0; | |
2291 precision_wanted_type.kind = CF_KIND_FIELD_PRECISION; | |
2292 precision_wanted_type.param = cur_param; | |
2293 precision_wanted_type.format_start = format_chars - 2; | |
2294 precision_wanted_type.format_length = 2; | |
2295 precision_wanted_type.arg_num = arg_num; | |
2296 precision_wanted_type.offset_loc = | |
2297 format_chars - orig_format_chars; | |
2298 precision_wanted_type.next = NULL; | |
2299 if (last_wanted_type != 0) | |
2300 last_wanted_type->next = &precision_wanted_type; | |
2301 if (first_wanted_type == 0) | |
2302 first_wanted_type = &precision_wanted_type; | |
2303 last_wanted_type = &precision_wanted_type; | |
2304 } | |
2305 } | |
2306 else | |
2307 { | |
2308 if (!(fki->flags & (int) FMT_FLAG_EMPTY_PREC_OK) | |
2309 && !ISDIGIT (*format_chars)) | |
2310 format_warning_at_char (format_string_loc, format_string_cst, | |
2311 format_chars - orig_format_chars, | |
2312 OPT_Wformat_, | |
2313 "empty precision in %s format", fki->name); | |
2314 while (ISDIGIT (*format_chars)) | |
2315 ++format_chars; | |
2316 } | |
2317 | |
2318 return true; | |
2319 } | |
2320 | |
2321 /* Parse any assignment-allocation flags, which request an extra | |
2322 char ** for writing back a dynamically-allocated char *. | |
2323 This is for handling the optional 'm' character in scanf, | |
2324 and, before C99, 'a' (for compatibility with a non-standard | |
2325 GNU libc extension). */ | |
2326 | |
2327 void | |
2328 argument_parser::handle_alloc_chars () | |
2329 { | |
2330 if (fki->alloc_char && fki->alloc_char == *format_chars) | |
2331 { | |
2332 flag_chars.add_char (fki->alloc_char); | |
2333 format_chars++; | |
2334 } | |
2335 | |
2336 /* Handle the scanf allocation kludge. */ | |
2337 if (fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE) | |
2338 { | |
2339 if (*format_chars == 'a' && !flag_isoc99) | |
2340 { | |
2341 if (format_chars[1] == 's' || format_chars[1] == 'S' | |
2342 || format_chars[1] == '[') | |
2343 { | |
2344 /* 'a' is used as a flag. */ | |
2345 flag_chars.add_char ('a'); | |
2346 format_chars++; | |
2347 } | |
2348 } | |
2349 } | |
2350 } | |
2351 | |
2352 /* Look for length modifiers within the current format argument, | |
2353 returning a length_modifier instance describing it (or the | |
2354 default if one is not found). | |
2355 | |
2356 Issue warnings about non-standard modifiers. */ | |
2357 | |
2358 length_modifier | |
2359 argument_parser::read_any_length_modifier () | |
2360 { | |
2361 length_modifier result; | |
2362 | |
2363 const format_length_info *fli = fki->length_char_specs; | |
2364 if (!fli) | |
2365 return result; | |
2366 | |
2367 while (fli->name != 0 | |
2368 && strncmp (fli->name, format_chars, strlen (fli->name))) | |
2369 fli++; | |
2370 if (fli->name != 0) | |
2371 { | |
2372 format_chars += strlen (fli->name); | |
2373 if (fli->double_name != 0 && fli->name[0] == *format_chars) | |
2374 { | |
2375 format_chars++; | |
2376 result = length_modifier (fli->double_name, fli->double_index, | |
2377 fli->double_std, 0); | |
2378 } | |
2379 else | |
2380 { | |
2381 result = length_modifier (fli->name, fli->index, fli->std, | |
2382 fli->scalar_identity_flag); | |
2383 } | |
2384 flag_chars.add_char (fki->length_code_char); | |
2385 } | |
2386 if (pedantic) | |
2387 { | |
2388 /* Warn if the length modifier is non-standard. */ | |
2389 if (ADJ_STD (result.std) > C_STD_VER) | |
2390 warning_at (format_string_loc, OPT_Wformat_, | |
2391 "%s does not support the %qs %s length modifier", | |
2392 C_STD_NAME (result.std), result.chars, | |
2393 fki->name); | |
2394 } | |
2395 | |
2396 return result; | |
2397 } | |
2398 | |
2399 /* Read any other modifier (strftime E/O). */ | |
2400 | |
2401 void | |
2402 argument_parser::read_any_other_modifier () | |
2403 { | |
2404 if (fki->modifier_chars == NULL) | |
2405 return; | |
2406 | |
2407 while (*format_chars != 0 | |
2408 && strchr (fki->modifier_chars, *format_chars) != 0) | |
2409 { | |
2410 if (flag_chars.has_char_p (*format_chars)) | |
2411 { | |
2412 const format_flag_spec *s = get_flag_spec (flag_specs, | |
2413 *format_chars, NULL); | |
2414 format_warning_at_char (format_string_loc, format_string_cst, | |
2415 format_chars - orig_format_chars, | |
2416 OPT_Wformat_, | |
2417 "repeated %s in format", _(s->name)); | |
2418 } | |
2419 else | |
2420 flag_chars.add_char (*format_chars); | |
2421 ++format_chars; | |
2422 } | |
2423 } | |
2424 | |
2425 /* Return the format_char_info corresponding to FORMAT_CHAR, | |
2426 potentially issuing a warning if the format char is | |
2427 not supported in the C standard version we are checking | |
2428 against. | |
2429 | |
2430 Issue a warning and return NULL if it is not found. | |
2431 | |
2432 Issue warnings about non-standard modifiers. */ | |
2433 | |
2434 const format_char_info * | |
2435 argument_parser::find_format_char_info (char format_char) | |
2436 { | |
2437 const format_char_info *fci = fki->conversion_specs; | |
2438 | |
2439 while (fci->format_chars != 0 | |
2440 && strchr (fci->format_chars, format_char) == 0) | |
2441 ++fci; | |
2442 if (fci->format_chars == 0) | |
2443 { | |
2444 format_warning_at_char (format_string_loc, format_string_cst, | |
2445 format_chars - orig_format_chars, | |
2446 OPT_Wformat_, | |
2447 "unknown conversion type character" | |
2448 " %qc in format", | |
2449 format_char); | |
2450 return NULL; | |
2451 } | |
2452 | |
2453 if (pedantic) | |
2454 { | |
2455 if (ADJ_STD (fci->std) > C_STD_VER) | |
2456 format_warning_at_char (format_string_loc, format_string_cst, | |
2457 format_chars - orig_format_chars, | |
2458 OPT_Wformat_, | |
2459 "%s does not support the %<%%%c%> %s format", | |
2460 C_STD_NAME (fci->std), format_char, fki->name); | |
2461 } | |
2462 | |
2463 return fci; | |
2464 } | |
2465 | |
2466 /* Validate the pairs of flags used. | |
2467 Issue warnings about incompatible combinations of flags. */ | |
2468 | |
2469 void | |
2470 argument_parser::validate_flag_pairs (const format_char_info *fci, | |
2471 char format_char) | |
2472 { | |
2473 const format_flag_pair * const bad_flag_pairs = fki->bad_flag_pairs; | |
2474 | |
2475 for (int i = 0; bad_flag_pairs[i].flag_char1 != 0; i++) | |
2476 { | |
2477 const format_flag_spec *s, *t; | |
2478 if (!flag_chars.has_char_p (bad_flag_pairs[i].flag_char1)) | |
2479 continue; | |
2480 if (!flag_chars.has_char_p (bad_flag_pairs[i].flag_char2)) | |
2481 continue; | |
2482 if (bad_flag_pairs[i].predicate != 0 | |
2483 && strchr (fci->flags2, bad_flag_pairs[i].predicate) == 0) | |
2484 continue; | |
2485 s = get_flag_spec (flag_specs, bad_flag_pairs[i].flag_char1, NULL); | |
2486 t = get_flag_spec (flag_specs, bad_flag_pairs[i].flag_char2, NULL); | |
2487 if (bad_flag_pairs[i].ignored) | |
2488 { | |
2489 if (bad_flag_pairs[i].predicate != 0) | |
2490 warning_at (format_string_loc, OPT_Wformat_, | |
2491 "%s ignored with %s and %<%%%c%> %s format", | |
2492 _(s->name), _(t->name), format_char, | |
2493 fki->name); | |
2494 else | |
2495 warning_at (format_string_loc, OPT_Wformat_, | |
2496 "%s ignored with %s in %s format", | |
2497 _(s->name), _(t->name), fki->name); | |
2498 } | |
2499 else | |
2500 { | |
2501 if (bad_flag_pairs[i].predicate != 0) | |
2502 warning_at (format_string_loc, OPT_Wformat_, | |
2503 "use of %s and %s together with %<%%%c%> %s format", | |
2504 _(s->name), _(t->name), format_char, | |
2505 fki->name); | |
2506 else | |
2507 warning_at (format_string_loc, OPT_Wformat_, | |
2508 "use of %s and %s together in %s format", | |
2509 _(s->name), _(t->name), fki->name); | |
2510 } | |
2511 } | |
2512 } | |
2513 | |
2514 /* Give Y2K warnings. */ | |
2515 | |
2516 void | |
2517 argument_parser::give_y2k_warnings (const format_char_info *fci, | |
2518 char format_char) | |
2519 { | |
2520 if (!warn_format_y2k) | |
2521 return; | |
2522 | |
2523 int y2k_level = 0; | |
2524 if (strchr (fci->flags2, '4') != 0) | |
2525 if (flag_chars.has_char_p ('E')) | |
2526 y2k_level = 3; | |
2527 else | |
2528 y2k_level = 2; | |
2529 else if (strchr (fci->flags2, '3') != 0) | |
2530 y2k_level = 3; | |
2531 else if (strchr (fci->flags2, '2') != 0) | |
2532 y2k_level = 2; | |
2533 if (y2k_level == 3) | |
2534 warning_at (format_string_loc, OPT_Wformat_y2k, | |
2535 "%<%%%c%> yields only last 2 digits of " | |
2536 "year in some locales", format_char); | |
2537 else if (y2k_level == 2) | |
2538 warning_at (format_string_loc, OPT_Wformat_y2k, | |
2539 "%<%%%c%> yields only last 2 digits of year", | |
2540 format_char); | |
2541 } | |
2542 | |
2543 /* Parse any "scan sets" enclosed in square brackets, e.g. | |
2544 for scanf-style calls. */ | |
2545 | |
2546 void | |
2547 argument_parser::parse_any_scan_set (const format_char_info *fci) | |
2548 { | |
2549 if (strchr (fci->flags2, '[') == NULL) | |
2550 return; | |
2551 | |
2552 /* Skip over scan set, in case it happens to have '%' in it. */ | |
2553 if (*format_chars == '^') | |
2554 ++format_chars; | |
2555 /* Find closing bracket; if one is hit immediately, then | |
2556 it's part of the scan set rather than a terminator. */ | |
2557 if (*format_chars == ']') | |
2558 ++format_chars; | |
2559 while (*format_chars && *format_chars != ']') | |
2560 ++format_chars; | |
2561 if (*format_chars != ']') | |
2562 /* The end of the format string was reached. */ | |
2563 format_warning_at_char (format_string_loc, format_string_cst, | |
2564 format_chars - orig_format_chars, | |
2565 OPT_Wformat_, | |
2566 "no closing %<]%> for %<%%[%> format"); | |
2567 } | |
2568 | |
2569 /* Return true if this argument is to be continued to be parsed, | |
2570 false to skip to next argument. */ | |
2571 | |
2572 bool | |
2573 argument_parser::handle_conversions (const format_char_info *fci, | |
2574 const length_modifier &len_modifier, | |
2575 tree &wanted_type, | |
2576 const char *&wanted_type_name, | |
2577 unsigned HOST_WIDE_INT &arg_num, | |
2578 tree ¶ms, | |
2579 char format_char) | |
2580 { | |
2581 enum format_std_version wanted_type_std; | |
2582 | |
2583 if (!(fki->flags & (int) FMT_FLAG_ARG_CONVERT)) | |
2584 return true; | |
2585 | |
2586 wanted_type = (fci->types[len_modifier.val].type | |
2587 ? *fci->types[len_modifier.val].type : 0); | |
2588 wanted_type_name = fci->types[len_modifier.val].name; | |
2589 wanted_type_std = fci->types[len_modifier.val].std; | |
2590 if (wanted_type == 0) | |
2591 { | |
2592 format_warning_at_char (format_string_loc, format_string_cst, | |
2593 format_chars - orig_format_chars, | |
2594 OPT_Wformat_, | |
2595 "use of %qs length modifier with %qc type" | |
2596 " character has either no effect" | |
2597 " or undefined behavior", | |
2598 len_modifier.chars, format_char); | |
2599 /* Heuristic: skip one argument when an invalid length/type | |
2600 combination is encountered. */ | |
2601 arg_num++; | |
2602 if (params != 0) | |
2603 params = TREE_CHAIN (params); | |
2604 return false; | |
2605 } | |
2606 else if (pedantic | |
2607 /* Warn if non-standard, provided it is more non-standard | |
2608 than the length and type characters that may already | |
2609 have been warned for. */ | |
2610 && ADJ_STD (wanted_type_std) > ADJ_STD (len_modifier.std) | |
2611 && ADJ_STD (wanted_type_std) > ADJ_STD (fci->std)) | |
2612 { | |
2613 if (ADJ_STD (wanted_type_std) > C_STD_VER) | |
2614 format_warning_at_char (format_string_loc, format_string_cst, | |
2615 format_chars - orig_format_chars, | |
2616 OPT_Wformat_, | |
2617 "%s does not support the %<%%%s%c%> %s format", | |
2618 C_STD_NAME (wanted_type_std), | |
2619 len_modifier.chars, | |
2620 format_char, fki->name); | |
2621 } | |
2622 | |
2623 return true; | |
2624 } | |
2625 | |
2626 /* Check type of argument against desired type. | |
2627 | |
2628 Return true if format parsing is to continue, false otherwise. */ | |
2629 | |
2630 bool | |
2631 argument_parser:: | |
2632 check_argument_type (const format_char_info *fci, | |
2633 const length_modifier &len_modifier, | |
2634 tree &wanted_type, | |
2635 const char *&wanted_type_name, | |
2636 const bool suppressed, | |
2637 unsigned HOST_WIDE_INT &arg_num, | |
2638 tree ¶ms, | |
2639 const int alloc_flag, | |
2640 const char * const format_start, | |
2641 const char * const type_start, | |
2642 location_t fmt_param_loc, | |
2643 char conversion_char) | |
2644 { | |
2645 if (info->first_arg_num == 0) | |
2646 return true; | |
2647 | |
2648 if ((fci->pointer_count == 0 && wanted_type == void_type_node) | |
2649 || suppressed) | |
2650 { | |
2651 if (main_arg_num != 0) | |
2652 { | |
2653 if (suppressed) | |
2654 warning_at (format_string_loc, OPT_Wformat_, | |
2655 "operand number specified with " | |
2656 "suppressed assignment"); | |
2657 else | |
2658 warning_at (format_string_loc, OPT_Wformat_, | |
2659 "operand number specified for format " | |
2660 "taking no argument"); | |
2661 } | |
2662 } | |
2663 else | |
2664 { | |
2665 format_wanted_type *wanted_type_ptr; | |
2666 | |
2667 if (main_arg_num != 0) | |
2668 { | |
2669 arg_num = main_arg_num; | |
2670 params = main_arg_params; | |
2671 } | |
2672 else | |
2673 { | |
2674 ++arg_num; | |
2675 if (has_operand_number > 0) | |
2676 { | |
2677 warning_at (format_string_loc, OPT_Wformat_, | |
2678 "missing $ operand number in format"); | |
2679 return false; | |
2680 } | |
2681 else | |
2682 has_operand_number = 0; | |
2683 } | |
2684 | |
2685 wanted_type_ptr = &main_wanted_type; | |
2686 while (fci) | |
2687 { | |
2688 tree cur_param; | |
2689 if (params == 0) | |
2690 cur_param = NULL; | |
2691 else | |
2692 { | |
2693 cur_param = TREE_VALUE (params); | |
2694 params = TREE_CHAIN (params); | |
2695 } | |
2696 | |
2697 wanted_type_ptr->wanted_type = wanted_type; | |
2698 wanted_type_ptr->wanted_type_name = wanted_type_name; | |
2699 wanted_type_ptr->pointer_count = fci->pointer_count + alloc_flag; | |
2700 wanted_type_ptr->char_lenient_flag = 0; | |
2701 if (strchr (fci->flags2, 'c') != 0) | |
2702 wanted_type_ptr->char_lenient_flag = 1; | |
2703 wanted_type_ptr->scalar_identity_flag = 0; | |
2704 if (len_modifier.scalar_identity_flag) | |
2705 wanted_type_ptr->scalar_identity_flag = 1; | |
2706 wanted_type_ptr->writing_in_flag = 0; | |
2707 wanted_type_ptr->reading_from_flag = 0; | |
2708 if (alloc_flag) | |
2709 wanted_type_ptr->writing_in_flag = 1; | |
2710 else | |
2711 { | |
2712 if (strchr (fci->flags2, 'W') != 0) | |
2713 wanted_type_ptr->writing_in_flag = 1; | |
2714 if (strchr (fci->flags2, 'R') != 0) | |
2715 wanted_type_ptr->reading_from_flag = 1; | |
2716 } | |
2717 wanted_type_ptr->kind = CF_KIND_FORMAT; | |
2718 wanted_type_ptr->param = cur_param; | |
2719 wanted_type_ptr->arg_num = arg_num; | |
2720 wanted_type_ptr->format_start = format_start; | |
2721 wanted_type_ptr->format_length = format_chars - format_start; | |
2722 wanted_type_ptr->offset_loc = format_chars - orig_format_chars; | |
2723 wanted_type_ptr->next = NULL; | |
2724 if (last_wanted_type != 0) | |
2725 last_wanted_type->next = wanted_type_ptr; | |
2726 if (first_wanted_type == 0) | |
2727 first_wanted_type = wanted_type_ptr; | |
2728 last_wanted_type = wanted_type_ptr; | |
2729 | |
2730 fci = fci->chain; | |
2731 if (fci) | |
2732 { | |
2733 wanted_type_ptr = fwt_pool.allocate (); | |
2734 arg_num++; | |
2735 wanted_type = *fci->types[len_modifier.val].type; | |
2736 wanted_type_name = fci->types[len_modifier.val].name; | |
2737 } | |
2738 } | |
2739 } | |
2740 | |
2741 if (first_wanted_type != 0) | |
2742 { | |
2743 ptrdiff_t offset_to_format_start = (start_of_this_format - 1) - orig_format_chars; | |
2744 ptrdiff_t offset_to_format_end = (format_chars - 1) - orig_format_chars; | |
2745 /* By default, use the end of the range for the caret location. */ | |
2746 substring_loc fmt_loc (fmt_param_loc, TREE_TYPE (format_string_cst), | |
2747 offset_to_format_end, | |
2748 offset_to_format_start, offset_to_format_end); | |
2749 ptrdiff_t offset_to_type_start = type_start - orig_format_chars; | |
2750 check_format_types (fmt_loc, first_wanted_type, fki, | |
2751 offset_to_type_start, | |
2752 conversion_char, arglocs); | |
2753 } | |
2754 | |
2755 return true; | |
2756 } | |
1610 | 2757 |
1611 /* Do the main part of checking a call to a format function. FORMAT_CHARS | 2758 /* Do the main part of checking a call to a format function. FORMAT_CHARS |
1612 is the NUL-terminated format string (which at this point may contain | 2759 is the NUL-terminated format string (which at this point may contain |
1613 internal NUL characters); FORMAT_LENGTH is its length (excluding the | 2760 internal NUL characters); FORMAT_LENGTH is its length (excluding the |
1614 terminating NUL character). ARG_NUM is one less than the number of | 2761 terminating NUL character). ARG_NUM is one less than the number of |
1616 argument in the list of arguments. */ | 2763 argument in the list of arguments. */ |
1617 | 2764 |
1618 static void | 2765 static void |
1619 check_format_info_main (format_check_results *res, | 2766 check_format_info_main (format_check_results *res, |
1620 function_format_info *info, const char *format_chars, | 2767 function_format_info *info, const char *format_chars, |
2768 location_t fmt_param_loc, tree format_string_cst, | |
1621 int format_length, tree params, | 2769 int format_length, tree params, |
1622 unsigned HOST_WIDE_INT arg_num, alloc_pool fwt_pool) | 2770 unsigned HOST_WIDE_INT arg_num, |
1623 { | 2771 object_allocator <format_wanted_type> &fwt_pool, |
1624 const char *orig_format_chars = format_chars; | 2772 vec<location_t> *arglocs) |
1625 tree first_fillin_param = params; | 2773 { |
1626 | 2774 const char * const orig_format_chars = format_chars; |
1627 const format_kind_info *fki = &format_types[info->format_type]; | 2775 const tree first_fillin_param = params; |
1628 const format_flag_spec *flag_specs = fki->flag_specs; | 2776 |
1629 const format_flag_pair *bad_flag_pairs = fki->bad_flag_pairs; | 2777 const format_kind_info * const fki = &format_types[info->format_type]; |
2778 const format_flag_spec * const flag_specs = fki->flag_specs; | |
2779 const location_t format_string_loc = res->format_string_loc; | |
1630 | 2780 |
1631 /* -1 if no conversions taking an operand have been found; 0 if one has | 2781 /* -1 if no conversions taking an operand have been found; 0 if one has |
1632 and it didn't use $; 1 if $ formats are in use. */ | 2782 and it didn't use $; 1 if $ formats are in use. */ |
1633 int has_operand_number = -1; | 2783 int has_operand_number = -1; |
1634 | 2784 |
2785 /* Vector of pointers to opening quoting directives (like GCC "%<"). */ | |
2786 auto_vec<const char*> quotdirs; | |
2787 | |
2788 /* Pointers to the most recent color directives (like GCC's "%r or %R"). | |
2789 A starting color directive much be terminated before the end of | |
2790 the format string. A terminating directive makes no sense without | |
2791 a prior starting directive. */ | |
2792 const char *color_begin = NULL; | |
2793 const char *color_end = NULL; | |
2794 | |
1635 init_dollar_format_checking (info->first_arg_num, first_fillin_param); | 2795 init_dollar_format_checking (info->first_arg_num, first_fillin_param); |
1636 | 2796 |
1637 while (*format_chars != 0) | 2797 while (*format_chars != 0) |
1638 { | 2798 { |
1639 int i; | |
1640 int suppressed = FALSE; | |
1641 const char *length_chars = NULL; | |
1642 enum format_lengths length_chars_val = FMT_LEN_none; | |
1643 enum format_std_version length_chars_std = STD_C89; | |
1644 int format_char; | |
1645 tree cur_param; | |
1646 tree wanted_type; | |
1647 int main_arg_num = 0; | |
1648 tree main_arg_params = 0; | |
1649 enum format_std_version wanted_type_std; | |
1650 const char *wanted_type_name; | |
1651 format_wanted_type width_wanted_type; | |
1652 format_wanted_type precision_wanted_type; | |
1653 format_wanted_type main_wanted_type; | |
1654 format_wanted_type *first_wanted_type = NULL; | |
1655 format_wanted_type *last_wanted_type = NULL; | |
1656 const format_length_info *fli = NULL; | |
1657 const format_char_info *fci = NULL; | |
1658 char flag_chars[256]; | |
1659 int alloc_flag = 0; | |
1660 int scalar_identity_flag = 0; | |
1661 const char *format_start; | |
1662 | |
1663 if (*format_chars++ != '%') | 2799 if (*format_chars++ != '%') |
1664 continue; | 2800 continue; |
1665 if (*format_chars == 0) | 2801 if (*format_chars == 0) |
1666 { | 2802 { |
1667 warning (OPT_Wformat, "spurious trailing %<%%%> in format"); | 2803 format_warning_at_char (format_string_loc, format_string_cst, |
2804 format_chars - orig_format_chars, | |
2805 OPT_Wformat_, | |
2806 "spurious trailing %<%%%> in format"); | |
1668 continue; | 2807 continue; |
1669 } | 2808 } |
1670 if (*format_chars == '%') | 2809 if (*format_chars == '%') |
1671 { | 2810 { |
1672 ++format_chars; | 2811 ++format_chars; |
1673 continue; | 2812 continue; |
1674 } | 2813 } |
1675 flag_chars[0] = 0; | 2814 |
1676 | 2815 flag_chars_t flag_chars; |
1677 if ((fki->flags & (int) FMT_FLAG_USE_DOLLAR) && has_operand_number != 0) | 2816 argument_parser arg_parser (info, format_chars, format_string_cst, |
1678 { | 2817 orig_format_chars, format_string_loc, |
1679 /* Possibly read a $ operand number at the start of the format. | 2818 flag_chars, has_operand_number, |
1680 If one was previously used, one is required here. If one | 2819 first_fillin_param, fwt_pool, arglocs); |
1681 is not used here, we can't immediately conclude this is a | 2820 |
1682 format without them, since it could be printf %m or scanf %*. */ | 2821 if (!arg_parser.read_any_dollar ()) |
1683 int opnum; | 2822 return; |
1684 opnum = maybe_read_dollar_number (&format_chars, 0, | 2823 |
1685 first_fillin_param, | 2824 if (!arg_parser.read_format_flags ()) |
1686 &main_arg_params, fki); | 2825 return; |
1687 if (opnum == -1) | |
1688 return; | |
1689 else if (opnum > 0) | |
1690 { | |
1691 has_operand_number = 1; | |
1692 main_arg_num = opnum + info->first_arg_num - 1; | |
1693 } | |
1694 } | |
1695 else if (fki->flags & FMT_FLAG_USE_DOLLAR) | |
1696 { | |
1697 if (avoid_dollar_number (format_chars)) | |
1698 return; | |
1699 } | |
1700 | |
1701 /* Read any format flags, but do not yet validate them beyond removing | |
1702 duplicates, since in general validation depends on the rest of | |
1703 the format. */ | |
1704 while (*format_chars != 0 | |
1705 && strchr (fki->flag_chars, *format_chars) != 0) | |
1706 { | |
1707 const format_flag_spec *s = get_flag_spec (flag_specs, | |
1708 *format_chars, NULL); | |
1709 if (strchr (flag_chars, *format_chars) != 0) | |
1710 { | |
1711 warning (OPT_Wformat, "repeated %s in format", _(s->name)); | |
1712 } | |
1713 else | |
1714 { | |
1715 i = strlen (flag_chars); | |
1716 flag_chars[i++] = *format_chars; | |
1717 flag_chars[i] = 0; | |
1718 } | |
1719 if (s->skip_next_char) | |
1720 { | |
1721 ++format_chars; | |
1722 if (*format_chars == 0) | |
1723 { | |
1724 warning (OPT_Wformat, "missing fill character at end of strfmon format"); | |
1725 return; | |
1726 } | |
1727 } | |
1728 ++format_chars; | |
1729 } | |
1730 | 2826 |
1731 /* Read any format width, possibly * or *m$. */ | 2827 /* Read any format width, possibly * or *m$. */ |
1732 if (fki->width_char != 0) | 2828 if (!arg_parser.read_any_format_width (params, arg_num)) |
1733 { | 2829 return; |
1734 if (fki->width_type != NULL && *format_chars == '*') | |
1735 { | |
1736 i = strlen (flag_chars); | |
1737 flag_chars[i++] = fki->width_char; | |
1738 flag_chars[i] = 0; | |
1739 /* "...a field width...may be indicated by an asterisk. | |
1740 In this case, an int argument supplies the field width..." */ | |
1741 ++format_chars; | |
1742 if (has_operand_number != 0) | |
1743 { | |
1744 int opnum; | |
1745 opnum = maybe_read_dollar_number (&format_chars, | |
1746 has_operand_number == 1, | |
1747 first_fillin_param, | |
1748 ¶ms, fki); | |
1749 if (opnum == -1) | |
1750 return; | |
1751 else if (opnum > 0) | |
1752 { | |
1753 has_operand_number = 1; | |
1754 arg_num = opnum + info->first_arg_num - 1; | |
1755 } | |
1756 else | |
1757 has_operand_number = 0; | |
1758 } | |
1759 else | |
1760 { | |
1761 if (avoid_dollar_number (format_chars)) | |
1762 return; | |
1763 } | |
1764 if (info->first_arg_num != 0) | |
1765 { | |
1766 if (params == 0) | |
1767 cur_param = NULL; | |
1768 else | |
1769 { | |
1770 cur_param = TREE_VALUE (params); | |
1771 if (has_operand_number <= 0) | |
1772 { | |
1773 params = TREE_CHAIN (params); | |
1774 ++arg_num; | |
1775 } | |
1776 } | |
1777 width_wanted_type.wanted_type = *fki->width_type; | |
1778 width_wanted_type.wanted_type_name = NULL; | |
1779 width_wanted_type.pointer_count = 0; | |
1780 width_wanted_type.char_lenient_flag = 0; | |
1781 width_wanted_type.scalar_identity_flag = 0; | |
1782 width_wanted_type.writing_in_flag = 0; | |
1783 width_wanted_type.reading_from_flag = 0; | |
1784 width_wanted_type.kind = CF_KIND_FIELD_WIDTH; | |
1785 width_wanted_type.format_start = format_chars - 1; | |
1786 width_wanted_type.format_length = 1; | |
1787 width_wanted_type.param = cur_param; | |
1788 width_wanted_type.arg_num = arg_num; | |
1789 width_wanted_type.next = NULL; | |
1790 if (last_wanted_type != 0) | |
1791 last_wanted_type->next = &width_wanted_type; | |
1792 if (first_wanted_type == 0) | |
1793 first_wanted_type = &width_wanted_type; | |
1794 last_wanted_type = &width_wanted_type; | |
1795 } | |
1796 } | |
1797 else | |
1798 { | |
1799 /* Possibly read a numeric width. If the width is zero, | |
1800 we complain if appropriate. */ | |
1801 int non_zero_width_char = FALSE; | |
1802 int found_width = FALSE; | |
1803 while (ISDIGIT (*format_chars)) | |
1804 { | |
1805 found_width = TRUE; | |
1806 if (*format_chars != '0') | |
1807 non_zero_width_char = TRUE; | |
1808 ++format_chars; | |
1809 } | |
1810 if (found_width && !non_zero_width_char && | |
1811 (fki->flags & (int) FMT_FLAG_ZERO_WIDTH_BAD)) | |
1812 warning (OPT_Wformat, "zero width in %s format", fki->name); | |
1813 if (found_width) | |
1814 { | |
1815 i = strlen (flag_chars); | |
1816 flag_chars[i++] = fki->width_char; | |
1817 flag_chars[i] = 0; | |
1818 } | |
1819 } | |
1820 } | |
1821 | 2830 |
1822 /* Read any format left precision (must be a number, not *). */ | 2831 /* Read any format left precision (must be a number, not *). */ |
1823 if (fki->left_precision_char != 0 && *format_chars == '#') | 2832 arg_parser.read_any_format_left_precision (); |
1824 { | |
1825 ++format_chars; | |
1826 i = strlen (flag_chars); | |
1827 flag_chars[i++] = fki->left_precision_char; | |
1828 flag_chars[i] = 0; | |
1829 if (!ISDIGIT (*format_chars)) | |
1830 warning (OPT_Wformat, "empty left precision in %s format", fki->name); | |
1831 while (ISDIGIT (*format_chars)) | |
1832 ++format_chars; | |
1833 } | |
1834 | 2833 |
1835 /* Read any format precision, possibly * or *m$. */ | 2834 /* Read any format precision, possibly * or *m$. */ |
1836 if (fki->precision_char != 0 && *format_chars == '.') | 2835 if (!arg_parser.read_any_format_precision (params, arg_num)) |
1837 { | 2836 return; |
1838 ++format_chars; | 2837 |
1839 i = strlen (flag_chars); | 2838 const char *format_start = format_chars; |
1840 flag_chars[i++] = fki->precision_char; | 2839 |
1841 flag_chars[i] = 0; | 2840 arg_parser.handle_alloc_chars (); |
1842 if (fki->precision_type != NULL && *format_chars == '*') | 2841 |
1843 { | 2842 /* The rest of the conversion specification is the length modifier |
1844 /* "...a...precision...may be indicated by an asterisk. | 2843 (if any), and the conversion specifier, so this is where the |
1845 In this case, an int argument supplies the...precision." */ | 2844 type information starts. If we need to issue a suggestion |
1846 ++format_chars; | 2845 about a type mismatch, then we should preserve everything up |
1847 if (has_operand_number != 0) | 2846 to here. */ |
1848 { | 2847 const char *type_start = format_chars; |
1849 int opnum; | |
1850 opnum = maybe_read_dollar_number (&format_chars, | |
1851 has_operand_number == 1, | |
1852 first_fillin_param, | |
1853 ¶ms, fki); | |
1854 if (opnum == -1) | |
1855 return; | |
1856 else if (opnum > 0) | |
1857 { | |
1858 has_operand_number = 1; | |
1859 arg_num = opnum + info->first_arg_num - 1; | |
1860 } | |
1861 else | |
1862 has_operand_number = 0; | |
1863 } | |
1864 else | |
1865 { | |
1866 if (avoid_dollar_number (format_chars)) | |
1867 return; | |
1868 } | |
1869 if (info->first_arg_num != 0) | |
1870 { | |
1871 if (params == 0) | |
1872 cur_param = NULL; | |
1873 else | |
1874 { | |
1875 cur_param = TREE_VALUE (params); | |
1876 if (has_operand_number <= 0) | |
1877 { | |
1878 params = TREE_CHAIN (params); | |
1879 ++arg_num; | |
1880 } | |
1881 } | |
1882 precision_wanted_type.wanted_type = *fki->precision_type; | |
1883 precision_wanted_type.wanted_type_name = NULL; | |
1884 precision_wanted_type.pointer_count = 0; | |
1885 precision_wanted_type.char_lenient_flag = 0; | |
1886 precision_wanted_type.scalar_identity_flag = 0; | |
1887 precision_wanted_type.writing_in_flag = 0; | |
1888 precision_wanted_type.reading_from_flag = 0; | |
1889 precision_wanted_type.kind = CF_KIND_FIELD_PRECISION; | |
1890 precision_wanted_type.param = cur_param; | |
1891 precision_wanted_type.format_start = format_chars - 2; | |
1892 precision_wanted_type.format_length = 2; | |
1893 precision_wanted_type.arg_num = arg_num; | |
1894 precision_wanted_type.next = NULL; | |
1895 if (last_wanted_type != 0) | |
1896 last_wanted_type->next = &precision_wanted_type; | |
1897 if (first_wanted_type == 0) | |
1898 first_wanted_type = &precision_wanted_type; | |
1899 last_wanted_type = &precision_wanted_type; | |
1900 } | |
1901 } | |
1902 else | |
1903 { | |
1904 if (!(fki->flags & (int) FMT_FLAG_EMPTY_PREC_OK) | |
1905 && !ISDIGIT (*format_chars)) | |
1906 warning (OPT_Wformat, "empty precision in %s format", fki->name); | |
1907 while (ISDIGIT (*format_chars)) | |
1908 ++format_chars; | |
1909 } | |
1910 } | |
1911 | |
1912 format_start = format_chars; | |
1913 if (fki->alloc_char && fki->alloc_char == *format_chars) | |
1914 { | |
1915 i = strlen (flag_chars); | |
1916 flag_chars[i++] = fki->alloc_char; | |
1917 flag_chars[i] = 0; | |
1918 format_chars++; | |
1919 } | |
1920 | |
1921 /* Handle the scanf allocation kludge. */ | |
1922 if (fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE) | |
1923 { | |
1924 if (*format_chars == 'a' && !flag_isoc99) | |
1925 { | |
1926 if (format_chars[1] == 's' || format_chars[1] == 'S' | |
1927 || format_chars[1] == '[') | |
1928 { | |
1929 /* 'a' is used as a flag. */ | |
1930 i = strlen (flag_chars); | |
1931 flag_chars[i++] = 'a'; | |
1932 flag_chars[i] = 0; | |
1933 format_chars++; | |
1934 } | |
1935 } | |
1936 } | |
1937 | 2848 |
1938 /* Read any length modifier, if this kind of format has them. */ | 2849 /* Read any length modifier, if this kind of format has them. */ |
1939 fli = fki->length_char_specs; | 2850 const length_modifier len_modifier |
1940 length_chars = NULL; | 2851 = arg_parser.read_any_length_modifier (); |
1941 length_chars_val = FMT_LEN_none; | |
1942 length_chars_std = STD_C89; | |
1943 scalar_identity_flag = 0; | |
1944 if (fli) | |
1945 { | |
1946 while (fli->name != 0 | |
1947 && strncmp (fli->name, format_chars, strlen (fli->name))) | |
1948 fli++; | |
1949 if (fli->name != 0) | |
1950 { | |
1951 format_chars += strlen (fli->name); | |
1952 if (fli->double_name != 0 && fli->name[0] == *format_chars) | |
1953 { | |
1954 format_chars++; | |
1955 length_chars = fli->double_name; | |
1956 length_chars_val = fli->double_index; | |
1957 length_chars_std = fli->double_std; | |
1958 } | |
1959 else | |
1960 { | |
1961 length_chars = fli->name; | |
1962 length_chars_val = fli->index; | |
1963 length_chars_std = fli->std; | |
1964 scalar_identity_flag = fli->scalar_identity_flag; | |
1965 } | |
1966 i = strlen (flag_chars); | |
1967 flag_chars[i++] = fki->length_code_char; | |
1968 flag_chars[i] = 0; | |
1969 } | |
1970 if (pedantic) | |
1971 { | |
1972 /* Warn if the length modifier is non-standard. */ | |
1973 if (ADJ_STD (length_chars_std) > C_STD_VER) | |
1974 warning (OPT_Wformat, | |
1975 "%s does not support the %qs %s length modifier", | |
1976 C_STD_NAME (length_chars_std), length_chars, | |
1977 fki->name); | |
1978 } | |
1979 } | |
1980 | 2852 |
1981 /* Read any modifier (strftime E/O). */ | 2853 /* Read any modifier (strftime E/O). */ |
1982 if (fki->modifier_chars != NULL) | 2854 arg_parser.read_any_other_modifier (); |
1983 { | 2855 |
1984 while (*format_chars != 0 | 2856 char format_char = *format_chars; |
1985 && strchr (fki->modifier_chars, *format_chars) != 0) | |
1986 { | |
1987 if (strchr (flag_chars, *format_chars) != 0) | |
1988 { | |
1989 const format_flag_spec *s = get_flag_spec (flag_specs, | |
1990 *format_chars, NULL); | |
1991 warning (OPT_Wformat, "repeated %s in format", _(s->name)); | |
1992 } | |
1993 else | |
1994 { | |
1995 i = strlen (flag_chars); | |
1996 flag_chars[i++] = *format_chars; | |
1997 flag_chars[i] = 0; | |
1998 } | |
1999 ++format_chars; | |
2000 } | |
2001 } | |
2002 | |
2003 format_char = *format_chars; | |
2004 if (format_char == 0 | 2857 if (format_char == 0 |
2005 || (!(fki->flags & (int) FMT_FLAG_FANCY_PERCENT_OK) | 2858 || (!(fki->flags & (int) FMT_FLAG_FANCY_PERCENT_OK) |
2006 && format_char == '%')) | 2859 && format_char == '%')) |
2007 { | 2860 { |
2008 warning (OPT_Wformat, "conversion lacks type at end of format"); | 2861 format_warning_at_char (format_string_loc, format_string_cst, |
2862 format_chars - orig_format_chars, | |
2863 OPT_Wformat_, | |
2864 "conversion lacks type at end of format"); | |
2009 continue; | 2865 continue; |
2010 } | 2866 } |
2011 format_chars++; | 2867 format_chars++; |
2012 fci = fki->conversion_specs; | 2868 |
2013 while (fci->format_chars != 0 | 2869 const format_char_info * const fci |
2014 && strchr (fci->format_chars, format_char) == 0) | 2870 = arg_parser.find_format_char_info (format_char); |
2015 ++fci; | 2871 if (!fci) |
2016 if (fci->format_chars == 0) | 2872 continue; |
2017 { | 2873 |
2018 if (ISGRAPH (format_char)) | 2874 flag_chars.validate (fki, fci, flag_specs, format_chars, |
2019 warning (OPT_Wformat, "unknown conversion type character %qc in format", | 2875 format_string_cst, |
2020 format_char); | 2876 format_string_loc, orig_format_chars, format_char, |
2877 quotdirs.length () > 0); | |
2878 | |
2879 const int alloc_flag = flag_chars.get_alloc_flag (fki); | |
2880 const bool suppressed = flag_chars.assignment_suppression_p (fki); | |
2881 | |
2882 /* Diagnose nested or unmatched quoting directives such as GCC's | |
2883 "%<...%<" and "%>...%>". */ | |
2884 bool quot_begin_p = strchr (fci->flags2, '<'); | |
2885 bool quot_end_p = strchr (fci->flags2, '>'); | |
2886 | |
2887 if (quot_begin_p && !quot_end_p) | |
2888 { | |
2889 if (quotdirs.length ()) | |
2890 format_warning_at_char (format_string_loc, format_string_cst, | |
2891 format_chars - orig_format_chars, | |
2892 OPT_Wformat_, | |
2893 "nested quoting directive"); | |
2894 quotdirs.safe_push (format_chars); | |
2895 } | |
2896 else if (!quot_begin_p && quot_end_p) | |
2897 { | |
2898 if (quotdirs.length ()) | |
2899 quotdirs.pop (); | |
2021 else | 2900 else |
2022 warning (OPT_Wformat, "unknown conversion type character 0x%x in format", | 2901 format_warning_at_char (format_string_loc, format_string_cst, |
2023 format_char); | 2902 format_chars - orig_format_chars, |
2024 continue; | 2903 OPT_Wformat_, |
2025 } | 2904 "unmatched quoting directive"); |
2026 if (pedantic) | 2905 } |
2027 { | 2906 |
2028 if (ADJ_STD (fci->std) > C_STD_VER) | 2907 bool color_begin_p = strchr (fci->flags2, '/'); |
2029 warning (OPT_Wformat, "%s does not support the %<%%%c%> %s format", | 2908 if (color_begin_p) |
2030 C_STD_NAME (fci->std), format_char, fki->name); | 2909 { |
2031 } | 2910 color_begin = format_chars; |
2032 | 2911 color_end = NULL; |
2033 /* Validate the individual flags used, removing any that are invalid. */ | 2912 } |
2034 { | 2913 else if (strchr (fci->flags2, '\\')) |
2035 int d = 0; | 2914 { |
2036 for (i = 0; flag_chars[i] != 0; i++) | 2915 if (color_end) |
2037 { | 2916 format_warning_at_char (format_string_loc, format_string_cst, |
2038 const format_flag_spec *s = get_flag_spec (flag_specs, | 2917 format_chars - orig_format_chars, |
2039 flag_chars[i], NULL); | 2918 OPT_Wformat_, |
2040 flag_chars[i - d] = flag_chars[i]; | 2919 "%qc directive redundant after prior " |
2041 if (flag_chars[i] == fki->length_code_char) | 2920 "occurence of the same", format_char); |
2042 continue; | 2921 else if (!color_begin) |
2043 if (strchr (fci->flag_chars, flag_chars[i]) == 0) | 2922 format_warning_at_char (format_string_loc, format_string_cst, |
2044 { | 2923 format_chars - orig_format_chars, |
2045 warning (OPT_Wformat, "%s used with %<%%%c%> %s format", | 2924 OPT_Wformat_, |
2046 _(s->name), format_char, fki->name); | 2925 "unmatched color reset directive"); |
2047 d++; | 2926 color_end = format_chars; |
2048 continue; | 2927 } |
2049 } | 2928 |
2050 if (pedantic) | 2929 /* Diagnose directives that shouldn't appear in a quoted sequence. |
2051 { | 2930 (They are denoted by a double quote in FLAGS2.) */ |
2052 const format_flag_spec *t; | 2931 if (quotdirs.length ()) |
2053 if (ADJ_STD (s->std) > C_STD_VER) | 2932 { |
2054 warning (OPT_Wformat, "%s does not support %s", | 2933 if (strchr (fci->flags2, '"')) |
2055 C_STD_NAME (s->std), _(s->long_name)); | 2934 format_warning_at_char (format_string_loc, format_string_cst, |
2056 t = get_flag_spec (flag_specs, flag_chars[i], fci->flags2); | 2935 format_chars - orig_format_chars, |
2057 if (t != NULL && ADJ_STD (t->std) > ADJ_STD (s->std)) | 2936 OPT_Wformat_, |
2058 { | 2937 "%qc conversion used within a quoted " |
2059 const char *long_name = (t->long_name != NULL | 2938 "sequence", |
2060 ? t->long_name | 2939 format_char); |
2061 : s->long_name); | 2940 } |
2062 if (ADJ_STD (t->std) > C_STD_VER) | |
2063 warning (OPT_Wformat, | |
2064 "%s does not support %s with the %<%%%c%> %s format", | |
2065 C_STD_NAME (t->std), _(long_name), | |
2066 format_char, fki->name); | |
2067 } | |
2068 } | |
2069 } | |
2070 flag_chars[i - d] = 0; | |
2071 } | |
2072 | |
2073 if ((fki->flags & (int) FMT_FLAG_SCANF_A_KLUDGE) | |
2074 && strchr (flag_chars, 'a') != 0) | |
2075 alloc_flag = 1; | |
2076 if (fki->alloc_char && strchr (flag_chars, fki->alloc_char) != 0) | |
2077 alloc_flag = 1; | |
2078 | |
2079 if (fki->suppression_char | |
2080 && strchr (flag_chars, fki->suppression_char) != 0) | |
2081 suppressed = 1; | |
2082 | 2941 |
2083 /* Validate the pairs of flags used. */ | 2942 /* Validate the pairs of flags used. */ |
2084 for (i = 0; bad_flag_pairs[i].flag_char1 != 0; i++) | 2943 arg_parser.validate_flag_pairs (fci, format_char); |
2085 { | 2944 |
2086 const format_flag_spec *s, *t; | 2945 arg_parser.give_y2k_warnings (fci, format_char); |
2087 if (strchr (flag_chars, bad_flag_pairs[i].flag_char1) == 0) | 2946 |
2088 continue; | 2947 arg_parser.parse_any_scan_set (fci); |
2089 if (strchr (flag_chars, bad_flag_pairs[i].flag_char2) == 0) | 2948 |
2090 continue; | 2949 tree wanted_type = NULL; |
2091 if (bad_flag_pairs[i].predicate != 0 | 2950 const char *wanted_type_name = NULL; |
2092 && strchr (fci->flags2, bad_flag_pairs[i].predicate) == 0) | 2951 |
2093 continue; | 2952 if (!arg_parser.handle_conversions (fci, len_modifier, |
2094 s = get_flag_spec (flag_specs, bad_flag_pairs[i].flag_char1, NULL); | 2953 wanted_type, wanted_type_name, |
2095 t = get_flag_spec (flag_specs, bad_flag_pairs[i].flag_char2, NULL); | 2954 arg_num, |
2096 if (bad_flag_pairs[i].ignored) | 2955 params, |
2097 { | 2956 format_char)) |
2098 if (bad_flag_pairs[i].predicate != 0) | 2957 continue; |
2099 warning (OPT_Wformat, | 2958 |
2100 "%s ignored with %s and %<%%%c%> %s format", | 2959 arg_parser.main_wanted_type.next = NULL; |
2101 _(s->name), _(t->name), format_char, | |
2102 fki->name); | |
2103 else | |
2104 warning (OPT_Wformat, "%s ignored with %s in %s format", | |
2105 _(s->name), _(t->name), fki->name); | |
2106 } | |
2107 else | |
2108 { | |
2109 if (bad_flag_pairs[i].predicate != 0) | |
2110 warning (OPT_Wformat, | |
2111 "use of %s and %s together with %<%%%c%> %s format", | |
2112 _(s->name), _(t->name), format_char, | |
2113 fki->name); | |
2114 else | |
2115 warning (OPT_Wformat, "use of %s and %s together in %s format", | |
2116 _(s->name), _(t->name), fki->name); | |
2117 } | |
2118 } | |
2119 | |
2120 /* Give Y2K warnings. */ | |
2121 if (warn_format_y2k) | |
2122 { | |
2123 int y2k_level = 0; | |
2124 if (strchr (fci->flags2, '4') != 0) | |
2125 if (strchr (flag_chars, 'E') != 0) | |
2126 y2k_level = 3; | |
2127 else | |
2128 y2k_level = 2; | |
2129 else if (strchr (fci->flags2, '3') != 0) | |
2130 y2k_level = 3; | |
2131 else if (strchr (fci->flags2, '2') != 0) | |
2132 y2k_level = 2; | |
2133 if (y2k_level == 3) | |
2134 warning (OPT_Wformat_y2k, "%<%%%c%> yields only last 2 digits of " | |
2135 "year in some locales", format_char); | |
2136 else if (y2k_level == 2) | |
2137 warning (OPT_Wformat_y2k, "%<%%%c%> yields only last 2 digits of " | |
2138 "year", format_char); | |
2139 } | |
2140 | |
2141 if (strchr (fci->flags2, '[') != 0) | |
2142 { | |
2143 /* Skip over scan set, in case it happens to have '%' in it. */ | |
2144 if (*format_chars == '^') | |
2145 ++format_chars; | |
2146 /* Find closing bracket; if one is hit immediately, then | |
2147 it's part of the scan set rather than a terminator. */ | |
2148 if (*format_chars == ']') | |
2149 ++format_chars; | |
2150 while (*format_chars && *format_chars != ']') | |
2151 ++format_chars; | |
2152 if (*format_chars != ']') | |
2153 /* The end of the format string was reached. */ | |
2154 warning (OPT_Wformat, "no closing %<]%> for %<%%[%> format"); | |
2155 } | |
2156 | |
2157 wanted_type = 0; | |
2158 wanted_type_name = 0; | |
2159 if (fki->flags & (int) FMT_FLAG_ARG_CONVERT) | |
2160 { | |
2161 wanted_type = (fci->types[length_chars_val].type | |
2162 ? *fci->types[length_chars_val].type : 0); | |
2163 wanted_type_name = fci->types[length_chars_val].name; | |
2164 wanted_type_std = fci->types[length_chars_val].std; | |
2165 if (wanted_type == 0) | |
2166 { | |
2167 warning (OPT_Wformat, | |
2168 "use of %qs length modifier with %qc type character", | |
2169 length_chars, format_char); | |
2170 /* Heuristic: skip one argument when an invalid length/type | |
2171 combination is encountered. */ | |
2172 arg_num++; | |
2173 if (params != 0) | |
2174 params = TREE_CHAIN (params); | |
2175 continue; | |
2176 } | |
2177 else if (pedantic | |
2178 /* Warn if non-standard, provided it is more non-standard | |
2179 than the length and type characters that may already | |
2180 have been warned for. */ | |
2181 && ADJ_STD (wanted_type_std) > ADJ_STD (length_chars_std) | |
2182 && ADJ_STD (wanted_type_std) > ADJ_STD (fci->std)) | |
2183 { | |
2184 if (ADJ_STD (wanted_type_std) > C_STD_VER) | |
2185 warning (OPT_Wformat, | |
2186 "%s does not support the %<%%%s%c%> %s format", | |
2187 C_STD_NAME (wanted_type_std), length_chars, | |
2188 format_char, fki->name); | |
2189 } | |
2190 } | |
2191 | |
2192 main_wanted_type.next = NULL; | |
2193 | 2960 |
2194 /* Finally. . .check type of argument against desired type! */ | 2961 /* Finally. . .check type of argument against desired type! */ |
2195 if (info->first_arg_num == 0) | 2962 if (!arg_parser.check_argument_type (fci, len_modifier, |
2196 continue; | 2963 wanted_type, wanted_type_name, |
2197 if ((fci->pointer_count == 0 && wanted_type == void_type_node) | 2964 suppressed, |
2198 || suppressed) | 2965 arg_num, params, |
2199 { | 2966 alloc_flag, |
2200 if (main_arg_num != 0) | 2967 format_start, type_start, |
2201 { | 2968 fmt_param_loc, |
2202 if (suppressed) | 2969 format_char)) |
2203 warning (OPT_Wformat, "operand number specified with " | 2970 return; |
2204 "suppressed assignment"); | |
2205 else | |
2206 warning (OPT_Wformat, "operand number specified for format " | |
2207 "taking no argument"); | |
2208 } | |
2209 } | |
2210 else | |
2211 { | |
2212 format_wanted_type *wanted_type_ptr; | |
2213 | |
2214 if (main_arg_num != 0) | |
2215 { | |
2216 arg_num = main_arg_num; | |
2217 params = main_arg_params; | |
2218 } | |
2219 else | |
2220 { | |
2221 ++arg_num; | |
2222 if (has_operand_number > 0) | |
2223 { | |
2224 warning (OPT_Wformat, "missing $ operand number in format"); | |
2225 return; | |
2226 } | |
2227 else | |
2228 has_operand_number = 0; | |
2229 } | |
2230 | |
2231 wanted_type_ptr = &main_wanted_type; | |
2232 while (fci) | |
2233 { | |
2234 if (params == 0) | |
2235 cur_param = NULL; | |
2236 else | |
2237 { | |
2238 cur_param = TREE_VALUE (params); | |
2239 params = TREE_CHAIN (params); | |
2240 } | |
2241 | |
2242 wanted_type_ptr->wanted_type = wanted_type; | |
2243 wanted_type_ptr->wanted_type_name = wanted_type_name; | |
2244 wanted_type_ptr->pointer_count = fci->pointer_count + alloc_flag; | |
2245 wanted_type_ptr->char_lenient_flag = 0; | |
2246 if (strchr (fci->flags2, 'c') != 0) | |
2247 wanted_type_ptr->char_lenient_flag = 1; | |
2248 wanted_type_ptr->scalar_identity_flag = 0; | |
2249 if (scalar_identity_flag) | |
2250 wanted_type_ptr->scalar_identity_flag = 1; | |
2251 wanted_type_ptr->writing_in_flag = 0; | |
2252 wanted_type_ptr->reading_from_flag = 0; | |
2253 if (alloc_flag) | |
2254 wanted_type_ptr->writing_in_flag = 1; | |
2255 else | |
2256 { | |
2257 if (strchr (fci->flags2, 'W') != 0) | |
2258 wanted_type_ptr->writing_in_flag = 1; | |
2259 if (strchr (fci->flags2, 'R') != 0) | |
2260 wanted_type_ptr->reading_from_flag = 1; | |
2261 } | |
2262 wanted_type_ptr->kind = CF_KIND_FORMAT; | |
2263 wanted_type_ptr->param = cur_param; | |
2264 wanted_type_ptr->arg_num = arg_num; | |
2265 wanted_type_ptr->format_start = format_start; | |
2266 wanted_type_ptr->format_length = format_chars - format_start; | |
2267 wanted_type_ptr->next = NULL; | |
2268 if (last_wanted_type != 0) | |
2269 last_wanted_type->next = wanted_type_ptr; | |
2270 if (first_wanted_type == 0) | |
2271 first_wanted_type = wanted_type_ptr; | |
2272 last_wanted_type = wanted_type_ptr; | |
2273 | |
2274 fci = fci->chain; | |
2275 if (fci) | |
2276 { | |
2277 wanted_type_ptr = (format_wanted_type *) | |
2278 pool_alloc (fwt_pool); | |
2279 arg_num++; | |
2280 wanted_type = *fci->types[length_chars_val].type; | |
2281 wanted_type_name = fci->types[length_chars_val].name; | |
2282 } | |
2283 } | |
2284 } | |
2285 | |
2286 if (first_wanted_type != 0) | |
2287 check_format_types (first_wanted_type); | |
2288 } | 2971 } |
2289 | 2972 |
2290 if (format_chars - orig_format_chars != format_length) | 2973 if (format_chars - orig_format_chars != format_length) |
2291 warning (OPT_Wformat_contains_nul, "embedded %<\\0%> in format"); | 2974 format_warning_at_char (format_string_loc, format_string_cst, |
2975 format_chars + 1 - orig_format_chars, | |
2976 OPT_Wformat_contains_nul, | |
2977 "embedded %<\\0%> in format"); | |
2292 if (info->first_arg_num != 0 && params != 0 | 2978 if (info->first_arg_num != 0 && params != 0 |
2293 && has_operand_number <= 0) | 2979 && has_operand_number <= 0) |
2294 { | 2980 { |
2295 res->number_other--; | 2981 res->number_other--; |
2296 res->number_extra_args++; | 2982 res->number_extra_args++; |
2297 } | 2983 } |
2298 if (has_operand_number > 0) | 2984 if (has_operand_number > 0) |
2299 finish_dollar_format_checking (res, fki->flags & (int) FMT_FLAG_DOLLAR_GAP_POINTER_OK); | 2985 finish_dollar_format_checking (res, fki->flags & (int) FMT_FLAG_DOLLAR_GAP_POINTER_OK); |
2300 } | 2986 |
2301 | 2987 if (quotdirs.length ()) |
2988 format_warning_at_char (format_string_loc, format_string_cst, | |
2989 quotdirs.pop () - orig_format_chars, | |
2990 OPT_Wformat_, "unterminated quoting directive"); | |
2991 if (color_begin && !color_end) | |
2992 format_warning_at_char (format_string_loc, format_string_cst, | |
2993 color_begin - orig_format_chars, | |
2994 OPT_Wformat_, "unterminated color directive"); | |
2995 } | |
2302 | 2996 |
2303 /* Check the argument types from a single format conversion (possibly | 2997 /* Check the argument types from a single format conversion (possibly |
2304 including width and precision arguments). */ | 2998 including width and precision arguments). |
2999 | |
3000 FMT_LOC is the location of the format conversion. | |
3001 | |
3002 TYPES is a singly-linked list expressing the parts of the format | |
3003 conversion that expect argument types, and the arguments they | |
3004 correspond to. | |
3005 | |
3006 OFFSET_TO_TYPE_START is the offset within the execution-charset encoded | |
3007 format string to where type information begins for the conversion | |
3008 (the length modifier and conversion specifier). | |
3009 | |
3010 CONVERSION_CHAR is the user-provided conversion specifier. | |
3011 | |
3012 For example, given: | |
3013 | |
3014 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5); | |
3015 | |
3016 then FMT_LOC covers this range: | |
3017 | |
3018 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5); | |
3019 ^^^^^^^^^ | |
3020 | |
3021 and TYPES in this case is a three-entry singly-linked list consisting of: | |
3022 (1) the check for the field width here: | |
3023 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5); | |
3024 ^ ^^^^ | |
3025 against arg3, and | |
3026 (2) the check for the field precision here: | |
3027 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5); | |
3028 ^^ ^^^^ | |
3029 against arg4, and | |
3030 (3) the check for the length modifier and conversion char here: | |
3031 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5); | |
3032 ^^^ ^^^^ | |
3033 against arg5. | |
3034 | |
3035 OFFSET_TO_TYPE_START is 13, the offset to the "lld" within the | |
3036 STRING_CST: | |
3037 | |
3038 0000000000111111111122 | |
3039 0123456789012345678901 | |
3040 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5); | |
3041 ^ ^ | |
3042 | ` CONVERSION_CHAR: 'd' | |
3043 type starts here. */ | |
3044 | |
2305 static void | 3045 static void |
2306 check_format_types (format_wanted_type *types) | 3046 check_format_types (const substring_loc &fmt_loc, |
3047 format_wanted_type *types, const format_kind_info *fki, | |
3048 int offset_to_type_start, | |
3049 char conversion_char, | |
3050 vec<location_t> *arglocs) | |
2307 { | 3051 { |
2308 for (; types != 0; types = types->next) | 3052 for (; types != 0; types = types->next) |
2309 { | 3053 { |
2310 tree cur_param; | 3054 tree cur_param; |
2311 tree cur_type; | 3055 tree cur_type; |
2328 wanted_type = TYPE_MAIN_VARIANT (wanted_type); | 3072 wanted_type = TYPE_MAIN_VARIANT (wanted_type); |
2329 | 3073 |
2330 cur_param = types->param; | 3074 cur_param = types->param; |
2331 if (!cur_param) | 3075 if (!cur_param) |
2332 { | 3076 { |
2333 format_type_warning (types, wanted_type, NULL); | 3077 format_type_warning (fmt_loc, UNKNOWN_LOCATION, types, wanted_type, |
3078 NULL, fki, offset_to_type_start, | |
3079 conversion_char); | |
2334 continue; | 3080 continue; |
2335 } | 3081 } |
2336 | 3082 |
2337 cur_type = TREE_TYPE (cur_param); | 3083 cur_type = TREE_TYPE (cur_param); |
2338 if (cur_type == error_mark_node) | 3084 if (cur_type == error_mark_node) |
2339 continue; | 3085 continue; |
2340 orig_cur_type = cur_type; | 3086 orig_cur_type = cur_type; |
2341 char_type_flag = 0; | 3087 char_type_flag = 0; |
2342 | 3088 |
3089 location_t param_loc = UNKNOWN_LOCATION; | |
3090 if (EXPR_HAS_LOCATION (cur_param)) | |
3091 param_loc = EXPR_LOCATION (cur_param); | |
3092 else if (arglocs) | |
3093 { | |
3094 /* arg_num is 1-based. */ | |
3095 gcc_assert (types->arg_num > 0); | |
3096 param_loc = (*arglocs)[types->arg_num - 1]; | |
3097 } | |
3098 | |
2343 STRIP_NOPS (cur_param); | 3099 STRIP_NOPS (cur_param); |
2344 | 3100 |
2345 /* Check the types of any additional pointer arguments | 3101 /* Check the types of any additional pointer arguments |
2346 that precede the "real" argument. */ | 3102 that precede the "real" argument. */ |
2347 for (i = 0; i < types->pointer_count; ++i) | 3103 for (i = 0; i < types->pointer_count; ++i) |
2355 /* Check for writing through a NULL pointer. */ | 3111 /* Check for writing through a NULL pointer. */ |
2356 if (types->writing_in_flag | 3112 if (types->writing_in_flag |
2357 && i == 0 | 3113 && i == 0 |
2358 && cur_param != 0 | 3114 && cur_param != 0 |
2359 && integer_zerop (cur_param)) | 3115 && integer_zerop (cur_param)) |
2360 warning (OPT_Wformat, "writing through null pointer " | 3116 warning (OPT_Wformat_, "writing through null pointer " |
2361 "(argument %d)", arg_num); | 3117 "(argument %d)", arg_num); |
2362 | 3118 |
2363 /* Check for reading through a NULL pointer. */ | 3119 /* Check for reading through a NULL pointer. */ |
2364 if (types->reading_from_flag | 3120 if (types->reading_from_flag |
2365 && i == 0 | 3121 && i == 0 |
2366 && cur_param != 0 | 3122 && cur_param != 0 |
2367 && integer_zerop (cur_param)) | 3123 && integer_zerop (cur_param)) |
2368 warning (OPT_Wformat, "reading through null pointer " | 3124 warning (OPT_Wformat_, "reading through null pointer " |
2369 "(argument %d)", arg_num); | 3125 "(argument %d)", arg_num); |
2370 | 3126 |
2371 if (cur_param != 0 && TREE_CODE (cur_param) == ADDR_EXPR) | 3127 if (cur_param != 0 && TREE_CODE (cur_param) == ADDR_EXPR) |
2372 cur_param = TREE_OPERAND (cur_param, 0); | 3128 cur_param = TREE_OPERAND (cur_param, 0); |
2373 else | 3129 else |
2383 && (TYPE_READONLY (cur_type) | 3139 && (TYPE_READONLY (cur_type) |
2384 || (cur_param != 0 | 3140 || (cur_param != 0 |
2385 && (CONSTANT_CLASS_P (cur_param) | 3141 && (CONSTANT_CLASS_P (cur_param) |
2386 || (DECL_P (cur_param) | 3142 || (DECL_P (cur_param) |
2387 && TREE_READONLY (cur_param)))))) | 3143 && TREE_READONLY (cur_param)))))) |
2388 warning (OPT_Wformat, "writing into constant object " | 3144 warning (OPT_Wformat_, "writing into constant object " |
2389 "(argument %d)", arg_num); | 3145 "(argument %d)", arg_num); |
2390 | 3146 |
2391 /* If there are extra type qualifiers beyond the first | 3147 /* If there are extra type qualifiers beyond the first |
2392 indirection, then this makes the types technically | 3148 indirection, then this makes the types technically |
2393 incompatible. */ | 3149 incompatible. */ |
2394 if (i > 0 | 3150 if (i > 0 |
2395 && pedantic | 3151 && pedantic |
2396 && (TYPE_READONLY (cur_type) | 3152 && (TYPE_READONLY (cur_type) |
2397 || TYPE_VOLATILE (cur_type) | 3153 || TYPE_VOLATILE (cur_type) |
3154 || TYPE_ATOMIC (cur_type) | |
2398 || TYPE_RESTRICT (cur_type))) | 3155 || TYPE_RESTRICT (cur_type))) |
2399 warning (OPT_Wformat, "extra type qualifiers in format " | 3156 warning (OPT_Wformat_, "extra type qualifiers in format " |
2400 "argument (argument %d)", | 3157 "argument (argument %d)", |
2401 arg_num); | 3158 arg_num); |
2402 | 3159 |
2403 } | 3160 } |
2404 else | 3161 else |
2405 { | 3162 { |
2406 format_type_warning (types, wanted_type, orig_cur_type); | 3163 format_type_warning (fmt_loc, param_loc, |
3164 types, wanted_type, orig_cur_type, fki, | |
3165 offset_to_type_start, conversion_char); | |
2407 break; | 3166 break; |
2408 } | 3167 } |
2409 } | 3168 } |
2410 | 3169 |
2411 if (i < types->pointer_count) | 3170 if (i < types->pointer_count) |
2412 continue; | 3171 continue; |
2413 | 3172 |
2414 cur_type = TYPE_MAIN_VARIANT (cur_type); | 3173 cur_type = TYPE_MAIN_VARIANT (cur_type); |
2415 | 3174 |
2416 /* Check whether the argument type is a character type. This leniency | 3175 /* Check whether the argument type is a character type. This leniency |
2417 only applies to certain formats, flagged with 'c'. | 3176 only applies to certain formats, flagged with 'c'. */ |
2418 */ | |
2419 if (types->char_lenient_flag) | 3177 if (types->char_lenient_flag) |
2420 char_type_flag = (cur_type == char_type_node | 3178 char_type_flag = (cur_type == char_type_node |
2421 || cur_type == signed_char_type_node | 3179 || cur_type == signed_char_type_node |
2422 || cur_type == unsigned_char_type_node); | 3180 || cur_type == unsigned_char_type_node); |
2423 | 3181 |
2424 /* Check the type of the "real" argument, if there's a type we want. */ | 3182 /* Check the type of the "real" argument, if there's a type we want. */ |
2425 if (lang_hooks.types_compatible_p (wanted_type, cur_type)) | 3183 if (lang_hooks.types_compatible_p (wanted_type, cur_type)) |
2426 continue; | 3184 continue; |
2427 /* If we want 'void *', allow any pointer type. | 3185 /* If we want 'void *', allow any pointer type. |
2428 (Anything else would already have got a warning.) | 3186 (Anything else would already have got a warning.) |
2429 With -pedantic, only allow pointers to void and to character | 3187 With -Wpedantic, only allow pointers to void and to character |
2430 types. */ | 3188 types. */ |
2431 if (wanted_type == void_type_node | 3189 if (wanted_type == void_type_node |
2432 && (!pedantic || (i == 1 && char_type_flag))) | 3190 && (!pedantic || (i == 1 && char_type_flag))) |
2433 continue; | 3191 continue; |
2434 /* Don't warn about differences merely in signedness, unless | 3192 /* Don't warn about differences merely in signedness, unless |
2435 -pedantic. With -pedantic, warn if the type is a pointer | 3193 -Wpedantic. With -Wpedantic, warn if the type is a pointer |
2436 target and not a character type, and for character types at | 3194 target and not a character type, and for character types at |
2437 a second level of indirection. */ | 3195 a second level of indirection. */ |
2438 if (TREE_CODE (wanted_type) == INTEGER_TYPE | 3196 if (TREE_CODE (wanted_type) == INTEGER_TYPE |
2439 && TREE_CODE (cur_type) == INTEGER_TYPE | 3197 && TREE_CODE (cur_type) == INTEGER_TYPE |
2440 && (!pedantic || i == 0 || (i == 1 && char_type_flag)) | 3198 && ((!pedantic && !warn_format_signedness) |
3199 || (i == 0 && !warn_format_signedness) | |
3200 || (i == 1 && char_type_flag)) | |
2441 && (TYPE_UNSIGNED (wanted_type) | 3201 && (TYPE_UNSIGNED (wanted_type) |
2442 ? wanted_type == c_common_unsigned_type (cur_type) | 3202 ? wanted_type == c_common_unsigned_type (cur_type) |
2443 : wanted_type == c_common_signed_type (cur_type))) | 3203 : wanted_type == c_common_signed_type (cur_type))) |
2444 continue; | 3204 continue; |
3205 /* Don't warn about differences merely in signedness if we know | |
3206 that the current type is integer-promoted and its original type | |
3207 was unsigned such as that it is in the range of WANTED_TYPE. */ | |
3208 if (TREE_CODE (wanted_type) == INTEGER_TYPE | |
3209 && TREE_CODE (cur_type) == INTEGER_TYPE | |
3210 && warn_format_signedness | |
3211 && TYPE_UNSIGNED (wanted_type) | |
3212 && cur_param != NULL_TREE | |
3213 && TREE_CODE (cur_param) == NOP_EXPR) | |
3214 { | |
3215 tree t = TREE_TYPE (TREE_OPERAND (cur_param, 0)); | |
3216 if (TYPE_UNSIGNED (t) | |
3217 && cur_type == lang_hooks.types.type_promotes_to (t)) | |
3218 continue; | |
3219 } | |
2445 /* Likewise, "signed char", "unsigned char" and "char" are | 3220 /* Likewise, "signed char", "unsigned char" and "char" are |
2446 equivalent but the above test won't consider them equivalent. */ | 3221 equivalent but the above test won't consider them equivalent. */ |
2447 if (wanted_type == char_type_node | 3222 if (wanted_type == char_type_node |
2448 && (!pedantic || i < 2) | 3223 && (!pedantic || i < 2) |
2449 && char_type_flag) | 3224 && char_type_flag) |
2453 || (INTEGRAL_TYPE_P (cur_type) | 3228 || (INTEGRAL_TYPE_P (cur_type) |
2454 && INTEGRAL_TYPE_P (wanted_type))) | 3229 && INTEGRAL_TYPE_P (wanted_type))) |
2455 && TYPE_PRECISION (cur_type) == TYPE_PRECISION (wanted_type)) | 3230 && TYPE_PRECISION (cur_type) == TYPE_PRECISION (wanted_type)) |
2456 continue; | 3231 continue; |
2457 /* Now we have a type mismatch. */ | 3232 /* Now we have a type mismatch. */ |
2458 format_type_warning (types, wanted_type, orig_cur_type); | 3233 format_type_warning (fmt_loc, param_loc, types, |
2459 } | 3234 wanted_type, orig_cur_type, fki, |
2460 } | 3235 offset_to_type_start, conversion_char); |
2461 | 3236 } |
2462 | 3237 } |
2463 /* Give a warning about a format argument of different type from that | 3238 |
2464 expected. WANTED_TYPE is the type the argument should have, possibly | 3239 /* Given type TYPE, attempt to dereference the type N times |
2465 stripped of pointer dereferences. The description (such as "field | 3240 (e.g. from ("int ***", 2) to "int *") |
3241 | |
3242 Return the derefenced type, with any qualifiers | |
3243 such as "const" stripped from the result, or | |
3244 NULL if unsuccessful (e.g. TYPE is not a pointer type). */ | |
3245 | |
3246 static tree | |
3247 deref_n_times (tree type, int n) | |
3248 { | |
3249 gcc_assert (type); | |
3250 | |
3251 for (int i = n; i > 0; i--) | |
3252 { | |
3253 if (TREE_CODE (type) != POINTER_TYPE) | |
3254 return NULL_TREE; | |
3255 type = TREE_TYPE (type); | |
3256 } | |
3257 /* Strip off any "const" etc. */ | |
3258 return build_qualified_type (type, 0); | |
3259 } | |
3260 | |
3261 /* Lookup the format code for FORMAT_LEN within FLI, | |
3262 returning the string code for expressing it, or NULL | |
3263 if it is not found. */ | |
3264 | |
3265 static const char * | |
3266 get_modifier_for_format_len (const format_length_info *fli, | |
3267 enum format_lengths format_len) | |
3268 { | |
3269 for (; fli->name; fli++) | |
3270 { | |
3271 if (fli->index == format_len) | |
3272 return fli->name; | |
3273 if (fli->double_index == format_len) | |
3274 return fli->double_name; | |
3275 } | |
3276 return NULL; | |
3277 } | |
3278 | |
3279 #if CHECKING_P | |
3280 | |
3281 namespace selftest { | |
3282 | |
3283 static void | |
3284 test_get_modifier_for_format_len () | |
3285 { | |
3286 ASSERT_STREQ ("h", | |
3287 get_modifier_for_format_len (printf_length_specs, FMT_LEN_h)); | |
3288 ASSERT_STREQ ("hh", | |
3289 get_modifier_for_format_len (printf_length_specs, FMT_LEN_hh)); | |
3290 ASSERT_STREQ ("L", | |
3291 get_modifier_for_format_len (printf_length_specs, FMT_LEN_L)); | |
3292 ASSERT_EQ (NULL, | |
3293 get_modifier_for_format_len (printf_length_specs, FMT_LEN_none)); | |
3294 } | |
3295 | |
3296 } // namespace selftest | |
3297 | |
3298 #endif /* CHECKING_P */ | |
3299 | |
3300 /* Determine if SPEC_TYPE and ARG_TYPE are sufficiently similar for a | |
3301 format_type_detail using SPEC_TYPE to be offered as a suggestion for | |
3302 Wformat type errors where the argument has type ARG_TYPE. */ | |
3303 | |
3304 static bool | |
3305 matching_type_p (tree spec_type, tree arg_type) | |
3306 { | |
3307 gcc_assert (spec_type); | |
3308 gcc_assert (arg_type); | |
3309 | |
3310 /* If any of the types requires structural equality, we can't compare | |
3311 their canonical types. */ | |
3312 if (TYPE_STRUCTURAL_EQUALITY_P (spec_type) | |
3313 || TYPE_STRUCTURAL_EQUALITY_P (arg_type)) | |
3314 return false; | |
3315 | |
3316 spec_type = TYPE_CANONICAL (spec_type); | |
3317 arg_type = TYPE_CANONICAL (arg_type); | |
3318 | |
3319 if (TREE_CODE (spec_type) == INTEGER_TYPE | |
3320 && TREE_CODE (arg_type) == INTEGER_TYPE | |
3321 && (TYPE_UNSIGNED (spec_type) | |
3322 ? spec_type == c_common_unsigned_type (arg_type) | |
3323 : spec_type == c_common_signed_type (arg_type))) | |
3324 return true; | |
3325 | |
3326 return spec_type == arg_type; | |
3327 } | |
3328 | |
3329 /* Subroutine of get_format_for_type. | |
3330 | |
3331 Generate a string containing the length modifier and conversion specifier | |
3332 that should be used to format arguments of type ARG_TYPE within FKI | |
3333 (effectively the inverse of the checking code). | |
3334 | |
3335 If CONVERSION_CHAR is not zero (the first pass), the resulting suggestion | |
3336 is required to use it, for correcting bogus length modifiers. | |
3337 If CONVERSION_CHAR is zero (the second pass), then allow any suggestion | |
3338 that matches ARG_TYPE. | |
3339 | |
3340 If successful, returns a non-NULL string which should be freed | |
3341 by the caller. | |
3342 Otherwise, returns NULL. */ | |
3343 | |
3344 static char * | |
3345 get_format_for_type_1 (const format_kind_info *fki, tree arg_type, | |
3346 char conversion_char) | |
3347 { | |
3348 gcc_assert (arg_type); | |
3349 | |
3350 const format_char_info *spec; | |
3351 for (spec = &fki->conversion_specs[0]; | |
3352 spec->format_chars; | |
3353 spec++) | |
3354 { | |
3355 if (conversion_char) | |
3356 if (!strchr (spec->format_chars, conversion_char)) | |
3357 continue; | |
3358 | |
3359 tree effective_arg_type = deref_n_times (arg_type, | |
3360 spec->pointer_count); | |
3361 if (!effective_arg_type) | |
3362 continue; | |
3363 for (int i = 0; i < FMT_LEN_MAX; i++) | |
3364 { | |
3365 const format_type_detail *ftd = &spec->types[i]; | |
3366 if (!ftd->type) | |
3367 continue; | |
3368 if (matching_type_p (*ftd->type, effective_arg_type)) | |
3369 { | |
3370 const char *len_modifier | |
3371 = get_modifier_for_format_len (fki->length_char_specs, | |
3372 (enum format_lengths)i); | |
3373 if (!len_modifier) | |
3374 len_modifier = ""; | |
3375 | |
3376 if (conversion_char) | |
3377 /* We found a match, using the given conversion char - the | |
3378 length modifier was incorrect (or absent). | |
3379 Provide a suggestion using the conversion char with the | |
3380 correct length modifier for the type. */ | |
3381 return xasprintf ("%s%c", len_modifier, conversion_char); | |
3382 else | |
3383 /* 2nd pass: no match was possible using the user-provided | |
3384 conversion char, but we do have a match without using it. | |
3385 Provide a suggestion using the first conversion char | |
3386 listed for the given type. */ | |
3387 return xasprintf ("%s%c", len_modifier, spec->format_chars[0]); | |
3388 } | |
3389 } | |
3390 } | |
3391 | |
3392 return NULL; | |
3393 } | |
3394 | |
3395 /* Generate a string containing the length modifier and conversion specifier | |
3396 that should be used to format arguments of type ARG_TYPE within FKI | |
3397 (effectively the inverse of the checking code). | |
3398 | |
3399 If successful, returns a non-NULL string which should be freed | |
3400 by the caller. | |
3401 Otherwise, returns NULL. */ | |
3402 | |
3403 static char * | |
3404 get_format_for_type (const format_kind_info *fki, tree arg_type, | |
3405 char conversion_char) | |
3406 { | |
3407 gcc_assert (arg_type); | |
3408 gcc_assert (conversion_char); | |
3409 | |
3410 /* First pass: look for a format_char_info containing CONVERSION_CHAR | |
3411 If we find one, then presumably the length modifier was incorrect | |
3412 (or absent). */ | |
3413 char *result = get_format_for_type_1 (fki, arg_type, conversion_char); | |
3414 if (result) | |
3415 return result; | |
3416 | |
3417 /* Second pass: we didn't find a match for CONVERSION_CHAR, so try | |
3418 matching just on the type. */ | |
3419 return get_format_for_type_1 (fki, arg_type, '\0'); | |
3420 } | |
3421 | |
3422 /* Attempt to get a string for use as a replacement fix-it hint for the | |
3423 source range in FMT_LOC. | |
3424 | |
3425 Preserve all of the text within the range of FMT_LOC up to | |
3426 OFFSET_TO_TYPE_START, replacing the rest with an appropriate | |
3427 length modifier and conversion specifier for ARG_TYPE, attempting | |
3428 to keep the user-provided CONVERSION_CHAR if possible. | |
3429 | |
3430 For example, given a long vs long long mismatch for arg5 here: | |
3431 | |
3432 000000000111111111122222222223333333333| | |
3433 123456789012345678901234567890123456789` column numbers | |
3434 0000000000111111111122| | |
3435 0123456789012345678901` string offsets | |
3436 V~~~~~~~~ : range of FMT_LOC, from cols 23-31 | |
3437 sprintf (d, "before %-+*.*lld after", arg3, arg4, arg5); | |
3438 ^ ^ | |
3439 | ` CONVERSION_CHAR: 'd' | |
3440 type starts here | |
3441 | |
3442 where OFFSET_TO_TYPE_START is 13 (the offset to the "lld" within the | |
3443 STRING_CST), where the user provided: | |
3444 %-+*.*lld | |
3445 the result (assuming "long" argument 5) should be: | |
3446 %-+*.*ld | |
3447 | |
3448 If successful, returns a non-NULL string which should be freed | |
3449 by the caller. | |
3450 Otherwise, returns NULL. */ | |
3451 | |
3452 static char * | |
3453 get_corrected_substring (const substring_loc &fmt_loc, | |
3454 format_wanted_type *type, tree arg_type, | |
3455 const format_kind_info *fki, | |
3456 int offset_to_type_start, char conversion_char) | |
3457 { | |
3458 /* Attempt to provide hints for argument types, but not for field widths | |
3459 and precisions. */ | |
3460 if (!arg_type) | |
3461 return NULL; | |
3462 if (type->kind != CF_KIND_FORMAT) | |
3463 return NULL; | |
3464 | |
3465 /* Locate the current code within the source range, rejecting | |
3466 any awkward cases where the format string occupies more than | |
3467 one line. | |
3468 Lookup the place where the type starts (including any length | |
3469 modifiers), getting it as the caret location. */ | |
3470 substring_loc type_loc (fmt_loc); | |
3471 type_loc.set_caret_index (offset_to_type_start); | |
3472 | |
3473 location_t fmt_substring_loc; | |
3474 const char *err = type_loc.get_location (&fmt_substring_loc); | |
3475 if (err) | |
3476 return NULL; | |
3477 | |
3478 source_range fmt_substring_range | |
3479 = get_range_from_loc (line_table, fmt_substring_loc); | |
3480 | |
3481 expanded_location caret | |
3482 = expand_location_to_spelling_point (fmt_substring_loc); | |
3483 expanded_location start | |
3484 = expand_location_to_spelling_point (fmt_substring_range.m_start); | |
3485 expanded_location finish | |
3486 = expand_location_to_spelling_point (fmt_substring_range.m_finish); | |
3487 if (caret.file != start.file) | |
3488 return NULL; | |
3489 if (start.file != finish.file) | |
3490 return NULL; | |
3491 if (caret.line != start.line) | |
3492 return NULL; | |
3493 if (start.line != finish.line) | |
3494 return NULL; | |
3495 if (start.column > caret.column) | |
3496 return NULL; | |
3497 if (start.column > finish.column) | |
3498 return NULL; | |
3499 if (caret.column > finish.column) | |
3500 return NULL; | |
3501 | |
3502 int line_width; | |
3503 const char *line = location_get_source_line (start.file, start.line, | |
3504 &line_width); | |
3505 if (line == NULL) | |
3506 return NULL; | |
3507 | |
3508 /* If we got this far, then we have the line containing the | |
3509 existing conversion specification. | |
3510 | |
3511 Generate a trimmed copy, containing the prefix part of the conversion | |
3512 specification, up to the (but not including) the length modifier. | |
3513 In the above example, this would be "%-+*.*". */ | |
3514 const char *current_content = line + start.column - 1; | |
3515 int length_up_to_type = caret.column - start.column; | |
3516 char *prefix = xstrndup (current_content, length_up_to_type); | |
3517 | |
3518 /* Now attempt to generate a suggestion for the rest of the specification | |
3519 (length modifier and conversion char), based on ARG_TYPE and | |
3520 CONVERSION_CHAR. | |
3521 In the above example, this would be "ld". */ | |
3522 char *format_for_type = get_format_for_type (fki, arg_type, conversion_char); | |
3523 if (!format_for_type) | |
3524 { | |
3525 free (prefix); | |
3526 return NULL; | |
3527 } | |
3528 | |
3529 /* Success. Generate the resulting suggestion for the whole range of | |
3530 FMT_LOC by concatenating the two strings. | |
3531 In the above example, this would be "%-+*.*ld". */ | |
3532 char *result = concat (prefix, format_for_type, NULL); | |
3533 free (format_for_type); | |
3534 free (prefix); | |
3535 return result; | |
3536 } | |
3537 | |
3538 /* Give a warning about a format argument of different type from that expected. | |
3539 The range of the diagnostic is taken from WHOLE_FMT_LOC; the caret location | |
3540 is based on the location of the char at TYPE->offset_loc. | |
3541 PARAM_LOC is the location of the relevant argument, or UNKNOWN_LOCATION | |
3542 if this is unavailable. | |
3543 WANTED_TYPE is the type the argument should have, | |
3544 possibly stripped of pointer dereferences. The description (such as "field | |
2466 precision"), the placement in the format string, a possibly more | 3545 precision"), the placement in the format string, a possibly more |
2467 friendly name of WANTED_TYPE, and the number of pointer dereferences | 3546 friendly name of WANTED_TYPE, and the number of pointer dereferences |
2468 are taken from TYPE. ARG_TYPE is the type of the actual argument, | 3547 are taken from TYPE. ARG_TYPE is the type of the actual argument, |
2469 or NULL if it is missing. */ | 3548 or NULL if it is missing. |
3549 | |
3550 OFFSET_TO_TYPE_START is the offset within the execution-charset encoded | |
3551 format string to where type information begins for the conversion | |
3552 (the length modifier and conversion specifier). | |
3553 CONVERSION_CHAR is the user-provided conversion specifier. | |
3554 | |
3555 For example, given a type mismatch for argument 5 here: | |
3556 | |
3557 00000000011111111112222222222333333333344444444445555555555| | |
3558 12345678901234567890123456789012345678901234567890123456789` column numbers | |
3559 0000000000111111111122| | |
3560 0123456789012345678901` offsets within STRING_CST | |
3561 V~~~~~~~~ : range of WHOLE_FMT_LOC, from cols 23-31 | |
3562 sprintf (d, "before %-+*.*lld after", int_expr, int_expr, long_expr); | |
3563 ^ ^ ^~~~~~~~~ | |
3564 | ` CONVERSION_CHAR: 'd' PARAM_LOC | |
3565 type starts here | |
3566 | |
3567 OFFSET_TO_TYPE_START is 13, the offset to the "lld" within the | |
3568 STRING_CST. */ | |
3569 | |
2470 static void | 3570 static void |
2471 format_type_warning (format_wanted_type *type, tree wanted_type, tree arg_type) | 3571 format_type_warning (const substring_loc &whole_fmt_loc, |
2472 { | 3572 location_t param_loc, |
2473 int kind = type->kind; | 3573 format_wanted_type *type, |
3574 tree wanted_type, tree arg_type, | |
3575 const format_kind_info *fki, | |
3576 int offset_to_type_start, | |
3577 char conversion_char) | |
3578 { | |
3579 enum format_specifier_kind kind = type->kind; | |
2474 const char *wanted_type_name = type->wanted_type_name; | 3580 const char *wanted_type_name = type->wanted_type_name; |
2475 const char *format_start = type->format_start; | 3581 const char *format_start = type->format_start; |
2476 int format_length = type->format_length; | 3582 int format_length = type->format_length; |
2477 int pointer_count = type->pointer_count; | 3583 int pointer_count = type->pointer_count; |
2478 int arg_num = type->arg_num; | 3584 int arg_num = type->arg_num; |
2507 p[0] = ' '; | 3613 p[0] = ' '; |
2508 memset (p + 1, '*', pointer_count); | 3614 memset (p + 1, '*', pointer_count); |
2509 p[pointer_count + 1] = 0; | 3615 p[pointer_count + 1] = 0; |
2510 } | 3616 } |
2511 | 3617 |
3618 /* WHOLE_FMT_LOC has the caret at the end of the range. | |
3619 Set the caret to be at the offset from TYPE. Subtract one | |
3620 from the offset for the same reason as in format_warning_at_char. */ | |
3621 substring_loc fmt_loc (whole_fmt_loc); | |
3622 fmt_loc.set_caret_index (type->offset_loc - 1); | |
3623 | |
3624 /* Get a string for use as a replacement fix-it hint for the range in | |
3625 fmt_loc, or NULL. */ | |
3626 char *corrected_substring | |
3627 = get_corrected_substring (fmt_loc, type, arg_type, fki, | |
3628 offset_to_type_start, conversion_char); | |
3629 | |
2512 if (wanted_type_name) | 3630 if (wanted_type_name) |
2513 { | 3631 { |
2514 if (arg_type) | 3632 if (arg_type) |
2515 warning (OPT_Wformat, "%s %<%s%.*s%> expects argument of type %<%s%s%>, " | 3633 format_warning_at_substring |
2516 "but argument %d has type %qT", | 3634 (fmt_loc, param_loc, |
2517 gettext (kind_descriptions[kind]), | 3635 corrected_substring, OPT_Wformat_, |
2518 (kind == CF_KIND_FORMAT ? "%" : ""), | 3636 "%s %<%s%.*s%> expects argument of type %<%s%s%>, " |
2519 format_length, format_start, | 3637 "but argument %d has type %qT", |
2520 wanted_type_name, p, arg_num, arg_type); | 3638 gettext (kind_descriptions[kind]), |
3639 (kind == CF_KIND_FORMAT ? "%" : ""), | |
3640 format_length, format_start, | |
3641 wanted_type_name, p, arg_num, arg_type); | |
2521 else | 3642 else |
2522 warning (OPT_Wformat, "%s %<%s%.*s%> expects a matching %<%s%s%> argument", | 3643 format_warning_at_substring |
2523 gettext (kind_descriptions[kind]), | 3644 (fmt_loc, param_loc, |
2524 (kind == CF_KIND_FORMAT ? "%" : ""), | 3645 corrected_substring, OPT_Wformat_, |
2525 format_length, format_start, wanted_type_name, p); | 3646 "%s %<%s%.*s%> expects a matching %<%s%s%> argument", |
3647 gettext (kind_descriptions[kind]), | |
3648 (kind == CF_KIND_FORMAT ? "%" : ""), | |
3649 format_length, format_start, wanted_type_name, p); | |
2526 } | 3650 } |
2527 else | 3651 else |
2528 { | 3652 { |
2529 if (arg_type) | 3653 if (arg_type) |
2530 warning (OPT_Wformat, "%s %<%s%.*s%> expects argument of type %<%T%s%>, " | 3654 format_warning_at_substring |
2531 "but argument %d has type %qT", | 3655 (fmt_loc, param_loc, |
2532 gettext (kind_descriptions[kind]), | 3656 corrected_substring, OPT_Wformat_, |
2533 (kind == CF_KIND_FORMAT ? "%" : ""), | 3657 "%s %<%s%.*s%> expects argument of type %<%T%s%>, " |
2534 format_length, format_start, | 3658 "but argument %d has type %qT", |
2535 wanted_type, p, arg_num, arg_type); | 3659 gettext (kind_descriptions[kind]), |
3660 (kind == CF_KIND_FORMAT ? "%" : ""), | |
3661 format_length, format_start, | |
3662 wanted_type, p, arg_num, arg_type); | |
2536 else | 3663 else |
2537 warning (OPT_Wformat, "%s %<%s%.*s%> expects a matching %<%T%s%> argument", | 3664 format_warning_at_substring |
2538 gettext (kind_descriptions[kind]), | 3665 (fmt_loc, param_loc, |
2539 (kind == CF_KIND_FORMAT ? "%" : ""), | 3666 corrected_substring, OPT_Wformat_, |
2540 format_length, format_start, wanted_type, p); | 3667 "%s %<%s%.*s%> expects a matching %<%T%s%> argument", |
2541 } | 3668 gettext (kind_descriptions[kind]), |
3669 (kind == CF_KIND_FORMAT ? "%" : ""), | |
3670 format_length, format_start, wanted_type, p); | |
3671 } | |
3672 | |
3673 free (corrected_substring); | |
2542 } | 3674 } |
2543 | 3675 |
2544 | 3676 |
2545 /* Given a format_char_info array FCI, and a character C, this function | 3677 /* Given a format_char_info array FCI, and a character C, this function |
2546 returns the index into the conversion_specs where that specifier's | 3678 returns the index into the conversion_specs where that specifier's |
2637 in GCC's __gcc_gfc__ custom format attribute. You must have set | 3769 in GCC's __gcc_gfc__ custom format attribute. You must have set |
2638 dynamic_format_types before calling this function. */ | 3770 dynamic_format_types before calling this function. */ |
2639 static void | 3771 static void |
2640 init_dynamic_gfc_info (void) | 3772 init_dynamic_gfc_info (void) |
2641 { | 3773 { |
2642 static tree locus; | |
2643 | |
2644 if (!locus) | 3774 if (!locus) |
2645 { | 3775 { |
2646 static format_char_info *gfc_fci; | 3776 static format_char_info *gfc_fci; |
2647 | 3777 |
2648 /* For the GCC __gcc_gfc__ custom format specifier to work, one | 3778 /* For the GCC __gcc_gfc__ custom format specifier to work, one |
2687 compiled for use in GCC's diagnostic custom format attributes. You | 3817 compiled for use in GCC's diagnostic custom format attributes. You |
2688 must have set dynamic_format_types before calling this function. */ | 3818 must have set dynamic_format_types before calling this function. */ |
2689 static void | 3819 static void |
2690 init_dynamic_diag_info (void) | 3820 init_dynamic_diag_info (void) |
2691 { | 3821 { |
2692 static tree t, loc, hwi; | 3822 /* For the GCC-diagnostics custom format specifiers to work, one |
2693 | 3823 must have declared 'tree' and 'location_t' prior to using those |
2694 if (!loc || !t || !hwi) | 3824 attributes. If we haven't seen these declarations then |
2695 { | 3825 the specifiers requiring these types shouldn't be used. |
2696 static format_char_info *diag_fci, *tdiag_fci, *cdiag_fci, *cxxdiag_fci; | 3826 However we don't force a hard ICE because we may see only one |
3827 or the other type. */ | |
3828 if (tree loc = maybe_get_identifier ("location_t")) | |
3829 { | |
3830 loc = identifier_global_value (loc); | |
3831 if (loc && TREE_CODE (loc) != TYPE_DECL) | |
3832 error ("%<location_t%> is not defined as a type"); | |
3833 } | |
3834 | |
3835 /* Initialize the global tree node type local to this file. */ | |
3836 if (!local_tree_type_node | |
3837 || local_tree_type_node == void_type_node) | |
3838 { | |
3839 /* We need to grab the underlying 'union tree_node' so peek into | |
3840 an extra type level. */ | |
3841 if ((local_tree_type_node = maybe_get_identifier ("tree"))) | |
3842 { | |
3843 local_tree_type_node = identifier_global_value (local_tree_type_node); | |
3844 if (local_tree_type_node) | |
3845 { | |
3846 if (TREE_CODE (local_tree_type_node) != TYPE_DECL) | |
3847 { | |
3848 error ("%<tree%> is not defined as a type"); | |
3849 local_tree_type_node = 0; | |
3850 } | |
3851 else if (TREE_CODE (TREE_TYPE (local_tree_type_node)) | |
3852 != POINTER_TYPE) | |
3853 { | |
3854 error ("%<tree%> is not defined as a pointer type"); | |
3855 local_tree_type_node = 0; | |
3856 } | |
3857 else | |
3858 local_tree_type_node = | |
3859 TREE_TYPE (TREE_TYPE (local_tree_type_node)); | |
3860 } | |
3861 } | |
3862 else | |
3863 local_tree_type_node = void_type_node; | |
3864 } | |
3865 | |
3866 /* Similar to the above but for gcall*. */ | |
3867 if (!local_gcall_ptr_node | |
3868 || local_gcall_ptr_node == void_type_node) | |
3869 { | |
3870 if ((local_gcall_ptr_node = maybe_get_identifier ("gcall"))) | |
3871 { | |
3872 local_gcall_ptr_node | |
3873 = identifier_global_value (local_gcall_ptr_node); | |
3874 if (local_gcall_ptr_node) | |
3875 { | |
3876 if (TREE_CODE (local_gcall_ptr_node) != TYPE_DECL) | |
3877 { | |
3878 error ("%<gcall%> is not defined as a type"); | |
3879 local_gcall_ptr_node = 0; | |
3880 } | |
3881 else | |
3882 local_gcall_ptr_node = TREE_TYPE (local_gcall_ptr_node); | |
3883 } | |
3884 } | |
3885 else | |
3886 local_gcall_ptr_node = void_type_node; | |
3887 } | |
3888 | |
3889 static tree hwi; | |
3890 | |
3891 if (!hwi) | |
3892 { | |
2697 static format_length_info *diag_ls; | 3893 static format_length_info *diag_ls; |
2698 unsigned int i; | 3894 unsigned int i; |
2699 | 3895 |
2700 /* For the GCC-diagnostics custom format specifiers to work, one | 3896 /* Find the underlying type for HOST_WIDE_INT. For the 'w' |
2701 must have declared 'tree' and/or 'location_t' prior to using | |
2702 those attributes. If we haven't seen these declarations then | |
2703 you shouldn't use the specifiers requiring these types. | |
2704 However we don't force a hard ICE because we may see only one | |
2705 or the other type. */ | |
2706 if ((loc = maybe_get_identifier ("location_t"))) | |
2707 { | |
2708 loc = identifier_global_value (loc); | |
2709 if (loc) | |
2710 { | |
2711 if (TREE_CODE (loc) != TYPE_DECL) | |
2712 { | |
2713 error ("%<location_t%> is not defined as a type"); | |
2714 loc = 0; | |
2715 } | |
2716 else | |
2717 loc = TREE_TYPE (loc); | |
2718 } | |
2719 } | |
2720 | |
2721 /* We need to grab the underlying 'union tree_node' so peek into | |
2722 an extra type level. */ | |
2723 if ((t = maybe_get_identifier ("tree"))) | |
2724 { | |
2725 t = identifier_global_value (t); | |
2726 if (t) | |
2727 { | |
2728 if (TREE_CODE (t) != TYPE_DECL) | |
2729 { | |
2730 error ("%<tree%> is not defined as a type"); | |
2731 t = 0; | |
2732 } | |
2733 else if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE) | |
2734 { | |
2735 error ("%<tree%> is not defined as a pointer type"); | |
2736 t = 0; | |
2737 } | |
2738 else | |
2739 t = TREE_TYPE (TREE_TYPE (t)); | |
2740 } | |
2741 } | |
2742 | |
2743 /* Find the underlying type for HOST_WIDE_INT. For the %w | |
2744 length modifier to work, one must have issued: "typedef | 3897 length modifier to work, one must have issued: "typedef |
2745 HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code | 3898 HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code |
2746 prior to using that modifier. */ | 3899 prior to using that modifier. */ |
2747 if ((hwi = maybe_get_identifier ("__gcc_host_wide_int__"))) | 3900 if ((hwi = maybe_get_identifier ("__gcc_host_wide_int__"))) |
2748 { | 3901 { |
2790 else if (hwi == long_long_integer_type_node) | 3943 else if (hwi == long_long_integer_type_node) |
2791 diag_ls[i].index = FMT_LEN_ll; | 3944 diag_ls[i].index = FMT_LEN_ll; |
2792 else | 3945 else |
2793 gcc_unreachable (); | 3946 gcc_unreachable (); |
2794 } | 3947 } |
2795 | 3948 } |
2796 /* Handle the __gcc_diag__ format specifics. */ | 3949 |
2797 if (!diag_fci) | 3950 /* It's safe to "re-initialize these to the same values. */ |
2798 dynamic_format_types[gcc_diag_format_type].conversion_specs = | 3951 dynamic_format_types[gcc_diag_format_type].conversion_specs = |
2799 diag_fci = (format_char_info *) | 3952 gcc_diag_char_table; |
2800 xmemdup (gcc_diag_char_table, | 3953 dynamic_format_types[gcc_tdiag_format_type].conversion_specs = |
2801 sizeof (gcc_diag_char_table), | 3954 gcc_tdiag_char_table; |
2802 sizeof (gcc_diag_char_table)); | 3955 dynamic_format_types[gcc_cdiag_format_type].conversion_specs = |
2803 if (t) | 3956 gcc_cdiag_char_table; |
2804 { | 3957 dynamic_format_types[gcc_cxxdiag_format_type].conversion_specs = |
2805 i = find_char_info_specifier_index (diag_fci, 'K'); | 3958 gcc_cxxdiag_char_table; |
2806 diag_fci[i].types[0].type = &t; | |
2807 diag_fci[i].pointer_count = 1; | |
2808 } | |
2809 | |
2810 /* Handle the __gcc_tdiag__ format specifics. */ | |
2811 if (!tdiag_fci) | |
2812 dynamic_format_types[gcc_tdiag_format_type].conversion_specs = | |
2813 tdiag_fci = (format_char_info *) | |
2814 xmemdup (gcc_tdiag_char_table, | |
2815 sizeof (gcc_tdiag_char_table), | |
2816 sizeof (gcc_tdiag_char_table)); | |
2817 if (t) | |
2818 { | |
2819 /* All specifiers taking a tree share the same struct. */ | |
2820 i = find_char_info_specifier_index (tdiag_fci, 'D'); | |
2821 tdiag_fci[i].types[0].type = &t; | |
2822 tdiag_fci[i].pointer_count = 1; | |
2823 i = find_char_info_specifier_index (tdiag_fci, 'K'); | |
2824 tdiag_fci[i].types[0].type = &t; | |
2825 tdiag_fci[i].pointer_count = 1; | |
2826 } | |
2827 | |
2828 /* Handle the __gcc_cdiag__ format specifics. */ | |
2829 if (!cdiag_fci) | |
2830 dynamic_format_types[gcc_cdiag_format_type].conversion_specs = | |
2831 cdiag_fci = (format_char_info *) | |
2832 xmemdup (gcc_cdiag_char_table, | |
2833 sizeof (gcc_cdiag_char_table), | |
2834 sizeof (gcc_cdiag_char_table)); | |
2835 if (t) | |
2836 { | |
2837 /* All specifiers taking a tree share the same struct. */ | |
2838 i = find_char_info_specifier_index (cdiag_fci, 'D'); | |
2839 cdiag_fci[i].types[0].type = &t; | |
2840 cdiag_fci[i].pointer_count = 1; | |
2841 i = find_char_info_specifier_index (cdiag_fci, 'K'); | |
2842 cdiag_fci[i].types[0].type = &t; | |
2843 cdiag_fci[i].pointer_count = 1; | |
2844 } | |
2845 | |
2846 /* Handle the __gcc_cxxdiag__ format specifics. */ | |
2847 if (!cxxdiag_fci) | |
2848 dynamic_format_types[gcc_cxxdiag_format_type].conversion_specs = | |
2849 cxxdiag_fci = (format_char_info *) | |
2850 xmemdup (gcc_cxxdiag_char_table, | |
2851 sizeof (gcc_cxxdiag_char_table), | |
2852 sizeof (gcc_cxxdiag_char_table)); | |
2853 if (t) | |
2854 { | |
2855 /* All specifiers taking a tree share the same struct. */ | |
2856 i = find_char_info_specifier_index (cxxdiag_fci, 'D'); | |
2857 cxxdiag_fci[i].types[0].type = &t; | |
2858 cxxdiag_fci[i].pointer_count = 1; | |
2859 i = find_char_info_specifier_index (cxxdiag_fci, 'K'); | |
2860 cxxdiag_fci[i].types[0].type = &t; | |
2861 cxxdiag_fci[i].pointer_count = 1; | |
2862 } | |
2863 } | |
2864 } | 3959 } |
2865 | 3960 |
2866 #ifdef TARGET_FORMAT_TYPES | 3961 #ifdef TARGET_FORMAT_TYPES |
2867 extern const format_kind_info TARGET_FORMAT_TYPES[]; | 3962 extern const format_kind_info TARGET_FORMAT_TYPES[]; |
2868 #endif | 3963 #endif |
2931 } | 4026 } |
2932 | 4027 |
2933 return attr_name; | 4028 return attr_name; |
2934 } | 4029 } |
2935 | 4030 |
2936 /* Return true if TATTR_NAME and ATTR_NAME are the same format attribute, | |
2937 counting "name" and "__name__" as the same, false otherwise. */ | |
2938 static bool | |
2939 cmp_attribs (const char *tattr_name, const char *attr_name) | |
2940 { | |
2941 int alen = strlen (attr_name); | |
2942 int slen = (tattr_name ? strlen (tattr_name) : 0); | |
2943 if (alen > 4 && attr_name[0] == '_' && attr_name[1] == '_' | |
2944 && attr_name[alen - 1] == '_' && attr_name[alen - 2] == '_') | |
2945 { | |
2946 attr_name += 2; | |
2947 alen -= 4; | |
2948 } | |
2949 if (alen != slen || strncmp (tattr_name, attr_name, alen) != 0) | |
2950 return false; | |
2951 return true; | |
2952 } | |
2953 | |
2954 /* Handle a "format" attribute; arguments as in | 4031 /* Handle a "format" attribute; arguments as in |
2955 struct attribute_spec.handler. */ | 4032 struct attribute_spec.handler. */ |
2956 tree | 4033 tree |
2957 handle_format_attribute (tree *node, tree ARG_UNUSED (name), tree args, | 4034 handle_format_attribute (tree *node, tree ARG_UNUSED (name), tree args, |
2958 int flags, bool *no_add_attrs) | 4035 int flags, bool *no_add_attrs) |
2959 { | 4036 { |
2960 tree type = *node; | 4037 tree type = *node; |
2961 function_format_info info; | 4038 function_format_info info; |
2962 tree argument; | |
2963 | 4039 |
2964 #ifdef TARGET_FORMAT_TYPES | 4040 #ifdef TARGET_FORMAT_TYPES |
2965 /* If the target provides additional format types, we need to | 4041 /* If the target provides additional format types, we need to |
2966 add them to FORMAT_TYPES at first use. */ | 4042 add them to FORMAT_TYPES at first use. */ |
2967 if (TARGET_FORMAT_TYPES != NULL && !dynamic_format_types) | 4043 if (TARGET_FORMAT_TYPES != NULL && !dynamic_format_types) |
2978 first_target_format_type = n_format_types; | 4054 first_target_format_type = n_format_types; |
2979 n_format_types += TARGET_N_FORMAT_TYPES; | 4055 n_format_types += TARGET_N_FORMAT_TYPES; |
2980 } | 4056 } |
2981 #endif | 4057 #endif |
2982 | 4058 |
4059 /* Canonicalize name of format function. */ | |
4060 if (TREE_CODE (TREE_VALUE (args)) == IDENTIFIER_NODE) | |
4061 TREE_VALUE (args) = canonicalize_attr_name (TREE_VALUE (args)); | |
4062 | |
2983 if (!decode_format_attr (args, &info, 0)) | 4063 if (!decode_format_attr (args, &info, 0)) |
2984 { | 4064 { |
2985 *no_add_attrs = true; | 4065 *no_add_attrs = true; |
2986 return NULL_TREE; | 4066 return NULL_TREE; |
2987 } | 4067 } |
2988 | 4068 |
2989 argument = TYPE_ARG_TYPES (type); | 4069 if (prototype_p (type)) |
2990 if (argument) | 4070 { |
2991 { | 4071 if (!check_format_string (type, info.format_num, flags, |
2992 if (!check_format_string (argument, info.format_num, flags, | |
2993 no_add_attrs, info.format_type)) | 4072 no_add_attrs, info.format_type)) |
2994 return NULL_TREE; | 4073 return NULL_TREE; |
2995 | 4074 |
2996 if (info.first_arg_num != 0) | 4075 if (info.first_arg_num != 0) |
2997 { | 4076 { |
2998 unsigned HOST_WIDE_INT arg_num = 1; | 4077 unsigned HOST_WIDE_INT arg_num = 1; |
4078 function_args_iterator iter; | |
4079 tree arg_type; | |
2999 | 4080 |
3000 /* Verify that first_arg_num points to the last arg, | 4081 /* Verify that first_arg_num points to the last arg, |
3001 the ... */ | 4082 the ... */ |
3002 while (argument) | 4083 FOREACH_FUNCTION_ARGS (type, arg_type, iter) |
3003 arg_num++, argument = TREE_CHAIN (argument); | 4084 arg_num++; |
3004 | 4085 |
3005 if (arg_num != info.first_arg_num) | 4086 if (arg_num != info.first_arg_num) |
3006 { | 4087 { |
3007 if (!(flags & (int) ATTR_FLAG_BUILT_IN)) | 4088 if (!(flags & (int) ATTR_FLAG_BUILT_IN)) |
3008 error ("args to be formatted is not %<...%>"); | 4089 error ("args to be formatted is not %<...%>"); |
3057 gcc_unreachable (); | 4138 gcc_unreachable (); |
3058 } | 4139 } |
3059 | 4140 |
3060 return NULL_TREE; | 4141 return NULL_TREE; |
3061 } | 4142 } |
4143 | |
4144 #if CHECKING_P | |
4145 | |
4146 namespace selftest { | |
4147 | |
4148 /* Selftests of location handling. */ | |
4149 | |
4150 /* Get the format_kind_info with the given name. */ | |
4151 | |
4152 static const format_kind_info * | |
4153 get_info (const char *name) | |
4154 { | |
4155 int idx = decode_format_type (name); | |
4156 const format_kind_info *fki = &format_types[idx]; | |
4157 ASSERT_STREQ (fki->name, name); | |
4158 return fki; | |
4159 } | |
4160 | |
4161 /* Verify that get_format_for_type (FKI, TYPE, CONVERSION_CHAR) | |
4162 is EXPECTED_FORMAT. */ | |
4163 | |
4164 static void | |
4165 assert_format_for_type_streq (const location &loc, const format_kind_info *fki, | |
4166 const char *expected_format, tree type, | |
4167 char conversion_char) | |
4168 { | |
4169 gcc_assert (fki); | |
4170 gcc_assert (expected_format); | |
4171 gcc_assert (type); | |
4172 | |
4173 char *actual_format = get_format_for_type (fki, type, conversion_char); | |
4174 ASSERT_STREQ_AT (loc, expected_format, actual_format); | |
4175 free (actual_format); | |
4176 } | |
4177 | |
4178 /* Selftests for get_format_for_type. */ | |
4179 | |
4180 #define ASSERT_FORMAT_FOR_TYPE_STREQ(EXPECTED_FORMAT, TYPE, CONVERSION_CHAR) \ | |
4181 assert_format_for_type_streq (SELFTEST_LOCATION, (fki), (EXPECTED_FORMAT), \ | |
4182 (TYPE), (CONVERSION_CHAR)) | |
4183 | |
4184 /* Selftest for get_format_for_type for "printf"-style functions. */ | |
4185 | |
4186 static void | |
4187 test_get_format_for_type_printf () | |
4188 { | |
4189 const format_kind_info *fki = get_info ("gnu_printf"); | |
4190 ASSERT_NE (fki, NULL); | |
4191 | |
4192 ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node, 'i'); | |
4193 ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node, 'i'); | |
4194 ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node, 'o'); | |
4195 ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node, 'o'); | |
4196 ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node, 'x'); | |
4197 ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node, 'x'); | |
4198 ASSERT_FORMAT_FOR_TYPE_STREQ ("f", double_type_node, 'X'); | |
4199 ASSERT_FORMAT_FOR_TYPE_STREQ ("Lf", long_double_type_node, 'X'); | |
4200 ASSERT_FORMAT_FOR_TYPE_STREQ ("d", integer_type_node, 'd'); | |
4201 ASSERT_FORMAT_FOR_TYPE_STREQ ("i", integer_type_node, 'i'); | |
4202 ASSERT_FORMAT_FOR_TYPE_STREQ ("o", integer_type_node, 'o'); | |
4203 ASSERT_FORMAT_FOR_TYPE_STREQ ("x", integer_type_node, 'x'); | |
4204 ASSERT_FORMAT_FOR_TYPE_STREQ ("X", integer_type_node, 'X'); | |
4205 ASSERT_FORMAT_FOR_TYPE_STREQ ("d", unsigned_type_node, 'd'); | |
4206 ASSERT_FORMAT_FOR_TYPE_STREQ ("i", unsigned_type_node, 'i'); | |
4207 ASSERT_FORMAT_FOR_TYPE_STREQ ("o", unsigned_type_node, 'o'); | |
4208 ASSERT_FORMAT_FOR_TYPE_STREQ ("x", unsigned_type_node, 'x'); | |
4209 ASSERT_FORMAT_FOR_TYPE_STREQ ("X", unsigned_type_node, 'X'); | |
4210 ASSERT_FORMAT_FOR_TYPE_STREQ ("ld", long_integer_type_node, 'd'); | |
4211 ASSERT_FORMAT_FOR_TYPE_STREQ ("li", long_integer_type_node, 'i'); | |
4212 ASSERT_FORMAT_FOR_TYPE_STREQ ("lx", long_integer_type_node, 'x'); | |
4213 ASSERT_FORMAT_FOR_TYPE_STREQ ("lo", long_unsigned_type_node, 'o'); | |
4214 ASSERT_FORMAT_FOR_TYPE_STREQ ("lx", long_unsigned_type_node, 'x'); | |
4215 ASSERT_FORMAT_FOR_TYPE_STREQ ("lld", long_long_integer_type_node, 'd'); | |
4216 ASSERT_FORMAT_FOR_TYPE_STREQ ("lli", long_long_integer_type_node, 'i'); | |
4217 ASSERT_FORMAT_FOR_TYPE_STREQ ("llo", long_long_unsigned_type_node, 'o'); | |
4218 ASSERT_FORMAT_FOR_TYPE_STREQ ("llx", long_long_unsigned_type_node, 'x'); | |
4219 ASSERT_FORMAT_FOR_TYPE_STREQ ("s", build_pointer_type (char_type_node), 'i'); | |
4220 } | |
4221 | |
4222 /* Selftest for get_format_for_type for "scanf"-style functions. */ | |
4223 | |
4224 static void | |
4225 test_get_format_for_type_scanf () | |
4226 { | |
4227 const format_kind_info *fki = get_info ("gnu_scanf"); | |
4228 ASSERT_NE (fki, NULL); | |
4229 ASSERT_FORMAT_FOR_TYPE_STREQ ("d", build_pointer_type (integer_type_node), 'd'); | |
4230 ASSERT_FORMAT_FOR_TYPE_STREQ ("u", build_pointer_type (unsigned_type_node), 'u'); | |
4231 ASSERT_FORMAT_FOR_TYPE_STREQ ("ld", | |
4232 build_pointer_type (long_integer_type_node), 'd'); | |
4233 ASSERT_FORMAT_FOR_TYPE_STREQ ("lu", | |
4234 build_pointer_type (long_unsigned_type_node), 'u'); | |
4235 ASSERT_FORMAT_FOR_TYPE_STREQ | |
4236 ("lld", build_pointer_type (long_long_integer_type_node), 'd'); | |
4237 ASSERT_FORMAT_FOR_TYPE_STREQ | |
4238 ("llu", build_pointer_type (long_long_unsigned_type_node), 'u'); | |
4239 ASSERT_FORMAT_FOR_TYPE_STREQ ("e", build_pointer_type (float_type_node), 'e'); | |
4240 ASSERT_FORMAT_FOR_TYPE_STREQ ("le", build_pointer_type (double_type_node), 'e'); | |
4241 } | |
4242 | |
4243 #undef ASSERT_FORMAT_FOR_TYPE_STREQ | |
4244 | |
4245 /* Run all of the selftests within this file. */ | |
4246 | |
4247 void | |
4248 c_format_c_tests () | |
4249 { | |
4250 test_get_modifier_for_format_len (); | |
4251 test_get_format_for_type_printf (); | |
4252 test_get_format_for_type_scanf (); | |
4253 } | |
4254 | |
4255 } // namespace selftest | |
4256 | |
4257 #endif /* CHECKING_P */ | |
4258 | |
4259 #include "gt-c-family-c-format.h" |