Mercurial > hg > CbC > CbC_gcc
comparison gcc/gimple-ssa-sprintf.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
1 /* Copyright (C) 2016-2017 Free Software Foundation, Inc. | 1 /* Copyright (C) 2016-2018 Free Software Foundation, Inc. |
2 Contributed by Martin Sebor <msebor@redhat.com>. | 2 Contributed by Martin Sebor <msebor@redhat.com>. |
3 | 3 |
4 This file is part of GCC. | 4 This file is part of GCC. |
5 | 5 |
6 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 |
77 #include "cpplib.h" | 77 #include "cpplib.h" |
78 #include "input.h" | 78 #include "input.h" |
79 #include "toplev.h" | 79 #include "toplev.h" |
80 #include "substring-locations.h" | 80 #include "substring-locations.h" |
81 #include "diagnostic.h" | 81 #include "diagnostic.h" |
82 #include "domwalk.h" | |
83 #include "alloc-pool.h" | |
84 #include "vr-values.h" | |
85 #include "gimple-ssa-evrp-analyze.h" | |
82 | 86 |
83 /* The likely worst case value of MB_LEN_MAX for the target, large enough | 87 /* The likely worst case value of MB_LEN_MAX for the target, large enough |
84 for UTF-8. Ideally, this would be obtained by a target hook if it were | 88 for UTF-8. Ideally, this would be obtained by a target hook if it were |
85 to be used for optimization but it's good enough as is for warnings. */ | 89 to be used for optimization but it's good enough as is for warnings. */ |
86 #define target_mb_len_max() 6 | 90 #define target_mb_len_max() 6 |
111 | 115 |
112 static int warn_level; | 116 static int warn_level; |
113 | 117 |
114 struct format_result; | 118 struct format_result; |
115 | 119 |
120 class sprintf_dom_walker : public dom_walker | |
121 { | |
122 public: | |
123 sprintf_dom_walker () : dom_walker (CDI_DOMINATORS) {} | |
124 ~sprintf_dom_walker () {} | |
125 | |
126 edge before_dom_children (basic_block) FINAL OVERRIDE; | |
127 void after_dom_children (basic_block) FINAL OVERRIDE; | |
128 bool handle_gimple_call (gimple_stmt_iterator *); | |
129 | |
130 struct call_info; | |
131 bool compute_format_length (call_info &, format_result *); | |
132 class evrp_range_analyzer evrp_range_analyzer; | |
133 }; | |
134 | |
116 class pass_sprintf_length : public gimple_opt_pass | 135 class pass_sprintf_length : public gimple_opt_pass |
117 { | 136 { |
118 bool fold_return_value; | 137 bool fold_return_value; |
119 | 138 |
120 public: | 139 public: |
133 { | 152 { |
134 gcc_assert (n == 0); | 153 gcc_assert (n == 0); |
135 fold_return_value = param; | 154 fold_return_value = param; |
136 } | 155 } |
137 | 156 |
138 bool handle_gimple_call (gimple_stmt_iterator *); | |
139 | |
140 struct call_info; | |
141 bool compute_format_length (call_info &, format_result *); | |
142 }; | 157 }; |
143 | 158 |
144 bool | 159 bool |
145 pass_sprintf_length::gate (function *) | 160 pass_sprintf_length::gate (function *) |
146 { | 161 { |
194 in cases where strings of unknown lengths are bounded by the arrays | 209 in cases where strings of unknown lengths are bounded by the arrays |
195 they are determined to refer to. KNOWNRANGE must not be used for | 210 they are determined to refer to. KNOWNRANGE must not be used for |
196 the return value optimization. */ | 211 the return value optimization. */ |
197 bool knownrange; | 212 bool knownrange; |
198 | 213 |
199 /* True if no individual directive resulted in more than 4095 bytes | 214 /* True if no individual directive could fail or result in more than |
200 of output (the total NUMBER_CHARS_{MIN,MAX} might be greater). | 215 4095 bytes of output (the total NUMBER_CHARS_{MIN,MAX} might be |
201 Implementations are not required to handle directives that produce | 216 greater). Implementations are not required to handle directives |
202 more than 4K bytes (leading to undefined behavior) and so when one | 217 that produce more than 4K bytes (leading to undefined behavior) |
203 is found it disables the return value optimization. */ | 218 and so when one is found it disables the return value optimization. |
204 bool under4k; | 219 Similarly, directives that can fail (such as wide character |
220 directives) disable the optimization. */ | |
221 bool posunder4k; | |
205 | 222 |
206 /* True when a floating point directive has been seen in the format | 223 /* True when a floating point directive has been seen in the format |
207 string. */ | 224 string. */ |
208 bool floating; | 225 bool floating; |
209 | 226 |
424 } | 441 } |
425 | 442 |
426 return val; | 443 return val; |
427 } | 444 } |
428 | 445 |
429 /* Return the constant initial value of DECL if available or DECL | |
430 otherwise. Same as the synonymous function in c/c-typeck.c. */ | |
431 | |
432 static tree | |
433 decl_constant_value (tree decl) | |
434 { | |
435 if (/* Don't change a variable array bound or initial value to a constant | |
436 in a place where a variable is invalid. Note that DECL_INITIAL | |
437 isn't valid for a PARM_DECL. */ | |
438 current_function_decl != 0 | |
439 && TREE_CODE (decl) != PARM_DECL | |
440 && !TREE_THIS_VOLATILE (decl) | |
441 && TREE_READONLY (decl) | |
442 && DECL_INITIAL (decl) != 0 | |
443 && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK | |
444 /* This is invalid if initial value is not constant. | |
445 If it has either a function call, a memory reference, | |
446 or a variable, then re-evaluating it could give different results. */ | |
447 && TREE_CONSTANT (DECL_INITIAL (decl)) | |
448 /* Check for cases where this is sub-optimal, even though valid. */ | |
449 && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR) | |
450 return DECL_INITIAL (decl); | |
451 return decl; | |
452 } | |
453 | |
454 /* Given FORMAT, set *PLOC to the source location of the format string | 446 /* Given FORMAT, set *PLOC to the source location of the format string |
455 and return the format string if it is known or null otherwise. */ | 447 and return the format string if it is known or null otherwise. */ |
456 | 448 |
457 static const char* | 449 static const char* |
458 get_format_string (tree format, location_t *ploc) | 450 get_format_string (tree format, location_t *ploc) |
459 { | 451 { |
460 if (VAR_P (format)) | |
461 { | |
462 /* Pull out a constant value if the front end didn't. */ | |
463 format = decl_constant_value (format); | |
464 STRIP_NOPS (format); | |
465 } | |
466 | |
467 if (integer_zerop (format)) | |
468 { | |
469 /* FIXME: Diagnose null format string if it hasn't been diagnosed | |
470 by -Wformat (the latter diagnoses only nul pointer constants, | |
471 this pass can do better). */ | |
472 return NULL; | |
473 } | |
474 | |
475 HOST_WIDE_INT offset = 0; | |
476 | |
477 if (TREE_CODE (format) == POINTER_PLUS_EXPR) | |
478 { | |
479 tree arg0 = TREE_OPERAND (format, 0); | |
480 tree arg1 = TREE_OPERAND (format, 1); | |
481 STRIP_NOPS (arg0); | |
482 STRIP_NOPS (arg1); | |
483 | |
484 if (TREE_CODE (arg1) != INTEGER_CST) | |
485 return NULL; | |
486 | |
487 format = arg0; | |
488 | |
489 /* POINTER_PLUS_EXPR offsets are to be interpreted signed. */ | |
490 if (!cst_and_fits_in_hwi (arg1)) | |
491 return NULL; | |
492 | |
493 offset = int_cst_value (arg1); | |
494 } | |
495 | |
496 if (TREE_CODE (format) != ADDR_EXPR) | |
497 return NULL; | |
498 | |
499 *ploc = EXPR_LOC_OR_LOC (format, input_location); | 452 *ploc = EXPR_LOC_OR_LOC (format, input_location); |
500 | 453 |
501 format = TREE_OPERAND (format, 0); | 454 return c_getstr (format); |
502 | 455 } |
503 if (TREE_CODE (format) == ARRAY_REF | 456 |
504 && tree_fits_shwi_p (TREE_OPERAND (format, 1)) | 457 /* For convenience and brevity, shorter named entrypoints of |
505 && (offset += tree_to_shwi (TREE_OPERAND (format, 1))) >= 0) | 458 format_string_diagnostic_t::emit_warning_va and |
506 format = TREE_OPERAND (format, 0); | 459 format_string_diagnostic_t::emit_warning_n_va. |
507 | 460 These have to be functions with the attribute so that exgettext |
508 if (offset < 0) | 461 works properly. */ |
509 return NULL; | |
510 | |
511 tree array_init; | |
512 tree array_size = NULL_TREE; | |
513 | |
514 if (VAR_P (format) | |
515 && TREE_CODE (TREE_TYPE (format)) == ARRAY_TYPE | |
516 && (array_init = decl_constant_value (format)) != format | |
517 && TREE_CODE (array_init) == STRING_CST) | |
518 { | |
519 /* Extract the string constant initializer. Note that this may | |
520 include a trailing NUL character that is not in the array (e.g. | |
521 const char a[3] = "foo";). */ | |
522 array_size = DECL_SIZE_UNIT (format); | |
523 format = array_init; | |
524 } | |
525 | |
526 if (TREE_CODE (format) != STRING_CST) | |
527 return NULL; | |
528 | |
529 tree type = TREE_TYPE (format); | |
530 | |
531 scalar_int_mode char_mode; | |
532 if (!is_int_mode (TYPE_MODE (TREE_TYPE (type)), &char_mode) | |
533 || GET_MODE_SIZE (char_mode) != 1) | |
534 { | |
535 /* Wide format string. */ | |
536 return NULL; | |
537 } | |
538 | |
539 const char *fmtstr = TREE_STRING_POINTER (format); | |
540 unsigned fmtlen = TREE_STRING_LENGTH (format); | |
541 | |
542 if (array_size) | |
543 { | |
544 /* Variable length arrays can't be initialized. */ | |
545 gcc_assert (TREE_CODE (array_size) == INTEGER_CST); | |
546 | |
547 if (tree_fits_shwi_p (array_size)) | |
548 { | |
549 HOST_WIDE_INT array_size_value = tree_to_shwi (array_size); | |
550 if (array_size_value > 0 | |
551 && array_size_value == (int) array_size_value | |
552 && fmtlen > array_size_value) | |
553 fmtlen = array_size_value; | |
554 } | |
555 } | |
556 if (offset) | |
557 { | |
558 if (offset >= fmtlen) | |
559 return NULL; | |
560 | |
561 fmtstr += offset; | |
562 fmtlen -= offset; | |
563 } | |
564 | |
565 if (fmtlen < 1 || fmtstr[--fmtlen] != 0) | |
566 { | |
567 /* FIXME: Diagnose an unterminated format string if it hasn't been | |
568 diagnosed by -Wformat. Similarly to a null format pointer, | |
569 -Wformay diagnoses only nul pointer constants, this pass can | |
570 do better). */ | |
571 return NULL; | |
572 } | |
573 | |
574 return fmtstr; | |
575 } | |
576 | |
577 /* The format_warning_at_substring function is not used here in a way | |
578 that makes using attribute format viable. Suppress the warning. */ | |
579 | |
580 #pragma GCC diagnostic push | |
581 #pragma GCC diagnostic ignored "-Wsuggest-attribute=format" | |
582 | |
583 /* For convenience and brevity. */ | |
584 | 462 |
585 static bool | 463 static bool |
586 (* const fmtwarn) (const substring_loc &, location_t, | 464 ATTRIBUTE_GCC_DIAG (5, 6) |
587 const char *, int, const char *, ...) | 465 fmtwarn (const substring_loc &fmt_loc, location_t param_loc, |
588 = format_warning_at_substring; | 466 const char *corrected_substring, int opt, const char *gmsgid, ...) |
467 { | |
468 format_string_diagnostic_t diag (fmt_loc, NULL, param_loc, NULL, | |
469 corrected_substring); | |
470 va_list ap; | |
471 va_start (ap, gmsgid); | |
472 bool warned = diag.emit_warning_va (opt, gmsgid, &ap); | |
473 va_end (ap); | |
474 | |
475 return warned; | |
476 } | |
477 | |
478 static bool | |
479 ATTRIBUTE_GCC_DIAG (6, 8) ATTRIBUTE_GCC_DIAG (7, 8) | |
480 fmtwarn_n (const substring_loc &fmt_loc, location_t param_loc, | |
481 const char *corrected_substring, int opt, unsigned HOST_WIDE_INT n, | |
482 const char *singular_gmsgid, const char *plural_gmsgid, ...) | |
483 { | |
484 format_string_diagnostic_t diag (fmt_loc, NULL, param_loc, NULL, | |
485 corrected_substring); | |
486 va_list ap; | |
487 va_start (ap, plural_gmsgid); | |
488 bool warned = diag.emit_warning_n_va (opt, n, singular_gmsgid, plural_gmsgid, | |
489 &ap); | |
490 va_end (ap); | |
491 | |
492 return warned; | |
493 } | |
589 | 494 |
590 /* Format length modifiers. */ | 495 /* Format length modifiers. */ |
591 | 496 |
592 enum format_lengths | 497 enum format_lengths |
593 { | 498 { |
609 struct fmtresult | 514 struct fmtresult |
610 { | 515 { |
611 /* Construct a FMTRESULT object with all counters initialized | 516 /* Construct a FMTRESULT object with all counters initialized |
612 to MIN. KNOWNRANGE is set when MIN is valid. */ | 517 to MIN. KNOWNRANGE is set when MIN is valid. */ |
613 fmtresult (unsigned HOST_WIDE_INT min = HOST_WIDE_INT_MAX) | 518 fmtresult (unsigned HOST_WIDE_INT min = HOST_WIDE_INT_MAX) |
614 : argmin (), argmax (), | 519 : argmin (), argmax (), nonstr (), |
615 knownrange (min < HOST_WIDE_INT_MAX), | 520 knownrange (min < HOST_WIDE_INT_MAX), |
616 nullp () | 521 mayfail (), nullp () |
617 { | 522 { |
618 range.min = min; | 523 range.min = min; |
619 range.max = min; | 524 range.max = min; |
620 range.likely = min; | 525 range.likely = min; |
621 range.unlikely = min; | 526 range.unlikely = min; |
623 | 528 |
624 /* Construct a FMTRESULT object with MIN, MAX, and LIKELY counters. | 529 /* Construct a FMTRESULT object with MIN, MAX, and LIKELY counters. |
625 KNOWNRANGE is set when both MIN and MAX are valid. */ | 530 KNOWNRANGE is set when both MIN and MAX are valid. */ |
626 fmtresult (unsigned HOST_WIDE_INT min, unsigned HOST_WIDE_INT max, | 531 fmtresult (unsigned HOST_WIDE_INT min, unsigned HOST_WIDE_INT max, |
627 unsigned HOST_WIDE_INT likely = HOST_WIDE_INT_MAX) | 532 unsigned HOST_WIDE_INT likely = HOST_WIDE_INT_MAX) |
628 : argmin (), argmax (), | 533 : argmin (), argmax (), nonstr (), |
629 knownrange (min < HOST_WIDE_INT_MAX && max < HOST_WIDE_INT_MAX), | 534 knownrange (min < HOST_WIDE_INT_MAX && max < HOST_WIDE_INT_MAX), |
630 nullp () | 535 mayfail (), nullp () |
631 { | 536 { |
632 range.min = min; | 537 range.min = min; |
633 range.max = max; | 538 range.max = max; |
634 range.likely = max < likely ? min : likely; | 539 range.likely = max < likely ? min : likely; |
635 range.unlikely = max; | 540 range.unlikely = max; |
650 | 555 |
651 /* The minimum and maximum number of bytes that a directive | 556 /* The minimum and maximum number of bytes that a directive |
652 results in on output for an argument in the range above. */ | 557 results in on output for an argument in the range above. */ |
653 result_range range; | 558 result_range range; |
654 | 559 |
560 /* Non-nul when the argument of a string directive is not a nul | |
561 terminated string. */ | |
562 tree nonstr; | |
563 | |
655 /* True when the range above is obtained from a known value of | 564 /* True when the range above is obtained from a known value of |
656 a directive's argument or its bounds and not the result of | 565 a directive's argument or its bounds and not the result of |
657 heuristics that depend on warning levels. */ | 566 heuristics that depend on warning levels. */ |
658 bool knownrange; | 567 bool knownrange; |
568 | |
569 /* True for a directive that may fail (such as wide character | |
570 directives). */ | |
571 bool mayfail; | |
659 | 572 |
660 /* True when the argument is a null pointer. */ | 573 /* True when the argument is a null pointer. */ |
661 bool nullp; | 574 bool nullp; |
662 }; | 575 }; |
663 | 576 |
742 | 655 |
743 unsigned | 656 unsigned |
744 fmtresult::type_max_digits (tree type, int base) | 657 fmtresult::type_max_digits (tree type, int base) |
745 { | 658 { |
746 unsigned prec = TYPE_PRECISION (type); | 659 unsigned prec = TYPE_PRECISION (type); |
747 if (base == 8) | 660 switch (base) |
748 return (prec + 2) / 3; | 661 { |
749 | 662 case 8: |
750 if (base == 16) | 663 return (prec + 2) / 3; |
751 return prec / 4; | 664 case 10: |
752 | 665 /* Decimal approximation: yields 3, 5, 10, and 20 for precision |
753 /* Decimal approximation: yields 3, 5, 10, and 20 for precision | 666 of 8, 16, 32, and 64 bits. */ |
754 of 8, 16, 32, and 64 bits. */ | 667 return prec * 301 / 1000 + 1; |
755 return prec * 301 / 1000 + 1; | 668 case 16: |
669 return prec / 4; | |
670 } | |
671 | |
672 gcc_unreachable (); | |
756 } | 673 } |
757 | 674 |
758 static bool | 675 static bool |
759 get_int_range (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, bool, HOST_WIDE_INT); | 676 get_int_range (tree, HOST_WIDE_INT *, HOST_WIDE_INT *, bool, HOST_WIDE_INT, |
677 class vr_values *vr_values); | |
760 | 678 |
761 /* Description of a format directive. A directive is either a plain | 679 /* Description of a format directive. A directive is either a plain |
762 string or a conversion specification that starts with '%'. */ | 680 string or a conversion specification that starts with '%'. */ |
763 | 681 |
764 struct directive | 682 struct directive |
789 take one or when none is available (such as for vararg functions). */ | 707 take one or when none is available (such as for vararg functions). */ |
790 tree arg; | 708 tree arg; |
791 | 709 |
792 /* Format conversion function that given a directive and an argument | 710 /* Format conversion function that given a directive and an argument |
793 returns the formatting result. */ | 711 returns the formatting result. */ |
794 fmtresult (*fmtfunc) (const directive &, tree); | 712 fmtresult (*fmtfunc) (const directive &, tree, vr_values *); |
795 | 713 |
796 /* Return True when a the format flag CHR has been used. */ | 714 /* Return True when a the format flag CHR has been used. */ |
797 bool get_flag (char chr) const | 715 bool get_flag (char chr) const |
798 { | 716 { |
799 unsigned char c = chr & 0xff; | 717 unsigned char c = chr & 0xff; |
826 /* Set the width range according to ARG, with both bounds being | 744 /* Set the width range according to ARG, with both bounds being |
827 no less than 0. For a constant ARG set both bounds to its value | 745 no less than 0. For a constant ARG set both bounds to its value |
828 or 0, whichever is greater. For a non-constant ARG in some range | 746 or 0, whichever is greater. For a non-constant ARG in some range |
829 set width to its range adjusting each bound to -1 if it's less. | 747 set width to its range adjusting each bound to -1 if it's less. |
830 For an indeterminate ARG set width to [0, INT_MAX]. */ | 748 For an indeterminate ARG set width to [0, INT_MAX]. */ |
831 void set_width (tree arg) | 749 void set_width (tree arg, vr_values *vr_values) |
832 { | 750 { |
833 get_int_range (arg, width, width + 1, true, 0); | 751 get_int_range (arg, width, width + 1, true, 0, vr_values); |
834 } | 752 } |
835 | 753 |
836 /* Set both bounds of the precision range to VAL. */ | 754 /* Set both bounds of the precision range to VAL. */ |
837 void set_precision (HOST_WIDE_INT val) | 755 void set_precision (HOST_WIDE_INT val) |
838 { | 756 { |
842 /* Set the precision range according to ARG, with both bounds being | 760 /* Set the precision range according to ARG, with both bounds being |
843 no less than -1. For a constant ARG set both bounds to its value | 761 no less than -1. For a constant ARG set both bounds to its value |
844 or -1 whichever is greater. For a non-constant ARG in some range | 762 or -1 whichever is greater. For a non-constant ARG in some range |
845 set precision to its range adjusting each bound to -1 if it's less. | 763 set precision to its range adjusting each bound to -1 if it's less. |
846 For an indeterminate ARG set precision to [-1, INT_MAX]. */ | 764 For an indeterminate ARG set precision to [-1, INT_MAX]. */ |
847 void set_precision (tree arg) | 765 void set_precision (tree arg, vr_values *vr_values) |
848 { | 766 { |
849 get_int_range (arg, prec, prec + 1, false, -1); | 767 get_int_range (arg, prec, prec + 1, false, -1, vr_values); |
850 } | 768 } |
851 | 769 |
852 /* Return true if both width and precision are known to be | 770 /* Return true if both width and precision are known to be |
853 either constant or in some range, false otherwise. */ | 771 either constant or in some range, false otherwise. */ |
854 bool known_width_and_precision () const | 772 bool known_width_and_precision () const |
974 return range; | 892 return range; |
975 } | 893 } |
976 | 894 |
977 /* Description of a call to a formatted function. */ | 895 /* Description of a call to a formatted function. */ |
978 | 896 |
979 struct pass_sprintf_length::call_info | 897 struct sprintf_dom_walker::call_info |
980 { | 898 { |
981 /* Function call statement. */ | 899 /* Function call statement. */ |
982 gimple *callstmt; | 900 gimple *callstmt; |
983 | 901 |
984 /* Function called. */ | 902 /* Function called. */ |
1025 }; | 943 }; |
1026 | 944 |
1027 /* Return the result of formatting a no-op directive (such as '%n'). */ | 945 /* Return the result of formatting a no-op directive (such as '%n'). */ |
1028 | 946 |
1029 static fmtresult | 947 static fmtresult |
1030 format_none (const directive &, tree) | 948 format_none (const directive &, tree, vr_values *) |
1031 { | 949 { |
1032 fmtresult res (0); | 950 fmtresult res (0); |
1033 return res; | 951 return res; |
1034 } | 952 } |
1035 | 953 |
1036 /* Return the result of formatting the '%%' directive. */ | 954 /* Return the result of formatting the '%%' directive. */ |
1037 | 955 |
1038 static fmtresult | 956 static fmtresult |
1039 format_percent (const directive &, tree) | 957 format_percent (const directive &, tree, vr_values *) |
1040 { | 958 { |
1041 fmtresult res (1); | 959 fmtresult res (1); |
1042 return res; | 960 return res; |
1043 } | 961 } |
1044 | 962 |
1091 the argument. When ABSOLUTE is false, negative bounds of | 1009 the argument. When ABSOLUTE is false, negative bounds of |
1092 the determined range are replaced with NEGBOUND. */ | 1010 the determined range are replaced with NEGBOUND. */ |
1093 | 1011 |
1094 static bool | 1012 static bool |
1095 get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax, | 1013 get_int_range (tree arg, HOST_WIDE_INT *pmin, HOST_WIDE_INT *pmax, |
1096 bool absolute, HOST_WIDE_INT negbound) | 1014 bool absolute, HOST_WIDE_INT negbound, |
1015 class vr_values *vr_values) | |
1097 { | 1016 { |
1098 /* The type of the result. */ | 1017 /* The type of the result. */ |
1099 const_tree type = integer_type_node; | 1018 const_tree type = integer_type_node; |
1100 | 1019 |
1101 bool knownrange = false; | 1020 bool knownrange = false; |
1130 if (TREE_CODE (arg) == SSA_NAME | 1049 if (TREE_CODE (arg) == SSA_NAME |
1131 && INTEGRAL_TYPE_P (argtype) | 1050 && INTEGRAL_TYPE_P (argtype) |
1132 && TYPE_PRECISION (argtype) <= TYPE_PRECISION (type)) | 1051 && TYPE_PRECISION (argtype) <= TYPE_PRECISION (type)) |
1133 { | 1052 { |
1134 /* Try to determine the range of values of the integer argument. */ | 1053 /* Try to determine the range of values of the integer argument. */ |
1135 wide_int min, max; | 1054 value_range *vr = vr_values->get_value_range (arg); |
1136 enum value_range_type range_type = get_range_info (arg, &min, &max); | 1055 if (range_int_cst_p (vr)) |
1137 if (range_type == VR_RANGE) | |
1138 { | 1056 { |
1139 HOST_WIDE_INT type_min | 1057 HOST_WIDE_INT type_min |
1140 = (TYPE_UNSIGNED (argtype) | 1058 = (TYPE_UNSIGNED (argtype) |
1141 ? tree_to_uhwi (TYPE_MIN_VALUE (argtype)) | 1059 ? tree_to_uhwi (TYPE_MIN_VALUE (argtype)) |
1142 : tree_to_shwi (TYPE_MIN_VALUE (argtype))); | 1060 : tree_to_shwi (TYPE_MIN_VALUE (argtype))); |
1143 | 1061 |
1144 HOST_WIDE_INT type_max = tree_to_uhwi (TYPE_MAX_VALUE (argtype)); | 1062 HOST_WIDE_INT type_max = tree_to_uhwi (TYPE_MAX_VALUE (argtype)); |
1145 | 1063 |
1146 *pmin = min.to_shwi (); | 1064 *pmin = TREE_INT_CST_LOW (vr->min ()); |
1147 *pmax = max.to_shwi (); | 1065 *pmax = TREE_INT_CST_LOW (vr->max ()); |
1148 | 1066 |
1149 if (*pmin < *pmax) | 1067 if (*pmin < *pmax) |
1150 { | 1068 { |
1151 /* Return true if the adjusted range is a subrange of | 1069 /* Return true if the adjusted range is a subrange of |
1152 the full range of the argument's type. *PMAX may | 1070 the full range of the argument's type. *PMAX may |
1162 } | 1080 } |
1163 | 1081 |
1164 /* Handle an argument with an unknown range as if none had been | 1082 /* Handle an argument with an unknown range as if none had been |
1165 provided. */ | 1083 provided. */ |
1166 if (unknown) | 1084 if (unknown) |
1167 return get_int_range (NULL_TREE, pmin, pmax, absolute, negbound); | 1085 return get_int_range (NULL_TREE, pmin, pmax, absolute, |
1086 negbound, vr_values); | |
1168 } | 1087 } |
1169 | 1088 |
1170 /* Adjust each bound as specified by ABSOLUTE and NEGBOUND. */ | 1089 /* Adjust each bound as specified by ABSOLUTE and NEGBOUND. */ |
1171 if (absolute) | 1090 if (absolute) |
1172 { | 1091 { |
1247 that the format directive DIR will output for any argument given | 1166 that the format directive DIR will output for any argument given |
1248 the WIDTH and PRECISION (extracted from DIR). This function is | 1167 the WIDTH and PRECISION (extracted from DIR). This function is |
1249 used when the directive argument or its value isn't known. */ | 1168 used when the directive argument or its value isn't known. */ |
1250 | 1169 |
1251 static fmtresult | 1170 static fmtresult |
1252 format_integer (const directive &dir, tree arg) | 1171 format_integer (const directive &dir, tree arg, vr_values *vr_values) |
1253 { | 1172 { |
1254 tree intmax_type_node; | 1173 tree intmax_type_node; |
1255 tree uintmax_type_node; | 1174 tree uintmax_type_node; |
1256 | 1175 |
1257 /* Base to format the number in. */ | 1176 /* Base to format the number in. */ |
1430 && TREE_CODE (arg) == SSA_NAME | 1349 && TREE_CODE (arg) == SSA_NAME |
1431 && INTEGRAL_TYPE_P (argtype)) | 1350 && INTEGRAL_TYPE_P (argtype)) |
1432 { | 1351 { |
1433 /* Try to determine the range of values of the integer argument | 1352 /* Try to determine the range of values of the integer argument |
1434 (range information is not available for pointers). */ | 1353 (range information is not available for pointers). */ |
1435 wide_int min, max; | 1354 value_range *vr = vr_values->get_value_range (arg); |
1436 enum value_range_type range_type = get_range_info (arg, &min, &max); | 1355 if (range_int_cst_p (vr)) |
1437 if (range_type == VR_RANGE) | 1356 { |
1438 { | 1357 argmin = vr->min (); |
1439 argmin = wide_int_to_tree (argtype, min); | 1358 argmax = vr->max (); |
1440 argmax = wide_int_to_tree (argtype, max); | |
1441 | 1359 |
1442 /* Set KNOWNRANGE if the argument is in a known subrange | 1360 /* Set KNOWNRANGE if the argument is in a known subrange |
1443 of the directive's type and neither width nor precision | 1361 of the directive's type and neither width nor precision |
1444 is unknown. (KNOWNRANGE may be reset below). */ | 1362 is unknown. (KNOWNRANGE may be reset below). */ |
1445 res.knownrange | 1363 res.knownrange |
1448 && dir.known_width_and_precision ()); | 1366 && dir.known_width_and_precision ()); |
1449 | 1367 |
1450 res.argmin = argmin; | 1368 res.argmin = argmin; |
1451 res.argmax = argmax; | 1369 res.argmax = argmax; |
1452 } | 1370 } |
1453 else if (range_type == VR_ANTI_RANGE) | 1371 else if (vr->kind () == VR_ANTI_RANGE) |
1454 { | 1372 { |
1455 /* Handle anti-ranges if/when bug 71690 is resolved. */ | 1373 /* Handle anti-ranges if/when bug 71690 is resolved. */ |
1456 } | 1374 } |
1457 else if (range_type == VR_VARYING) | 1375 else if (vr->varying_p () || vr->undefined_p ()) |
1458 { | 1376 { |
1459 /* The argument here may be the result of promoting the actual | 1377 /* The argument here may be the result of promoting the actual |
1460 argument to int. Try to determine the type of the actual | 1378 argument to int. Try to determine the type of the actual |
1461 argument before promotion and narrow down its range that | 1379 argument before promotion and narrow down its range that |
1462 way. */ | 1380 way. */ |
1465 { | 1383 { |
1466 tree_code code = gimple_assign_rhs_code (def); | 1384 tree_code code = gimple_assign_rhs_code (def); |
1467 if (code == INTEGER_CST) | 1385 if (code == INTEGER_CST) |
1468 { | 1386 { |
1469 arg = gimple_assign_rhs1 (def); | 1387 arg = gimple_assign_rhs1 (def); |
1470 return format_integer (dir, arg); | 1388 return format_integer (dir, arg, vr_values); |
1471 } | 1389 } |
1472 | 1390 |
1473 if (code == NOP_EXPR) | 1391 if (code == NOP_EXPR) |
1474 { | 1392 { |
1475 tree type = TREE_TYPE (gimple_assign_rhs1 (def)); | 1393 tree type = TREE_TYPE (gimple_assign_rhs1 (def)); |
1510 if (TYPE_UNSIGNED (dirtype) || tree_int_cst_sgn (argmin) >= 0) | 1428 if (TYPE_UNSIGNED (dirtype) || tree_int_cst_sgn (argmin) >= 0) |
1511 { | 1429 { |
1512 /* For unsigned conversions/directives or signed when | 1430 /* For unsigned conversions/directives or signed when |
1513 the minimum is positive, use the minimum and maximum to compute | 1431 the minimum is positive, use the minimum and maximum to compute |
1514 the shortest and longest output, respectively. */ | 1432 the shortest and longest output, respectively. */ |
1515 res.range.min = format_integer (dir, argmin).range.min; | 1433 res.range.min = format_integer (dir, argmin, vr_values).range.min; |
1516 res.range.max = format_integer (dir, argmax).range.max; | 1434 res.range.max = format_integer (dir, argmax, vr_values).range.max; |
1517 } | 1435 } |
1518 else if (tree_int_cst_sgn (argmax) < 0) | 1436 else if (tree_int_cst_sgn (argmax) < 0) |
1519 { | 1437 { |
1520 /* For signed conversions/directives if maximum is negative, | 1438 /* For signed conversions/directives if maximum is negative, |
1521 use the minimum as the longest output and maximum as the | 1439 use the minimum as the longest output and maximum as the |
1522 shortest output. */ | 1440 shortest output. */ |
1523 res.range.min = format_integer (dir, argmax).range.min; | 1441 res.range.min = format_integer (dir, argmax, vr_values).range.min; |
1524 res.range.max = format_integer (dir, argmin).range.max; | 1442 res.range.max = format_integer (dir, argmin, vr_values).range.max; |
1525 } | 1443 } |
1526 else | 1444 else |
1527 { | 1445 { |
1528 /* Otherwise, 0 is inside of the range and minimum negative. Use 0 | 1446 /* Otherwise, 0 is inside of the range and minimum negative. Use 0 |
1529 as the shortest output and for the longest output compute the | 1447 as the shortest output and for the longest output compute the |
1530 length of the output of both minimum and maximum and pick the | 1448 length of the output of both minimum and maximum and pick the |
1531 longer. */ | 1449 longer. */ |
1532 unsigned HOST_WIDE_INT max1 = format_integer (dir, argmin).range.max; | 1450 unsigned HOST_WIDE_INT max1 |
1533 unsigned HOST_WIDE_INT max2 = format_integer (dir, argmax).range.max; | 1451 = format_integer (dir, argmin, vr_values).range.max; |
1534 res.range.min = format_integer (dir, integer_zero_node).range.min; | 1452 unsigned HOST_WIDE_INT max2 |
1453 = format_integer (dir, argmax, vr_values).range.max; | |
1454 res.range.min | |
1455 = format_integer (dir, integer_zero_node, vr_values).range.min; | |
1535 res.range.max = MAX (max1, max2); | 1456 res.range.max = MAX (max1, max2); |
1536 } | 1457 } |
1537 | 1458 |
1538 /* If the range is known, use the maximum as the likely length. */ | 1459 /* If the range is known, use the maximum as the likely length. */ |
1539 if (res.knownrange) | 1460 if (res.knownrange) |
1711 When plus or space are set the output is preceded by either a sign | 1632 When plus or space are set the output is preceded by either a sign |
1712 or a space. */ | 1633 or a space. */ |
1713 unsigned flagmin = (1 /* for the first digit */ | 1634 unsigned flagmin = (1 /* for the first digit */ |
1714 + (dir.get_flag ('+') | dir.get_flag (' '))); | 1635 + (dir.get_flag ('+') | dir.get_flag (' '))); |
1715 | 1636 |
1637 /* The minimum is 3 for "inf" and "nan" for all specifiers, plus 1 | |
1638 for the plus sign/space with the '+' and ' ' flags, respectively, | |
1639 unless reduced below. */ | |
1640 res.range.min = 2 + flagmin; | |
1641 | |
1716 /* When the pound flag is set the decimal point is included in output | 1642 /* When the pound flag is set the decimal point is included in output |
1717 regardless of precision. Whether or not a decimal point is included | 1643 regardless of precision. Whether or not a decimal point is included |
1718 otherwise depends on the specification and precision. */ | 1644 otherwise depends on the specification and precision. */ |
1719 bool radix = dir.get_flag ('#'); | 1645 bool radix = dir.get_flag ('#'); |
1720 | 1646 |
1727 if (dir.prec[0] <= 0) | 1653 if (dir.prec[0] <= 0) |
1728 minprec = 0; | 1654 minprec = 0; |
1729 else if (dir.prec[0] > 0) | 1655 else if (dir.prec[0] > 0) |
1730 minprec = dir.prec[0] + !radix /* decimal point */; | 1656 minprec = dir.prec[0] + !radix /* decimal point */; |
1731 | 1657 |
1732 res.range.min = (2 /* 0x */ | 1658 res.range.likely = (2 /* 0x */ |
1733 + flagmin | 1659 + flagmin |
1734 + radix | 1660 + radix |
1735 + minprec | 1661 + minprec |
1736 + 3 /* p+0 */); | 1662 + 3 /* p+0 */); |
1737 | 1663 |
1738 res.range.max = format_floating_max (type, 'a', prec[1]); | 1664 res.range.max = format_floating_max (type, 'a', prec[1]); |
1739 res.range.likely = res.range.min; | |
1740 | 1665 |
1741 /* The unlikely maximum accounts for the longest multibyte | 1666 /* The unlikely maximum accounts for the longest multibyte |
1742 decimal point character. */ | 1667 decimal point character. */ |
1743 res.range.unlikely = res.range.max; | 1668 res.range.unlikely = res.range.max; |
1744 if (dir.prec[1] > 0) | 1669 if (dir.prec[1] > 0) |
1752 { | 1677 { |
1753 /* Minimum output attributable to precision and, when it's | 1678 /* Minimum output attributable to precision and, when it's |
1754 non-zero, decimal point. */ | 1679 non-zero, decimal point. */ |
1755 HOST_WIDE_INT minprec = prec[0] ? prec[0] + !radix : 0; | 1680 HOST_WIDE_INT minprec = prec[0] ? prec[0] + !radix : 0; |
1756 | 1681 |
1757 /* The minimum output is "[-+]1.234567e+00" regardless | 1682 /* The likely minimum output is "[-+]1.234567e+00" regardless |
1758 of the value of the actual argument. */ | 1683 of the value of the actual argument. */ |
1759 res.range.min = (flagmin | 1684 res.range.likely = (flagmin |
1760 + radix | 1685 + radix |
1761 + minprec | 1686 + minprec |
1762 + 2 /* e+ */ + 2); | 1687 + 2 /* e+ */ + 2); |
1763 | 1688 |
1764 res.range.max = format_floating_max (type, 'e', prec[1]); | 1689 res.range.max = format_floating_max (type, 'e', prec[1]); |
1765 res.range.likely = res.range.min; | |
1766 | 1690 |
1767 /* The unlikely maximum accounts for the longest multibyte | 1691 /* The unlikely maximum accounts for the longest multibyte |
1768 decimal point character. */ | 1692 decimal point character. */ |
1769 if (dir.prec[0] != dir.prec[1] | 1693 if (dir.prec[0] != dir.prec[1] |
1770 || dir.prec[0] == -1 || dir.prec[0] > 0) | 1694 || dir.prec[0] == -1 || dir.prec[0] > 0) |
1779 { | 1703 { |
1780 /* Minimum output attributable to precision and, when it's non-zero, | 1704 /* Minimum output attributable to precision and, when it's non-zero, |
1781 decimal point. */ | 1705 decimal point. */ |
1782 HOST_WIDE_INT minprec = prec[0] ? prec[0] + !radix : 0; | 1706 HOST_WIDE_INT minprec = prec[0] ? prec[0] + !radix : 0; |
1783 | 1707 |
1784 /* The lower bound when precision isn't specified is 8 bytes | 1708 /* For finite numbers (i.e., not infinity or NaN) the lower bound |
1785 ("1.23456" since precision is taken to be 6). When precision | 1709 when precision isn't specified is 8 bytes ("1.23456" since |
1786 is zero, the lower bound is 1 byte (e.g., "1"). Otherwise, | 1710 precision is taken to be 6). When precision is zero, the lower |
1787 when precision is greater than zero, then the lower bound | 1711 bound is 1 byte (e.g., "1"). Otherwise, when precision is greater |
1788 is 2 plus precision (plus flags). */ | 1712 than zero, then the lower bound is 2 plus precision (plus flags). |
1789 res.range.min = flagmin + radix + minprec; | 1713 But in all cases, the lower bound is no greater than 3. */ |
1714 unsigned HOST_WIDE_INT min = flagmin + radix + minprec; | |
1715 if (min < res.range.min) | |
1716 res.range.min = min; | |
1790 | 1717 |
1791 /* Compute the upper bound for -TYPE_MAX. */ | 1718 /* Compute the upper bound for -TYPE_MAX. */ |
1792 res.range.max = format_floating_max (type, 'f', prec[1]); | 1719 res.range.max = format_floating_max (type, 'f', prec[1]); |
1793 | 1720 |
1794 /* The minimum output with unknown precision is a single byte | 1721 /* The minimum output with unknown precision is a single byte |
1795 (e.g., "0") but the more likely output is 3 bytes ("0.0"). */ | 1722 (e.g., "0") but the more likely output is 3 bytes ("0.0"). */ |
1796 if (dir.prec[0] < 0 && dir.prec[1] > 0) | 1723 if (dir.prec[0] < 0 && dir.prec[1] > 0) |
1797 res.range.likely = 3; | 1724 res.range.likely = 3; |
1798 else | 1725 else |
1799 res.range.likely = res.range.min; | 1726 res.range.likely = min; |
1800 | 1727 |
1801 /* The unlikely maximum accounts for the longest multibyte | 1728 /* The unlikely maximum accounts for the longest multibyte |
1802 decimal point character. */ | 1729 decimal point character. */ |
1803 if (dir.prec[0] != dir.prec[1] | 1730 if (dir.prec[0] != dir.prec[1] |
1804 || dir.prec[0] == -1 || dir.prec[0] > 0) | 1731 || dir.prec[0] == -1 || dir.prec[0] > 0) |
1812 /* The %g output depends on precision and the exponent of | 1739 /* The %g output depends on precision and the exponent of |
1813 the argument. Since the value of the argument isn't known | 1740 the argument. Since the value of the argument isn't known |
1814 the lower bound on the range of bytes (not counting flags | 1741 the lower bound on the range of bytes (not counting flags |
1815 or width) is 1 plus radix (i.e., either "0" or "0." for | 1742 or width) is 1 plus radix (i.e., either "0" or "0." for |
1816 "%g" and "%#g", respectively, with a zero argument). */ | 1743 "%g" and "%#g", respectively, with a zero argument). */ |
1817 res.range.min = flagmin + radix; | 1744 unsigned HOST_WIDE_INT min = flagmin + radix; |
1745 if (min < res.range.min) | |
1746 res.range.min = min; | |
1818 | 1747 |
1819 char spec = 'g'; | 1748 char spec = 'g'; |
1820 HOST_WIDE_INT maxprec = dir.prec[1]; | 1749 HOST_WIDE_INT maxprec = dir.prec[1]; |
1821 if (radix && maxprec) | 1750 if (radix && maxprec) |
1822 { | 1751 { |
1870 /* Return a range representing the minimum and maximum number of bytes | 1799 /* Return a range representing the minimum and maximum number of bytes |
1871 that the directive DIR will write on output for the floating argument | 1800 that the directive DIR will write on output for the floating argument |
1872 ARG. */ | 1801 ARG. */ |
1873 | 1802 |
1874 static fmtresult | 1803 static fmtresult |
1875 format_floating (const directive &dir, tree arg) | 1804 format_floating (const directive &dir, tree arg, vr_values *) |
1876 { | 1805 { |
1877 HOST_WIDE_INT prec[] = { dir.prec[0], dir.prec[1] }; | 1806 HOST_WIDE_INT prec[] = { dir.prec[0], dir.prec[1] }; |
1807 tree type = (dir.modifier == FMT_LEN_L || dir.modifier == FMT_LEN_ll | |
1808 ? long_double_type_node : double_type_node); | |
1878 | 1809 |
1879 /* For an indeterminate precision the lower bound must be assumed | 1810 /* For an indeterminate precision the lower bound must be assumed |
1880 to be zero. */ | 1811 to be zero. */ |
1881 if (TOUPPER (dir.specifier) == 'A') | 1812 if (TOUPPER (dir.specifier) == 'A') |
1882 { | 1813 { |
1883 /* Get the number of fractional decimal digits needed to represent | 1814 /* Get the number of fractional decimal digits needed to represent |
1884 the argument without a loss of accuracy. */ | 1815 the argument without a loss of accuracy. */ |
1885 tree type = arg ? TREE_TYPE (arg) : | |
1886 (dir.modifier == FMT_LEN_L || dir.modifier == FMT_LEN_ll | |
1887 ? long_double_type_node : double_type_node); | |
1888 | |
1889 unsigned fmtprec | 1816 unsigned fmtprec |
1890 = REAL_MODE_FORMAT (TYPE_MODE (type))->p; | 1817 = REAL_MODE_FORMAT (TYPE_MODE (type))->p; |
1891 | 1818 |
1892 /* The precision of the IEEE 754 double format is 53. | 1819 /* The precision of the IEEE 754 double format is 53. |
1893 The precision of all other GCC binary double formats | 1820 The precision of all other GCC binary double formats |
1934 prec[0] = 0; | 1861 prec[0] = 0; |
1935 prec[1] = dir.prec[1] < 6 ? 6 : dir.prec[1]; | 1862 prec[1] = dir.prec[1] < 6 ? 6 : dir.prec[1]; |
1936 } | 1863 } |
1937 } | 1864 } |
1938 | 1865 |
1939 if (!arg || TREE_CODE (arg) != REAL_CST) | 1866 if (!arg |
1867 || TREE_CODE (arg) != REAL_CST | |
1868 || !useless_type_conversion_p (type, TREE_TYPE (arg))) | |
1940 return format_floating (dir, prec); | 1869 return format_floating (dir, prec); |
1941 | 1870 |
1942 /* The minimum and maximum number of bytes produced by the directive. */ | 1871 /* The minimum and maximum number of bytes produced by the directive. */ |
1943 fmtresult res; | 1872 fmtresult res; |
1944 | 1873 |
1945 /* Get the real type format desription for the target. */ | 1874 /* Get the real type format desription for the target. */ |
1946 const REAL_VALUE_TYPE *rvp = TREE_REAL_CST_PTR (arg); | 1875 const REAL_VALUE_TYPE *rvp = TREE_REAL_CST_PTR (arg); |
1947 const real_format *rfmt = REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg))); | 1876 const real_format *rfmt = REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (arg))); |
1877 | |
1878 if (!real_isfinite (rvp)) | |
1879 { | |
1880 /* The format for Infinity and NaN is "[-]inf"/"[-]infinity" | |
1881 and "[-]nan" with the choice being implementation-defined | |
1882 but not locale dependent. */ | |
1883 bool sign = dir.get_flag ('+') || real_isneg (rvp); | |
1884 res.range.min = 3 + sign; | |
1885 | |
1886 res.range.likely = res.range.min; | |
1887 res.range.max = res.range.min; | |
1888 /* The unlikely maximum is "[-/+]infinity" or "[-/+][qs]nan". | |
1889 For NaN, the C/POSIX standards specify two formats: | |
1890 "[-/+]nan" | |
1891 and | |
1892 "[-/+]nan(n-char-sequence)" | |
1893 No known printf implementation outputs the latter format but AIX | |
1894 outputs QNaN and SNaN for quiet and signalling NaN, respectively, | |
1895 so the unlikely maximum reflects that. */ | |
1896 res.range.unlikely = sign + (real_isinf (rvp) ? 8 : 4); | |
1897 | |
1898 /* The range for infinity and NaN is known unless either width | |
1899 or precision is unknown. Width has the same effect regardless | |
1900 of whether the argument is finite. Precision is either ignored | |
1901 (e.g., Glibc) or can have an effect on the short vs long format | |
1902 such as inf/infinity (e.g., Solaris). */ | |
1903 res.knownrange = dir.known_width_and_precision (); | |
1904 | |
1905 /* Adjust the range for width but ignore precision. */ | |
1906 res.adjust_for_width_or_precision (dir.width); | |
1907 | |
1908 return res; | |
1909 } | |
1948 | 1910 |
1949 char fmtstr [40]; | 1911 char fmtstr [40]; |
1950 char *pfmt = fmtstr; | 1912 char *pfmt = fmtstr; |
1951 | 1913 |
1952 /* Append flags. */ | 1914 /* Append flags. */ |
2031 /* Return a FMTRESULT struct set to the lengths of the shortest and longest | 1993 /* Return a FMTRESULT struct set to the lengths of the shortest and longest |
2032 strings referenced by the expression STR, or (-1, -1) when not known. | 1994 strings referenced by the expression STR, or (-1, -1) when not known. |
2033 Used by the format_string function below. */ | 1995 Used by the format_string function below. */ |
2034 | 1996 |
2035 static fmtresult | 1997 static fmtresult |
2036 get_string_length (tree str) | 1998 get_string_length (tree str, unsigned eltsize) |
2037 { | 1999 { |
2038 if (!str) | 2000 if (!str) |
2039 return fmtresult (); | 2001 return fmtresult (); |
2040 | 2002 |
2041 if (tree slen = c_strlen (str, 1)) | 2003 c_strlen_data data; |
2042 { | 2004 memset (&data, 0, sizeof (c_strlen_data)); |
2043 /* Simply return the length of the string. */ | 2005 tree slen = c_strlen (str, 1, &data, eltsize); |
2006 if (slen && TREE_CODE (slen) == INTEGER_CST) | |
2007 { | |
2008 /* The string is properly terminated and | |
2009 we know its length. */ | |
2044 fmtresult res (tree_to_shwi (slen)); | 2010 fmtresult res (tree_to_shwi (slen)); |
2011 res.nonstr = NULL_TREE; | |
2012 return res; | |
2013 } | |
2014 else if (!slen | |
2015 && data.decl | |
2016 && data.len | |
2017 && TREE_CODE (data.len) == INTEGER_CST) | |
2018 { | |
2019 /* STR was not properly NUL terminated, but we have | |
2020 length information about the unterminated string. */ | |
2021 fmtresult res (tree_to_shwi (data.len)); | |
2022 res.nonstr = data.decl; | |
2045 return res; | 2023 return res; |
2046 } | 2024 } |
2047 | 2025 |
2048 /* Determine the length of the shortest and longest string referenced | 2026 /* Determine the length of the shortest and longest string referenced |
2049 by STR. Strings of unknown lengths are bounded by the sizes of | 2027 by STR. Strings of unknown lengths are bounded by the sizes of |
2050 arrays that subexpressions of STR may refer to. Pointers that | 2028 arrays that subexpressions of STR may refer to. Pointers that |
2051 aren't known to point any such arrays result in LENRANGE[1] set | 2029 aren't known to point any such arrays result in LENRANGE[1] set |
2052 to SIZE_MAX. */ | 2030 to SIZE_MAX. NONSTR is set to the declaration of the constant |
2031 array that is known not to be nul-terminated. */ | |
2053 tree lenrange[2]; | 2032 tree lenrange[2]; |
2054 bool flexarray = get_range_strlen (str, lenrange); | 2033 tree nonstr; |
2034 bool flexarray = get_range_strlen (str, lenrange, eltsize, false, &nonstr); | |
2055 | 2035 |
2056 if (lenrange [0] || lenrange [1]) | 2036 if (lenrange [0] || lenrange [1]) |
2057 { | 2037 { |
2058 HOST_WIDE_INT min | 2038 HOST_WIDE_INT min |
2059 = (tree_fits_uhwi_p (lenrange[0]) | 2039 = (tree_fits_uhwi_p (lenrange[0]) |
2072 min = HOST_WIDE_INT_M1U; | 2052 min = HOST_WIDE_INT_M1U; |
2073 if ((unsigned HOST_WIDE_INT)max == target_size_max ()) | 2053 if ((unsigned HOST_WIDE_INT)max == target_size_max ()) |
2074 max = HOST_WIDE_INT_M1U; | 2054 max = HOST_WIDE_INT_M1U; |
2075 | 2055 |
2076 fmtresult res (min, max); | 2056 fmtresult res (min, max); |
2057 res.nonstr = nonstr; | |
2077 | 2058 |
2078 /* Set RES.KNOWNRANGE to true if and only if all strings referenced | 2059 /* Set RES.KNOWNRANGE to true if and only if all strings referenced |
2079 by STR are known to be bounded (though not necessarily by their | 2060 by STR are known to be bounded (though not necessarily by their |
2080 actual length but perhaps by their maximum possible length). */ | 2061 actual length but perhaps by their maximum possible length). */ |
2081 if (res.range.max < target_int_max ()) | 2062 if (res.range.max < target_int_max ()) |
2101 res.range.unlikely = flexarray ? HOST_WIDE_INT_MAX : res.range.max; | 2082 res.range.unlikely = flexarray ? HOST_WIDE_INT_MAX : res.range.max; |
2102 | 2083 |
2103 return res; | 2084 return res; |
2104 } | 2085 } |
2105 | 2086 |
2106 return get_string_length (NULL_TREE); | 2087 return fmtresult (); |
2107 } | 2088 } |
2108 | 2089 |
2109 /* Return the minimum and maximum number of characters formatted | 2090 /* Return the minimum and maximum number of characters formatted |
2110 by the '%c' format directives and its wide character form for | 2091 by the '%c' format directives and its wide character form for |
2111 the argument ARG. ARG can be null (for functions such as | 2092 the argument ARG. ARG can be null (for functions such as |
2112 vsprinf). */ | 2093 vsprinf). */ |
2113 | 2094 |
2114 static fmtresult | 2095 static fmtresult |
2115 format_character (const directive &dir, tree arg) | 2096 format_character (const directive &dir, tree arg, vr_values *vr_values) |
2116 { | 2097 { |
2117 fmtresult res; | 2098 fmtresult res; |
2118 | 2099 |
2119 res.knownrange = true; | 2100 res.knownrange = true; |
2120 | 2101 |
2121 if (dir.modifier == FMT_LEN_l) | 2102 if (dir.specifier == 'C' |
2103 || dir.modifier == FMT_LEN_l) | |
2122 { | 2104 { |
2123 /* A wide character can result in as few as zero bytes. */ | 2105 /* A wide character can result in as few as zero bytes. */ |
2124 res.range.min = 0; | 2106 res.range.min = 0; |
2125 | 2107 |
2126 HOST_WIDE_INT min, max; | 2108 HOST_WIDE_INT min, max; |
2127 if (get_int_range (arg, &min, &max, false, 0)) | 2109 if (get_int_range (arg, &min, &max, false, 0, vr_values)) |
2128 { | 2110 { |
2129 if (min == 0 && max == 0) | 2111 if (min == 0 && max == 0) |
2130 { | 2112 { |
2131 /* The NUL wide character results in no bytes. */ | 2113 /* The NUL wide character results in no bytes. */ |
2132 res.range.max = 0; | 2114 res.range.max = 0; |
2133 res.range.likely = 0; | 2115 res.range.likely = 0; |
2134 res.range.unlikely = 0; | 2116 res.range.unlikely = 0; |
2135 } | 2117 } |
2136 else if (min > 0 && min < 128) | 2118 else if (min >= 0 && min < 128) |
2137 { | 2119 { |
2120 /* Be conservative if the target execution character set | |
2121 is not a 1-to-1 mapping to the source character set or | |
2122 if the source set is not ASCII. */ | |
2123 bool one_2_one_ascii | |
2124 = (target_to_host_charmap[0] == 1 && target_to_host ('a') == 97); | |
2125 | |
2138 /* A wide character in the ASCII range most likely results | 2126 /* A wide character in the ASCII range most likely results |
2139 in a single byte, and only unlikely in up to MB_LEN_MAX. */ | 2127 in a single byte, and only unlikely in up to MB_LEN_MAX. */ |
2140 res.range.max = 1; | 2128 res.range.max = one_2_one_ascii ? 1 : target_mb_len_max ();; |
2141 res.range.likely = 1; | 2129 res.range.likely = 1; |
2142 res.range.unlikely = target_mb_len_max (); | 2130 res.range.unlikely = target_mb_len_max (); |
2131 res.mayfail = !one_2_one_ascii; | |
2143 } | 2132 } |
2144 else | 2133 else |
2145 { | 2134 { |
2146 /* A wide character outside the ASCII range likely results | 2135 /* A wide character outside the ASCII range likely results |
2147 in up to two bytes, and only unlikely in up to MB_LEN_MAX. */ | 2136 in up to two bytes, and only unlikely in up to MB_LEN_MAX. */ |
2148 res.range.max = target_mb_len_max (); | 2137 res.range.max = target_mb_len_max (); |
2149 res.range.likely = 2; | 2138 res.range.likely = 2; |
2150 res.range.unlikely = res.range.max; | 2139 res.range.unlikely = res.range.max; |
2140 /* Converting such a character may fail. */ | |
2141 res.mayfail = true; | |
2151 } | 2142 } |
2152 } | 2143 } |
2153 else | 2144 else |
2154 { | 2145 { |
2155 /* An unknown wide character is treated the same as a wide | 2146 /* An unknown wide character is treated the same as a wide |
2156 character outside the ASCII range. */ | 2147 character outside the ASCII range. */ |
2157 res.range.max = target_mb_len_max (); | 2148 res.range.max = target_mb_len_max (); |
2158 res.range.likely = 2; | 2149 res.range.likely = 2; |
2159 res.range.unlikely = res.range.max; | 2150 res.range.unlikely = res.range.max; |
2151 res.mayfail = true; | |
2160 } | 2152 } |
2161 } | 2153 } |
2162 else | 2154 else |
2163 { | 2155 { |
2164 /* A plain '%c' directive. Its ouput is exactly 1. */ | 2156 /* A plain '%c' directive. Its ouput is exactly 1. */ |
2175 by the '%s' format directive and its wide character form for | 2167 by the '%s' format directive and its wide character form for |
2176 the argument ARG. ARG can be null (for functions such as | 2168 the argument ARG. ARG can be null (for functions such as |
2177 vsprinf). */ | 2169 vsprinf). */ |
2178 | 2170 |
2179 static fmtresult | 2171 static fmtresult |
2180 format_string (const directive &dir, tree arg) | 2172 format_string (const directive &dir, tree arg, vr_values *) |
2181 { | 2173 { |
2182 fmtresult res; | 2174 fmtresult res; |
2183 | 2175 |
2184 /* Compute the range the argument's length can be in. */ | 2176 /* Compute the range the argument's length can be in. */ |
2185 fmtresult slen = get_string_length (arg); | 2177 int count_by = 1; |
2178 if (dir.specifier == 'S' || dir.modifier == FMT_LEN_l) | |
2179 { | |
2180 /* Get a node for a C type that will be the same size | |
2181 as a wchar_t on the target. */ | |
2182 tree node = get_typenode_from_name (MODIFIED_WCHAR_TYPE); | |
2183 | |
2184 /* Now that we have a suitable node, get the number of | |
2185 bytes it occupies. */ | |
2186 count_by = int_size_in_bytes (node); | |
2187 gcc_checking_assert (count_by == 2 || count_by == 4); | |
2188 } | |
2189 | |
2190 fmtresult slen = get_string_length (arg, count_by); | |
2186 if (slen.range.min == slen.range.max | 2191 if (slen.range.min == slen.range.max |
2187 && slen.range.min < HOST_WIDE_INT_MAX) | 2192 && slen.range.min < HOST_WIDE_INT_MAX) |
2188 { | 2193 { |
2189 /* The argument is either a string constant or it refers | 2194 /* The argument is either a string constant or it refers |
2190 to one of a number of strings of the same length. */ | 2195 to one of a number of strings of the same length. */ |
2191 | 2196 |
2192 /* A '%s' directive with a string argument with constant length. */ | 2197 /* A '%s' directive with a string argument with constant length. */ |
2193 res.range = slen.range; | 2198 res.range = slen.range; |
2194 | 2199 |
2195 if (dir.modifier == FMT_LEN_l) | 2200 if (dir.specifier == 'S' |
2201 || dir.modifier == FMT_LEN_l) | |
2196 { | 2202 { |
2197 /* In the worst case the length of output of a wide string S | 2203 /* In the worst case the length of output of a wide string S |
2198 is bounded by MB_LEN_MAX * wcslen (S). */ | 2204 is bounded by MB_LEN_MAX * wcslen (S). */ |
2199 res.range.max *= target_mb_len_max (); | 2205 res.range.max *= target_mb_len_max (); |
2200 res.range.unlikely = res.range.max; | 2206 res.range.unlikely = res.range.max; |
2216 res.range.likely = dir.prec[0]; | 2222 res.range.likely = dir.prec[0]; |
2217 | 2223 |
2218 /* Even a non-empty wide character string need not convert into | 2224 /* Even a non-empty wide character string need not convert into |
2219 any bytes. */ | 2225 any bytes. */ |
2220 res.range.min = 0; | 2226 res.range.min = 0; |
2227 | |
2228 /* A non-empty wide character conversion may fail. */ | |
2229 if (slen.range.max > 0) | |
2230 res.mayfail = true; | |
2221 } | 2231 } |
2222 else | 2232 else |
2223 { | 2233 { |
2224 res.knownrange = true; | 2234 res.knownrange = true; |
2225 | 2235 |
2254 PTRDIFF_MAX and PRECISION[1]. The likely length is either | 2264 PTRDIFF_MAX and PRECISION[1]. The likely length is either |
2255 the minimum at level 1 and the greater of the minimum and 1 | 2265 the minimum at level 1 and the greater of the minimum and 1 |
2256 at level 2. This result is adjust upward for width (if it's | 2266 at level 2. This result is adjust upward for width (if it's |
2257 specified). */ | 2267 specified). */ |
2258 | 2268 |
2259 if (dir.modifier == FMT_LEN_l) | 2269 if (dir.specifier == 'S' |
2270 || dir.modifier == FMT_LEN_l) | |
2260 { | 2271 { |
2261 /* A wide character converts to as few as zero bytes. */ | 2272 /* A wide character converts to as few as zero bytes. */ |
2262 slen.range.min = 0; | 2273 slen.range.min = 0; |
2263 if (slen.range.max < target_int_max ()) | 2274 if (slen.range.max < target_int_max ()) |
2264 slen.range.max *= target_mb_len_max (); | 2275 slen.range.max *= target_mb_len_max (); |
2266 if (slen.range.likely < target_int_max ()) | 2277 if (slen.range.likely < target_int_max ()) |
2267 slen.range.likely *= 2; | 2278 slen.range.likely *= 2; |
2268 | 2279 |
2269 if (slen.range.likely < target_int_max ()) | 2280 if (slen.range.likely < target_int_max ()) |
2270 slen.range.unlikely *= target_mb_len_max (); | 2281 slen.range.unlikely *= target_mb_len_max (); |
2282 | |
2283 /* A non-empty wide character conversion may fail. */ | |
2284 if (slen.range.max > 0) | |
2285 res.mayfail = true; | |
2271 } | 2286 } |
2272 | 2287 |
2273 res.range = slen.range; | 2288 res.range = slen.range; |
2274 | 2289 |
2275 if (dir.prec[0] >= 0) | 2290 if (dir.prec[0] >= 0) |
2329 } | 2344 } |
2330 | 2345 |
2331 res.range.unlikely = res.range.max; | 2346 res.range.unlikely = res.range.max; |
2332 } | 2347 } |
2333 | 2348 |
2349 /* If the argument isn't a nul-terminated string and the number | |
2350 of bytes on output isn't bounded by precision, set NONSTR. */ | |
2351 if (slen.nonstr && slen.range.min < (unsigned HOST_WIDE_INT)dir.prec[0]) | |
2352 res.nonstr = slen.nonstr; | |
2353 | |
2334 /* Bump up the byte counters if WIDTH is greater. */ | 2354 /* Bump up the byte counters if WIDTH is greater. */ |
2335 return res.adjust_for_width_or_precision (dir.width); | 2355 return res.adjust_for_width_or_precision (dir.width); |
2336 } | 2356 } |
2337 | 2357 |
2338 /* Format plain string (part of the format string itself). */ | 2358 /* Format plain string (part of the format string itself). */ |
2339 | 2359 |
2340 static fmtresult | 2360 static fmtresult |
2341 format_plain (const directive &dir, tree) | 2361 format_plain (const directive &dir, tree, vr_values *) |
2342 { | 2362 { |
2343 fmtresult res (dir.len); | 2363 fmtresult res (dir.len); |
2344 return res; | 2364 return res; |
2345 } | 2365 } |
2346 | 2366 |
2347 /* Return true if the RESULT of a directive in a call describe by INFO | 2367 /* Return true if the RESULT of a directive in a call describe by INFO |
2348 should be diagnosed given the AVAILable space in the destination. */ | 2368 should be diagnosed given the AVAILable space in the destination. */ |
2349 | 2369 |
2350 static bool | 2370 static bool |
2351 should_warn_p (const pass_sprintf_length::call_info &info, | 2371 should_warn_p (const sprintf_dom_walker::call_info &info, |
2352 const result_range &avail, const result_range &result) | 2372 const result_range &avail, const result_range &result) |
2353 { | 2373 { |
2354 if (result.max <= avail.min) | 2374 if (result.max <= avail.min) |
2355 { | 2375 { |
2356 /* The least amount of space remaining in the destination is big | 2376 /* The least amount of space remaining in the destination is big |
2417 past the end or truncation and, if so, format the warning. | 2437 past the end or truncation and, if so, format the warning. |
2418 Return true if a warning has been issued. */ | 2438 Return true if a warning has been issued. */ |
2419 | 2439 |
2420 static bool | 2440 static bool |
2421 maybe_warn (substring_loc &dirloc, location_t argloc, | 2441 maybe_warn (substring_loc &dirloc, location_t argloc, |
2422 const pass_sprintf_length::call_info &info, | 2442 const sprintf_dom_walker::call_info &info, |
2423 const result_range &avail_range, const result_range &res, | 2443 const result_range &avail_range, const result_range &res, |
2424 const directive &dir) | 2444 const directive &dir) |
2425 { | 2445 { |
2426 if (!should_warn_p (info, avail_range, res)) | 2446 if (!should_warn_p (info, avail_range, res)) |
2427 return false; | 2447 return false; |
2454 if (target_to_host (*dir.beg) != '%') | 2474 if (target_to_host (*dir.beg) != '%') |
2455 { | 2475 { |
2456 /* For plain character directives (i.e., the format string itself) | 2476 /* For plain character directives (i.e., the format string itself) |
2457 but not others, point the caret at the first character that's | 2477 but not others, point the caret at the first character that's |
2458 past the end of the destination. */ | 2478 past the end of the destination. */ |
2459 dirloc.set_caret_index (dirloc.get_caret_idx () + navail); | 2479 if (navail < dir.len) |
2480 dirloc.set_caret_index (dirloc.get_caret_idx () + navail); | |
2460 } | 2481 } |
2461 | 2482 |
2462 if (*dir.beg == '\0') | 2483 if (*dir.beg == '\0') |
2463 { | 2484 { |
2464 /* This is the terminating nul. */ | 2485 /* This is the terminating nul. */ |
2465 gcc_assert (res.min == 1 && res.min == res.max); | 2486 gcc_assert (res.min == 1 && res.min == res.max); |
2466 | 2487 |
2467 const char *fmtstr | |
2468 = (info.bounded | |
2469 ? (maybe | |
2470 ? G_("%qE output may be truncated before the last format " | |
2471 "character") | |
2472 : G_("%qE output truncated before the last format character")) | |
2473 : (maybe | |
2474 ? G_("%qE may write a terminating nul past the end " | |
2475 "of the destination") | |
2476 : G_("%qE writing a terminating nul past the end " | |
2477 "of the destination"))); | |
2478 | |
2479 return fmtwarn (dirloc, UNKNOWN_LOCATION, NULL, info.warnopt (), | 2488 return fmtwarn (dirloc, UNKNOWN_LOCATION, NULL, info.warnopt (), |
2480 fmtstr, info.func); | 2489 info.bounded |
2490 ? (maybe | |
2491 ? G_("%qE output may be truncated before the " | |
2492 "last format character") | |
2493 : G_("%qE output truncated before the last " | |
2494 "format character")) | |
2495 : (maybe | |
2496 ? G_("%qE may write a terminating nul past the " | |
2497 "end of the destination") | |
2498 : G_("%qE writing a terminating nul past the " | |
2499 "end of the destination")), | |
2500 info.func); | |
2481 } | 2501 } |
2482 | 2502 |
2483 if (res.min == res.max) | 2503 if (res.min == res.max) |
2484 { | 2504 { |
2485 const char* fmtstr | 2505 const char *d = target_to_host (hostdir, sizeof hostdir, dir.beg); |
2486 = (res.min == 1 | 2506 if (!info.bounded) |
2487 ? (info.bounded | 2507 return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min, |
2488 ? (maybe | 2508 "%<%.*s%> directive writing %wu byte into a " |
2489 ? G_("%<%.*s%> directive output may be truncated writing " | 2509 "region of size %wu", |
2490 "%wu byte into a region of size %wu") | 2510 "%<%.*s%> directive writing %wu bytes into a " |
2491 : G_("%<%.*s%> directive output truncated writing " | 2511 "region of size %wu", |
2492 "%wu byte into a region of size %wu")) | 2512 (int) dir.len, d, res.min, navail); |
2493 : G_("%<%.*s%> directive writing %wu byte " | 2513 else if (maybe) |
2494 "into a region of size %wu")) | 2514 return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min, |
2495 : (info.bounded | 2515 "%<%.*s%> directive output may be truncated " |
2496 ? (maybe | 2516 "writing %wu byte into a region of size %wu", |
2497 ? G_("%<%.*s%> directive output may be truncated writing " | 2517 "%<%.*s%> directive output may be truncated " |
2498 "%wu bytes into a region of size %wu") | 2518 "writing %wu bytes into a region of size %wu", |
2499 : G_("%<%.*s%> directive output truncated writing " | 2519 (int) dir.len, d, res.min, navail); |
2500 "%wu bytes into a region of size %wu")) | 2520 else |
2501 : G_("%<%.*s%> directive writing %wu bytes " | 2521 return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min, |
2502 "into a region of size %wu"))); | 2522 "%<%.*s%> directive output truncated writing " |
2503 return fmtwarn (dirloc, argloc, NULL, | 2523 "%wu byte into a region of size %wu", |
2504 info.warnopt (), fmtstr, dir.len, | 2524 "%<%.*s%> directive output truncated writing " |
2505 target_to_host (hostdir, sizeof hostdir, dir.beg), | 2525 "%wu bytes into a region of size %wu", |
2506 res.min, navail); | 2526 (int) dir.len, d, res.min, navail); |
2507 } | 2527 } |
2508 | |
2509 if (res.min == 0 && res.max < maxbytes) | 2528 if (res.min == 0 && res.max < maxbytes) |
2510 { | 2529 return fmtwarn (dirloc, argloc, NULL, |
2511 const char* fmtstr | 2530 info.warnopt (), |
2512 = (info.bounded | 2531 info.bounded |
2513 ? (maybe | 2532 ? (maybe |
2514 ? G_("%<%.*s%> directive output may be truncated writing " | 2533 ? G_("%<%.*s%> directive output may be truncated " |
2515 "up to %wu bytes into a region of size %wu") | 2534 "writing up to %wu bytes into a region of " |
2516 : G_("%<%.*s%> directive output truncated writing " | 2535 "size %wu") |
2517 "up to %wu bytes into a region of size %wu")) | 2536 : G_("%<%.*s%> directive output truncated writing " |
2518 : G_("%<%.*s%> directive writing up to %wu bytes " | 2537 "up to %wu bytes into a region of size %wu")) |
2519 "into a region of size %wu")); | 2538 : G_("%<%.*s%> directive writing up to %wu bytes " |
2520 return fmtwarn (dirloc, argloc, NULL, | 2539 "into a region of size %wu"), (int) dir.len, |
2521 info.warnopt (), fmtstr, dir.len, | 2540 target_to_host (hostdir, sizeof hostdir, dir.beg), |
2522 target_to_host (hostdir, sizeof hostdir, dir.beg), | 2541 res.max, navail); |
2523 res.max, navail); | |
2524 } | |
2525 | 2542 |
2526 if (res.min == 0 && maxbytes <= res.max) | 2543 if (res.min == 0 && maxbytes <= res.max) |
2527 { | 2544 /* This is a special case to avoid issuing the potentially |
2528 /* This is a special case to avoid issuing the potentially | 2545 confusing warning: |
2529 confusing warning: | 2546 writing 0 or more bytes into a region of size 0. */ |
2530 writing 0 or more bytes into a region of size 0. */ | 2547 return fmtwarn (dirloc, argloc, NULL, info.warnopt (), |
2531 const char* fmtstr | 2548 info.bounded |
2532 = (info.bounded | 2549 ? (maybe |
2533 ? (maybe | 2550 ? G_("%<%.*s%> directive output may be truncated " |
2534 ? G_("%<%.*s%> directive output may be truncated writing " | 2551 "writing likely %wu or more bytes into a " |
2535 "likely %wu or more bytes into a region of size %wu") | 2552 "region of size %wu") |
2536 : G_("%<%.*s%> directive output truncated writing " | 2553 : G_("%<%.*s%> directive output truncated writing " |
2537 "likely %wu or more bytes into a region of size %wu")) | 2554 "likely %wu or more bytes into a region of " |
2538 : G_("%<%.*s%> directive writing likely %wu or more bytes " | 2555 "size %wu")) |
2539 "into a region of size %wu")); | 2556 : G_("%<%.*s%> directive writing likely %wu or more " |
2540 return fmtwarn (dirloc, argloc, NULL, | 2557 "bytes into a region of size %wu"), (int) dir.len, |
2541 info.warnopt (), fmtstr, dir.len, | 2558 target_to_host (hostdir, sizeof hostdir, dir.beg), |
2542 target_to_host (hostdir, sizeof hostdir, dir.beg), | 2559 res.likely, navail); |
2543 res.likely, navail); | |
2544 } | |
2545 | 2560 |
2546 if (res.max < maxbytes) | 2561 if (res.max < maxbytes) |
2547 { | 2562 return fmtwarn (dirloc, argloc, NULL, info.warnopt (), |
2548 const char* fmtstr | 2563 info.bounded |
2549 = (info.bounded | 2564 ? (maybe |
2550 ? (maybe | 2565 ? G_("%<%.*s%> directive output may be truncated " |
2551 ? G_("%<%.*s%> directive output may be truncated writing " | 2566 "writing between %wu and %wu bytes into a " |
2552 "between %wu and %wu bytes into a region of size %wu") | 2567 "region of size %wu") |
2553 : G_("%<%.*s%> directive output truncated writing " | 2568 : G_("%<%.*s%> directive output truncated " |
2554 "between %wu and %wu bytes into a region of size %wu")) | 2569 "writing between %wu and %wu bytes into a " |
2555 : G_("%<%.*s%> directive writing between %wu and " | 2570 "region of size %wu")) |
2556 "%wu bytes into a region of size %wu")); | 2571 : G_("%<%.*s%> directive writing between %wu and " |
2557 return fmtwarn (dirloc, argloc, NULL, | 2572 "%wu bytes into a region of size %wu"), |
2558 info.warnopt (), fmtstr, dir.len, | 2573 (int) dir.len, |
2559 target_to_host (hostdir, sizeof hostdir, dir.beg), | 2574 target_to_host (hostdir, sizeof hostdir, dir.beg), |
2560 res.min, res.max, navail); | 2575 res.min, res.max, navail); |
2561 } | 2576 |
2562 | 2577 return fmtwarn (dirloc, argloc, NULL, info.warnopt (), |
2563 const char* fmtstr | 2578 info.bounded |
2564 = (info.bounded | 2579 ? (maybe |
2565 ? (maybe | 2580 ? G_("%<%.*s%> directive output may be truncated " |
2566 ? G_("%<%.*s%> directive output may be truncated writing " | 2581 "writing %wu or more bytes into a region of " |
2567 "%wu or more bytes into a region of size %wu") | 2582 "size %wu") |
2568 : G_("%<%.*s%> directive output truncated writing " | 2583 : G_("%<%.*s%> directive output truncated writing " |
2569 "%wu or more bytes into a region of size %wu")) | 2584 "%wu or more bytes into a region of size %wu")) |
2570 : G_("%<%.*s%> directive writing %wu or more bytes " | 2585 : G_("%<%.*s%> directive writing %wu or more bytes " |
2571 "into a region of size %wu")); | 2586 "into a region of size %wu"), (int) dir.len, |
2572 return fmtwarn (dirloc, argloc, NULL, | |
2573 info.warnopt (), fmtstr, dir.len, | |
2574 target_to_host (hostdir, sizeof hostdir, dir.beg), | 2587 target_to_host (hostdir, sizeof hostdir, dir.beg), |
2575 res.min, navail); | 2588 res.min, navail); |
2576 } | 2589 } |
2577 | 2590 |
2578 /* The size of the destination region is a range. */ | 2591 /* The size of the destination region is a range. */ |
2582 unsigned HOST_WIDE_INT navail = avail_range.max; | 2595 unsigned HOST_WIDE_INT navail = avail_range.max; |
2583 | 2596 |
2584 /* For plain character directives (i.e., the format string itself) | 2597 /* For plain character directives (i.e., the format string itself) |
2585 but not others, point the caret at the first character that's | 2598 but not others, point the caret at the first character that's |
2586 past the end of the destination. */ | 2599 past the end of the destination. */ |
2587 dirloc.set_caret_index (dirloc.get_caret_idx () + navail); | 2600 if (navail < dir.len) |
2601 dirloc.set_caret_index (dirloc.get_caret_idx () + navail); | |
2588 } | 2602 } |
2589 | 2603 |
2590 if (*dir.beg == '\0') | 2604 if (*dir.beg == '\0') |
2591 { | 2605 { |
2592 gcc_assert (res.min == 1 && res.min == res.max); | 2606 gcc_assert (res.min == 1 && res.min == res.max); |
2593 | 2607 |
2594 const char *fmtstr | 2608 return fmtwarn (dirloc, UNKNOWN_LOCATION, NULL, info.warnopt (), |
2595 = (info.bounded | 2609 info.bounded |
2596 ? (maybe | 2610 ? (maybe |
2597 ? G_("%qE output may be truncated before the last format " | 2611 ? G_("%qE output may be truncated before the last " |
2598 "character") | 2612 "format character") |
2599 : G_("%qE output truncated before the last format character")) | 2613 : G_("%qE output truncated before the last format " |
2600 : (maybe | 2614 "character")) |
2601 ? G_("%qE may write a terminating nul past the end " | 2615 : (maybe |
2602 "of the destination") | 2616 ? G_("%qE may write a terminating nul past the end " |
2603 : G_("%qE writing a terminating nul past the end " | 2617 "of the destination") |
2604 "of the destination"))); | 2618 : G_("%qE writing a terminating nul past the end " |
2605 | 2619 "of the destination")), info.func); |
2606 return fmtwarn (dirloc, UNKNOWN_LOCATION, NULL, info.warnopt (), fmtstr, | |
2607 info.func); | |
2608 } | 2620 } |
2609 | 2621 |
2610 if (res.min == res.max) | 2622 if (res.min == res.max) |
2611 { | 2623 { |
2612 const char* fmtstr | 2624 const char *d = target_to_host (hostdir, sizeof hostdir, dir.beg); |
2613 = (res.min == 1 | 2625 if (!info.bounded) |
2614 ? (info.bounded | 2626 return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min, |
2615 ? (maybe | 2627 "%<%.*s%> directive writing %wu byte into a region " |
2616 ? G_("%<%.*s%> directive output may be truncated writing " | 2628 "of size between %wu and %wu", |
2617 "%wu byte into a region of size between %wu and %wu") | 2629 "%<%.*s%> directive writing %wu bytes into a region " |
2618 : G_("%<%.*s%> directive output truncated writing " | 2630 "of size between %wu and %wu", (int) dir.len, d, |
2619 "%wu byte into a region of size between %wu and %wu")) | 2631 res.min, avail_range.min, avail_range.max); |
2620 : G_("%<%.*s%> directive writing %wu byte " | 2632 else if (maybe) |
2621 "into a region of size between %wu and %wu")) | 2633 return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min, |
2622 : (info.bounded | 2634 "%<%.*s%> directive output may be truncated writing " |
2623 ? (maybe | 2635 "%wu byte into a region of size between %wu and %wu", |
2624 ? G_("%<%.*s%> directive output may be truncated writing " | 2636 "%<%.*s%> directive output may be truncated writing " |
2625 "%wu bytes into a region of size between %wu and %wu") | 2637 "%wu bytes into a region of size between %wu and " |
2626 : G_("%<%.*s%> directive output truncated writing " | 2638 "%wu", (int) dir.len, d, res.min, avail_range.min, |
2627 "%wu bytes into a region of size between %wu and %wu")) | 2639 avail_range.max); |
2628 : G_("%<%.*s%> directive writing %wu bytes " | 2640 else |
2629 "into a region of size between %wu and %wu"))); | 2641 return fmtwarn_n (dirloc, argloc, NULL, info.warnopt (), res.min, |
2630 | 2642 "%<%.*s%> directive output truncated writing %wu " |
2631 return fmtwarn (dirloc, argloc, NULL, | 2643 "byte into a region of size between %wu and %wu", |
2632 info.warnopt (), fmtstr, dir.len, | 2644 "%<%.*s%> directive output truncated writing %wu " |
2633 target_to_host (hostdir, sizeof hostdir, dir.beg), | 2645 "bytes into a region of size between %wu and %wu", |
2634 res.min, avail_range.min, avail_range.max); | 2646 (int) dir.len, d, res.min, avail_range.min, |
2647 avail_range.max); | |
2635 } | 2648 } |
2636 | 2649 |
2637 if (res.min == 0 && res.max < maxbytes) | 2650 if (res.min == 0 && res.max < maxbytes) |
2638 { | 2651 return fmtwarn (dirloc, argloc, NULL, info.warnopt (), |
2639 const char* fmtstr | 2652 info.bounded |
2640 = (info.bounded | 2653 ? (maybe |
2641 ? (maybe | 2654 ? G_("%<%.*s%> directive output may be truncated " |
2642 ? G_("%<%.*s%> directive output may be truncated writing " | 2655 "writing up to %wu bytes into a region of size " |
2643 "up to %wu bytes into a region of size between " | 2656 "between %wu and %wu") |
2644 "%wu and %wu") | 2657 : G_("%<%.*s%> directive output truncated writing " |
2645 : G_("%<%.*s%> directive output truncated writing " | 2658 "up to %wu bytes into a region of size between " |
2646 "up to %wu bytes into a region of size between " | 2659 "%wu and %wu")) |
2647 "%wu and %wu")) | 2660 : G_("%<%.*s%> directive writing up to %wu bytes " |
2648 : G_("%<%.*s%> directive writing up to %wu bytes " | 2661 "into a region of size between %wu and %wu"), |
2649 "into a region of size between %wu and %wu")); | 2662 (int) dir.len, |
2650 return fmtwarn (dirloc, argloc, NULL, | 2663 target_to_host (hostdir, sizeof hostdir, dir.beg), |
2651 info.warnopt (), fmtstr, dir.len, | 2664 res.max, avail_range.min, avail_range.max); |
2652 target_to_host (hostdir, sizeof hostdir, dir.beg), | |
2653 res.max, avail_range.min, avail_range.max); | |
2654 } | |
2655 | 2665 |
2656 if (res.min == 0 && maxbytes <= res.max) | 2666 if (res.min == 0 && maxbytes <= res.max) |
2657 { | 2667 /* This is a special case to avoid issuing the potentially confusing |
2658 /* This is a special case to avoid issuing the potentially confusing | 2668 warning: |
2659 warning: | 2669 writing 0 or more bytes into a region of size between 0 and N. */ |
2660 writing 0 or more bytes into a region of size between 0 and N. */ | 2670 return fmtwarn (dirloc, argloc, NULL, info.warnopt (), |
2661 const char* fmtstr | 2671 info.bounded |
2662 = (info.bounded | 2672 ? (maybe |
2663 ? (maybe | 2673 ? G_("%<%.*s%> directive output may be truncated " |
2664 ? G_("%<%.*s%> directive output may be truncated writing " | 2674 "writing likely %wu or more bytes into a region " |
2665 "likely %wu or more bytes into a region of size between " | 2675 "of size between %wu and %wu") |
2666 "%wu and %wu") | 2676 : G_("%<%.*s%> directive output truncated writing " |
2667 : G_("%<%.*s%> directive output truncated writing likely " | 2677 "likely %wu or more bytes into a region of size " |
2668 "%wu or more bytes into a region of size between " | 2678 "between %wu and %wu")) |
2669 "%wu and %wu")) | 2679 : G_("%<%.*s%> directive writing likely %wu or more bytes " |
2670 : G_("%<%.*s%> directive writing likely %wu or more bytes " | 2680 "into a region of size between %wu and %wu"), |
2671 "into a region of size between %wu and %wu")); | 2681 (int) dir.len, |
2672 return fmtwarn (dirloc, argloc, NULL, | 2682 target_to_host (hostdir, sizeof hostdir, dir.beg), |
2673 info.warnopt (), fmtstr, dir.len, | 2683 res.likely, avail_range.min, avail_range.max); |
2674 target_to_host (hostdir, sizeof hostdir, dir.beg), | |
2675 res.likely, avail_range.min, avail_range.max); | |
2676 } | |
2677 | 2684 |
2678 if (res.max < maxbytes) | 2685 if (res.max < maxbytes) |
2679 { | 2686 return fmtwarn (dirloc, argloc, NULL, info.warnopt (), |
2680 const char* fmtstr | 2687 info.bounded |
2681 = (info.bounded | 2688 ? (maybe |
2682 ? (maybe | 2689 ? G_("%<%.*s%> directive output may be truncated " |
2683 ? G_("%<%.*s%> directive output may be truncated writing " | 2690 "writing between %wu and %wu bytes into a region " |
2684 "between %wu and %wu bytes into a region of size " | 2691 "of size between %wu and %wu") |
2685 "between %wu and %wu") | 2692 : G_("%<%.*s%> directive output truncated writing " |
2686 : G_("%<%.*s%> directive output truncated writing " | 2693 "between %wu and %wu bytes into a region of size " |
2687 "between %wu and %wu bytes into a region of size " | 2694 "between %wu and %wu")) |
2688 "between %wu and %wu")) | 2695 : G_("%<%.*s%> directive writing between %wu and " |
2689 : G_("%<%.*s%> directive writing between %wu and " | 2696 "%wu bytes into a region of size between %wu and " |
2690 "%wu bytes into a region of size between %wu and %wu")); | 2697 "%wu"), (int) dir.len, |
2691 return fmtwarn (dirloc, argloc, NULL, | 2698 target_to_host (hostdir, sizeof hostdir, dir.beg), |
2692 info.warnopt (), fmtstr, dir.len, | 2699 res.min, res.max, avail_range.min, avail_range.max); |
2693 target_to_host (hostdir, sizeof hostdir, dir.beg), | 2700 |
2694 res.min, res.max, avail_range.min, avail_range.max); | 2701 return fmtwarn (dirloc, argloc, NULL, info.warnopt (), |
2695 } | 2702 info.bounded |
2696 | 2703 ? (maybe |
2697 const char* fmtstr | 2704 ? G_("%<%.*s%> directive output may be truncated writing " |
2698 = (info.bounded | 2705 "%wu or more bytes into a region of size between " |
2699 ? (maybe | 2706 "%wu and %wu") |
2700 ? G_("%<%.*s%> directive output may be truncated writing " | 2707 : G_("%<%.*s%> directive output truncated writing " |
2701 "%wu or more bytes into a region of size between " | 2708 "%wu or more bytes into a region of size between " |
2702 "%wu and %wu") | 2709 "%wu and %wu")) |
2703 : G_("%<%.*s%> directive output truncated writing " | 2710 : G_("%<%.*s%> directive writing %wu or more bytes " |
2704 "%wu or more bytes into a region of size between " | 2711 "into a region of size between %wu and %wu"), |
2705 "%wu and %wu")) | 2712 (int) dir.len, |
2706 : G_("%<%.*s%> directive writing %wu or more bytes " | |
2707 "into a region of size between %wu and %wu")); | |
2708 return fmtwarn (dirloc, argloc, NULL, | |
2709 info.warnopt (), fmtstr, dir.len, | |
2710 target_to_host (hostdir, sizeof hostdir, dir.beg), | 2713 target_to_host (hostdir, sizeof hostdir, dir.beg), |
2711 res.min, avail_range.min, avail_range.max); | 2714 res.min, avail_range.min, avail_range.max); |
2712 } | 2715 } |
2713 | 2716 |
2714 /* Compute the length of the output resulting from the directive DIR | 2717 /* Compute the length of the output resulting from the directive DIR |
2715 in a call described by INFO and update the overall result of the call | 2718 in a call described by INFO and update the overall result of the call |
2716 in *RES. Return true if the directive has been handled. */ | 2719 in *RES. Return true if the directive has been handled. */ |
2717 | 2720 |
2718 static bool | 2721 static bool |
2719 format_directive (const pass_sprintf_length::call_info &info, | 2722 format_directive (const sprintf_dom_walker::call_info &info, |
2720 format_result *res, const directive &dir) | 2723 format_result *res, const directive &dir, |
2724 class vr_values *vr_values) | |
2721 { | 2725 { |
2722 /* Offset of the beginning of the directive from the beginning | 2726 /* Offset of the beginning of the directive from the beginning |
2723 of the format string. */ | 2727 of the format string. */ |
2724 size_t offset = dir.beg - info.fmtstr; | 2728 size_t offset = dir.beg - info.fmtstr; |
2725 size_t start = offset; | 2729 size_t start = offset; |
2740 or when minimum length checking has been disabled. */ | 2744 or when minimum length checking has been disabled. */ |
2741 if (!dir.fmtfunc || res->range.min >= HOST_WIDE_INT_MAX) | 2745 if (!dir.fmtfunc || res->range.min >= HOST_WIDE_INT_MAX) |
2742 return false; | 2746 return false; |
2743 | 2747 |
2744 /* Compute the range of lengths of the formatted output. */ | 2748 /* Compute the range of lengths of the formatted output. */ |
2745 fmtresult fmtres = dir.fmtfunc (dir, dir.arg); | 2749 fmtresult fmtres = dir.fmtfunc (dir, dir.arg, vr_values); |
2746 | 2750 |
2747 /* Record whether the output of all directives is known to be | 2751 /* Record whether the output of all directives is known to be |
2748 bounded by some maximum, implying that their arguments are | 2752 bounded by some maximum, implying that their arguments are |
2749 either known exactly or determined to be in a known range | 2753 either known exactly or determined to be in a known range |
2750 or, for strings, limited by the upper bounds of the arrays | 2754 or, for strings, limited by the upper bounds of the arrays |
2834 | 2838 |
2835 /* Has the minimum directive output length exceeded the maximum | 2839 /* Has the minimum directive output length exceeded the maximum |
2836 of 4095 bytes required to be supported? */ | 2840 of 4095 bytes required to be supported? */ |
2837 bool minunder4k = fmtres.range.min < 4096; | 2841 bool minunder4k = fmtres.range.min < 4096; |
2838 bool maxunder4k = fmtres.range.max < 4096; | 2842 bool maxunder4k = fmtres.range.max < 4096; |
2839 /* Clear UNDER4K in the overall result if the maximum has exceeded | 2843 /* Clear POSUNDER4K in the overall result if the maximum has exceeded |
2840 the 4k (this is necessary to avoid the return valuye optimization | 2844 the 4k (this is necessary to avoid the return value optimization |
2841 that may not be safe in the maximum case). */ | 2845 that may not be safe in the maximum case). */ |
2842 if (!maxunder4k) | 2846 if (!maxunder4k) |
2843 res->under4k = false; | 2847 res->posunder4k = false; |
2848 /* Also clear POSUNDER4K if the directive may fail. */ | |
2849 if (fmtres.mayfail) | |
2850 res->posunder4k = false; | |
2844 | 2851 |
2845 if (!warned | 2852 if (!warned |
2846 /* Only warn at level 2. */ | 2853 /* Only warn at level 2. */ |
2847 && 1 < warn_level | 2854 && warn_level > 1 |
2848 && (!minunder4k | 2855 && (!minunder4k |
2849 || (!maxunder4k && fmtres.range.max < HOST_WIDE_INT_MAX))) | 2856 || (!maxunder4k && fmtres.range.max < HOST_WIDE_INT_MAX))) |
2850 { | 2857 { |
2851 /* The directive output may be longer than the maximum required | 2858 /* The directive output may be longer than the maximum required |
2852 to be handled by an implementation according to 7.21.6.1, p15 | 2859 to be handled by an implementation according to 7.21.6.1, p15 |
2854 prevent folding the return value when done. This allows for | 2861 prevent folding the return value when done. This allows for |
2855 the possibility of the actual libc call failing due to ENOMEM | 2862 the possibility of the actual libc call failing due to ENOMEM |
2856 (like Glibc does under some conditions). */ | 2863 (like Glibc does under some conditions). */ |
2857 | 2864 |
2858 if (fmtres.range.min == fmtres.range.max) | 2865 if (fmtres.range.min == fmtres.range.max) |
2859 warned = fmtwarn (dirloc, argloc, NULL, | 2866 warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (), |
2860 info.warnopt (), | |
2861 "%<%.*s%> directive output of %wu bytes exceeds " | 2867 "%<%.*s%> directive output of %wu bytes exceeds " |
2862 "minimum required size of 4095", | 2868 "minimum required size of 4095", dirlen, |
2863 dirlen, | |
2864 target_to_host (hostdir, sizeof hostdir, dir.beg), | 2869 target_to_host (hostdir, sizeof hostdir, dir.beg), |
2865 fmtres.range.min); | 2870 fmtres.range.min); |
2866 else | 2871 else |
2867 { | 2872 warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (), |
2868 const char *fmtstr | 2873 minunder4k |
2869 = (minunder4k | 2874 ? G_("%<%.*s%> directive output between %wu and %wu " |
2870 ? G_("%<%.*s%> directive output between %wu and %wu " | 2875 "bytes may exceed minimum required size of " |
2871 "bytes may exceed minimum required size of 4095") | 2876 "4095") |
2872 : G_("%<%.*s%> directive output between %wu and %wu " | 2877 : G_("%<%.*s%> directive output between %wu and %wu " |
2873 "bytes exceeds minimum required size of 4095")); | 2878 "bytes exceeds minimum required size of 4095"), |
2874 | 2879 dirlen, |
2875 warned = fmtwarn (dirloc, argloc, NULL, | 2880 target_to_host (hostdir, sizeof hostdir, dir.beg), |
2876 info.warnopt (), fmtstr, dirlen, | 2881 fmtres.range.min, fmtres.range.max); |
2877 target_to_host (hostdir, sizeof hostdir, dir.beg), | |
2878 fmtres.range.min, fmtres.range.max); | |
2879 } | |
2880 } | 2882 } |
2881 | 2883 |
2882 /* Has the likely and maximum directive output exceeded INT_MAX? */ | 2884 /* Has the likely and maximum directive output exceeded INT_MAX? */ |
2883 bool likelyximax = *dir.beg && res->range.likely > target_int_max (); | 2885 bool likelyximax = *dir.beg && res->range.likely > target_int_max (); |
2884 /* Don't consider the maximum to be in excess when it's the result | 2886 /* Don't consider the maximum to be in excess when it's the result |
2890 | 2892 |
2891 if (!warned | 2893 if (!warned |
2892 /* Warn for the likely output size at level 1. */ | 2894 /* Warn for the likely output size at level 1. */ |
2893 && (likelyximax | 2895 && (likelyximax |
2894 /* But only warn for the maximum at level 2. */ | 2896 /* But only warn for the maximum at level 2. */ |
2895 || (1 < warn_level | 2897 || (warn_level > 1 |
2896 && maxximax | 2898 && maxximax |
2897 && fmtres.range.max < HOST_WIDE_INT_MAX))) | 2899 && fmtres.range.max < HOST_WIDE_INT_MAX))) |
2898 { | 2900 { |
2899 /* The directive output causes the total length of output | 2901 /* The directive output causes the total length of output |
2900 to exceed INT_MAX bytes. */ | 2902 to exceed INT_MAX bytes. */ |
2901 | 2903 |
2902 if (fmtres.range.min == fmtres.range.max) | 2904 if (fmtres.range.min == fmtres.range.max) |
2903 warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (), | 2905 warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (), |
2904 "%<%.*s%> directive output of %wu bytes causes " | 2906 "%<%.*s%> directive output of %wu bytes causes " |
2905 "result to exceed %<INT_MAX%>", | 2907 "result to exceed %<INT_MAX%>", dirlen, |
2906 dirlen, | |
2907 target_to_host (hostdir, sizeof hostdir, dir.beg), | 2908 target_to_host (hostdir, sizeof hostdir, dir.beg), |
2908 fmtres.range.min); | 2909 fmtres.range.min); |
2909 else | 2910 else |
2910 { | 2911 warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (), |
2911 const char *fmtstr | 2912 fmtres.range.min > target_int_max () |
2912 = (fmtres.range.min > target_int_max () | 2913 ? G_("%<%.*s%> directive output between %wu and " |
2913 ? G_ ("%<%.*s%> directive output between %wu and %wu " | 2914 "%wu bytes causes result to exceed " |
2914 "bytes causes result to exceed %<INT_MAX%>") | 2915 "%<INT_MAX%>") |
2915 : G_ ("%<%.*s%> directive output between %wu and %wu " | 2916 : G_("%<%.*s%> directive output between %wu and " |
2916 "bytes may cause result to exceed %<INT_MAX%>")); | 2917 "%wu bytes may cause result to exceed " |
2917 warned = fmtwarn (dirloc, argloc, NULL, | 2918 "%<INT_MAX%>"), dirlen, |
2918 info.warnopt (), fmtstr, dirlen, | 2919 target_to_host (hostdir, sizeof hostdir, dir.beg), |
2919 target_to_host (hostdir, sizeof hostdir, dir.beg), | 2920 fmtres.range.min, fmtres.range.max); |
2920 fmtres.range.min, fmtres.range.max); | 2921 } |
2921 } | 2922 |
2923 if (!warned && fmtres.nonstr) | |
2924 { | |
2925 warned = fmtwarn (dirloc, argloc, NULL, info.warnopt (), | |
2926 "%<%.*s%> directive argument is not a nul-terminated " | |
2927 "string", | |
2928 dirlen, | |
2929 target_to_host (hostdir, sizeof hostdir, dir.beg)); | |
2930 if (warned && DECL_P (fmtres.nonstr)) | |
2931 inform (DECL_SOURCE_LOCATION (fmtres.nonstr), | |
2932 "referenced argument declared here"); | |
2933 return false; | |
2922 } | 2934 } |
2923 | 2935 |
2924 if (warned && fmtres.range.min < fmtres.range.likely | 2936 if (warned && fmtres.range.min < fmtres.range.likely |
2925 && fmtres.range.likely < fmtres.range.max) | 2937 && fmtres.range.likely < fmtres.range.max) |
2926 { | 2938 inform_n (info.fmtloc, fmtres.range.likely, |
2927 inform (info.fmtloc, | 2939 "assuming directive output of %wu byte", |
2928 (1 == fmtres.range.likely | 2940 "assuming directive output of %wu bytes", |
2929 ? G_("assuming directive output of %wu byte") | |
2930 : G_("assuming directive output of %wu bytes")), | |
2931 fmtres.range.likely); | 2941 fmtres.range.likely); |
2932 } | |
2933 | 2942 |
2934 if (warned && fmtres.argmin) | 2943 if (warned && fmtres.argmin) |
2935 { | 2944 { |
2936 if (fmtres.argmin == fmtres.argmax) | 2945 if (fmtres.argmin == fmtres.argmax) |
2937 inform (info.fmtloc, "directive argument %qE", fmtres.argmin); | 2946 inform (info.fmtloc, "directive argument %qE", fmtres.argmin); |
2979 info.func, min, info.objsize); | 2988 info.func, min, info.objsize); |
2980 } | 2989 } |
2981 | 2990 |
2982 if (dump_file && *dir.beg) | 2991 if (dump_file && *dir.beg) |
2983 { | 2992 { |
2984 fprintf (dump_file, " Result: %lli, %lli, %lli, %lli " | 2993 fprintf (dump_file, |
2985 "(%lli, %lli, %lli, %lli)\n", | 2994 " Result: " |
2986 (long long)fmtres.range.min, | 2995 HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC ", " |
2987 (long long)fmtres.range.likely, | 2996 HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC " (" |
2988 (long long)fmtres.range.max, | 2997 HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC ", " |
2989 (long long)fmtres.range.unlikely, | 2998 HOST_WIDE_INT_PRINT_DEC ", " HOST_WIDE_INT_PRINT_DEC ")\n", |
2990 (long long)res->range.min, | 2999 fmtres.range.min, fmtres.range.likely, |
2991 (long long)res->range.likely, | 3000 fmtres.range.max, fmtres.range.unlikely, |
2992 (long long)res->range.max, | 3001 res->range.min, res->range.likely, |
2993 (long long)res->range.unlikely); | 3002 res->range.max, res->range.unlikely); |
2994 } | 3003 } |
2995 | 3004 |
2996 return true; | 3005 return true; |
2997 } | 3006 } |
2998 | |
2999 #pragma GCC diagnostic pop | |
3000 | 3007 |
3001 /* Parse a format directive in function call described by INFO starting | 3008 /* Parse a format directive in function call described by INFO starting |
3002 at STR and populate DIR structure. Bump up *ARGNO by the number of | 3009 at STR and populate DIR structure. Bump up *ARGNO by the number of |
3003 arguments extracted for the directive. Return the length of | 3010 arguments extracted for the directive. Return the length of |
3004 the directive. */ | 3011 the directive. */ |
3005 | 3012 |
3006 static size_t | 3013 static size_t |
3007 parse_directive (pass_sprintf_length::call_info &info, | 3014 parse_directive (sprintf_dom_walker::call_info &info, |
3008 directive &dir, format_result *res, | 3015 directive &dir, format_result *res, |
3009 const char *str, unsigned *argno) | 3016 const char *str, unsigned *argno, |
3017 vr_values *vr_values) | |
3010 { | 3018 { |
3011 const char *pcnt = strchr (str, target_percent); | 3019 const char *pcnt = strchr (str, target_percent); |
3012 dir.beg = str; | 3020 dir.beg = str; |
3013 | 3021 |
3014 if (size_t len = pcnt ? pcnt - str : *str ? strlen (str) : 1) | 3022 if (size_t len = pcnt ? pcnt - str : *str ? strlen (str) : 1) |
3019 dir.len = len; | 3027 dir.len = len; |
3020 dir.fmtfunc = format_plain; | 3028 dir.fmtfunc = format_plain; |
3021 | 3029 |
3022 if (dump_file) | 3030 if (dump_file) |
3023 { | 3031 { |
3024 fprintf (dump_file, " Directive %u at offset %llu: \"%.*s\", " | 3032 fprintf (dump_file, " Directive %u at offset " |
3025 "length = %llu\n", | 3033 HOST_WIDE_INT_PRINT_UNSIGNED ": \"%.*s\", " |
3034 "length = " HOST_WIDE_INT_PRINT_UNSIGNED "\n", | |
3026 dir.dirno, | 3035 dir.dirno, |
3027 (unsigned long long)(size_t)(dir.beg - info.fmtstr), | 3036 (unsigned HOST_WIDE_INT)(size_t)(dir.beg - info.fmtstr), |
3028 (int)dir.len, dir.beg, (unsigned long long)dir.len); | 3037 (int)dir.len, dir.beg, (unsigned HOST_WIDE_INT) dir.len); |
3029 } | 3038 } |
3030 | 3039 |
3031 return len - !*str; | 3040 return len - !*str; |
3032 } | 3041 } |
3033 | 3042 |
3295 any buffer. */ | 3304 any buffer. */ |
3296 info.nowrite = false; | 3305 info.nowrite = false; |
3297 dir.fmtfunc = format_none; | 3306 dir.fmtfunc = format_none; |
3298 break; | 3307 break; |
3299 | 3308 |
3309 case 'C': | |
3300 case 'c': | 3310 case 'c': |
3311 /* POSIX wide character and C/POSIX narrow character. */ | |
3301 dir.fmtfunc = format_character; | 3312 dir.fmtfunc = format_character; |
3302 break; | 3313 break; |
3303 | 3314 |
3304 case 'S': | 3315 case 'S': |
3305 case 's': | 3316 case 's': |
3317 /* POSIX wide string and C/POSIX narrow character string. */ | |
3306 dir.fmtfunc = format_string; | 3318 dir.fmtfunc = format_string; |
3307 break; | 3319 break; |
3308 | 3320 |
3309 default: | 3321 default: |
3310 /* Unknown conversion specification. */ | 3322 /* Unknown conversion specification. */ |
3321 char hostdir[32]; | 3333 char hostdir[32]; |
3322 | 3334 |
3323 if (star_width) | 3335 if (star_width) |
3324 { | 3336 { |
3325 if (INTEGRAL_TYPE_P (TREE_TYPE (star_width))) | 3337 if (INTEGRAL_TYPE_P (TREE_TYPE (star_width))) |
3326 dir.set_width (star_width); | 3338 dir.set_width (star_width, vr_values); |
3327 else | 3339 else |
3328 { | 3340 { |
3329 /* Width specified by a va_list takes on the range [0, -INT_MIN] | 3341 /* Width specified by a va_list takes on the range [0, -INT_MIN] |
3330 (width is the absolute value of that specified). */ | 3342 (width is the absolute value of that specified). */ |
3331 dir.width[0] = 0; | 3343 dir.width[0] = 0; |
3343 /* Create a location for the width part of the directive, | 3355 /* Create a location for the width part of the directive, |
3344 pointing the caret at the first out-of-range digit. */ | 3356 pointing the caret at the first out-of-range digit. */ |
3345 substring_loc dirloc (info.fmtloc, TREE_TYPE (info.format), | 3357 substring_loc dirloc (info.fmtloc, TREE_TYPE (info.format), |
3346 caret, begin, end); | 3358 caret, begin, end); |
3347 | 3359 |
3348 fmtwarn (dirloc, UNKNOWN_LOCATION, NULL, | 3360 fmtwarn (dirloc, UNKNOWN_LOCATION, NULL, info.warnopt (), |
3349 info.warnopt (), "%<%.*s%> directive width out of range", | 3361 "%<%.*s%> directive width out of range", (int) dir.len, |
3350 dir.len, target_to_host (hostdir, sizeof hostdir, dir.beg)); | 3362 target_to_host (hostdir, sizeof hostdir, dir.beg)); |
3351 } | 3363 } |
3352 | 3364 |
3353 dir.set_width (width); | 3365 dir.set_width (width); |
3354 } | 3366 } |
3355 | 3367 |
3356 if (star_precision) | 3368 if (star_precision) |
3357 { | 3369 { |
3358 if (INTEGRAL_TYPE_P (TREE_TYPE (star_precision))) | 3370 if (INTEGRAL_TYPE_P (TREE_TYPE (star_precision))) |
3359 dir.set_precision (star_precision); | 3371 dir.set_precision (star_precision, vr_values); |
3360 else | 3372 else |
3361 { | 3373 { |
3362 /* Precision specified by a va_list takes on the range [-1, INT_MAX] | 3374 /* Precision specified by a va_list takes on the range [-1, INT_MAX] |
3363 (unlike width, negative precision is ignored). */ | 3375 (unlike width, negative precision is ignored). */ |
3364 dir.prec[0] = -1; | 3376 dir.prec[0] = -1; |
3377 including the leading period, pointing the caret at the first | 3389 including the leading period, pointing the caret at the first |
3378 out-of-range digit . */ | 3390 out-of-range digit . */ |
3379 substring_loc dirloc (info.fmtloc, TREE_TYPE (info.format), | 3391 substring_loc dirloc (info.fmtloc, TREE_TYPE (info.format), |
3380 caret, begin, end); | 3392 caret, begin, end); |
3381 | 3393 |
3382 fmtwarn (dirloc, UNKNOWN_LOCATION, NULL, | 3394 fmtwarn (dirloc, UNKNOWN_LOCATION, NULL, info.warnopt (), |
3383 info.warnopt (), "%<%.*s%> directive precision out of range", | 3395 "%<%.*s%> directive precision out of range", (int) dir.len, |
3384 dir.len, target_to_host (hostdir, sizeof hostdir, dir.beg)); | 3396 target_to_host (hostdir, sizeof hostdir, dir.beg)); |
3385 } | 3397 } |
3386 | 3398 |
3387 dir.set_precision (precision); | 3399 dir.set_precision (precision); |
3388 } | 3400 } |
3389 | 3401 |
3395 && *argno < gimple_call_num_args (info.callstmt)) | 3407 && *argno < gimple_call_num_args (info.callstmt)) |
3396 dir.arg = gimple_call_arg (info.callstmt, dollar ? dollar : (*argno)++); | 3408 dir.arg = gimple_call_arg (info.callstmt, dollar ? dollar : (*argno)++); |
3397 | 3409 |
3398 if (dump_file) | 3410 if (dump_file) |
3399 { | 3411 { |
3400 fprintf (dump_file, " Directive %u at offset %llu: \"%.*s\"", | 3412 fprintf (dump_file, |
3401 dir.dirno, (unsigned long long)(size_t)(dir.beg - info.fmtstr), | 3413 " Directive %u at offset " HOST_WIDE_INT_PRINT_UNSIGNED |
3414 ": \"%.*s\"", | |
3415 dir.dirno, | |
3416 (unsigned HOST_WIDE_INT)(size_t)(dir.beg - info.fmtstr), | |
3402 (int)dir.len, dir.beg); | 3417 (int)dir.len, dir.beg); |
3403 if (star_width) | 3418 if (star_width) |
3404 { | 3419 { |
3405 if (dir.width[0] == dir.width[1]) | 3420 if (dir.width[0] == dir.width[1]) |
3406 fprintf (dump_file, ", width = %lli", (long long)dir.width[0]); | 3421 fprintf (dump_file, ", width = " HOST_WIDE_INT_PRINT_DEC, |
3422 dir.width[0]); | |
3407 else | 3423 else |
3408 fprintf (dump_file, ", width in range [%lli, %lli]", | 3424 fprintf (dump_file, |
3409 (long long)dir.width[0], (long long)dir.width[1]); | 3425 ", width in range [" HOST_WIDE_INT_PRINT_DEC |
3426 ", " HOST_WIDE_INT_PRINT_DEC "]", | |
3427 dir.width[0], dir.width[1]); | |
3410 } | 3428 } |
3411 | 3429 |
3412 if (star_precision) | 3430 if (star_precision) |
3413 { | 3431 { |
3414 if (dir.prec[0] == dir.prec[1]) | 3432 if (dir.prec[0] == dir.prec[1]) |
3415 fprintf (dump_file, ", precision = %lli", (long long)dir.prec[0]); | 3433 fprintf (dump_file, ", precision = " HOST_WIDE_INT_PRINT_DEC, |
3434 dir.prec[0]); | |
3416 else | 3435 else |
3417 fprintf (dump_file, ", precision in range [%lli, %lli]", | 3436 fprintf (dump_file, |
3418 (long long)dir.prec[0], (long long)dir.prec[1]); | 3437 ", precision in range [" HOST_WIDE_INT_PRINT_DEC |
3438 HOST_WIDE_INT_PRINT_DEC "]", | |
3439 dir.prec[0], dir.prec[1]); | |
3419 } | 3440 } |
3420 fputc ('\n', dump_file); | 3441 fputc ('\n', dump_file); |
3421 } | 3442 } |
3422 | 3443 |
3423 return dir.len; | 3444 return dir.len; |
3429 if the complete format string has been processed and *RES can be relied | 3450 if the complete format string has been processed and *RES can be relied |
3430 on, false otherwise (e.g., when a unknown or unhandled directive was seen | 3451 on, false otherwise (e.g., when a unknown or unhandled directive was seen |
3431 that caused the processing to be terminated early). */ | 3452 that caused the processing to be terminated early). */ |
3432 | 3453 |
3433 bool | 3454 bool |
3434 pass_sprintf_length::compute_format_length (call_info &info, | 3455 sprintf_dom_walker::compute_format_length (call_info &info, |
3435 format_result *res) | 3456 format_result *res) |
3436 { | 3457 { |
3437 if (dump_file) | 3458 if (dump_file) |
3438 { | 3459 { |
3439 location_t callloc = gimple_location (info.callstmt); | 3460 location_t callloc = gimple_location (info.callstmt); |
3440 fprintf (dump_file, "%s:%i: ", | 3461 fprintf (dump_file, "%s:%i: ", |
3441 LOCATION_FILE (callloc), LOCATION_LINE (callloc)); | 3462 LOCATION_FILE (callloc), LOCATION_LINE (callloc)); |
3442 print_generic_expr (dump_file, info.func, dump_flags); | 3463 print_generic_expr (dump_file, info.func, dump_flags); |
3443 | 3464 |
3444 fprintf (dump_file, ": objsize = %llu, fmtstr = \"%s\"\n", | 3465 fprintf (dump_file, |
3445 (unsigned long long)info.objsize, info.fmtstr); | 3466 ": objsize = " HOST_WIDE_INT_PRINT_UNSIGNED |
3467 ", fmtstr = \"%s\"\n", | |
3468 info.objsize, info.fmtstr); | |
3446 } | 3469 } |
3447 | 3470 |
3448 /* Reset the minimum and maximum byte counters. */ | 3471 /* Reset the minimum and maximum byte counters. */ |
3449 res->range.min = res->range.max = 0; | 3472 res->range.min = res->range.max = 0; |
3450 | 3473 |
3451 /* No directive has been seen yet so the length of output is bounded | 3474 /* No directive has been seen yet so the length of output is bounded |
3452 by the known range [0, 0] (with no conversion producing more than | 3475 by the known range [0, 0] (with no conversion resulting in a failure |
3453 4K bytes) until determined otherwise. */ | 3476 or producing more than 4K bytes) until determined otherwise. */ |
3454 res->knownrange = true; | 3477 res->knownrange = true; |
3455 res->under4k = true; | 3478 res->posunder4k = true; |
3456 res->floating = false; | 3479 res->floating = false; |
3457 res->warned = false; | 3480 res->warned = false; |
3458 | 3481 |
3459 /* 1-based directive counter. */ | 3482 /* 1-based directive counter. */ |
3460 unsigned dirno = 1; | 3483 unsigned dirno = 1; |
3465 for (const char *pf = info.fmtstr; ; ++dirno) | 3488 for (const char *pf = info.fmtstr; ; ++dirno) |
3466 { | 3489 { |
3467 directive dir = directive (); | 3490 directive dir = directive (); |
3468 dir.dirno = dirno; | 3491 dir.dirno = dirno; |
3469 | 3492 |
3470 size_t n = parse_directive (info, dir, res, pf, &argno); | 3493 size_t n = parse_directive (info, dir, res, pf, &argno, |
3494 evrp_range_analyzer.get_vr_values ()); | |
3471 | 3495 |
3472 /* Return failure if the format function fails. */ | 3496 /* Return failure if the format function fails. */ |
3473 if (!format_directive (info, res, dir)) | 3497 if (!format_directive (info, res, dir, |
3498 evrp_range_analyzer.get_vr_values ())) | |
3474 return false; | 3499 return false; |
3475 | 3500 |
3476 /* Return success the directive is zero bytes long and it's | 3501 /* Return success the directive is zero bytes long and it's |
3477 the last think in the format string (i.e., it's the terminating | 3502 the last think in the format string (i.e., it's the terminating |
3478 nul, which isn't really a directive but handling it as one makes | 3503 nul, which isn't really a directive but handling it as one makes |
3512 /* Return true if the call described by INFO with result RES safe to | 3537 /* Return true if the call described by INFO with result RES safe to |
3513 optimize (i.e., no undefined behavior), and set RETVAL to the range | 3538 optimize (i.e., no undefined behavior), and set RETVAL to the range |
3514 of its return values. */ | 3539 of its return values. */ |
3515 | 3540 |
3516 static bool | 3541 static bool |
3517 is_call_safe (const pass_sprintf_length::call_info &info, | 3542 is_call_safe (const sprintf_dom_walker::call_info &info, |
3518 const format_result &res, bool under4k, | 3543 const format_result &res, bool under4k, |
3519 unsigned HOST_WIDE_INT retval[2]) | 3544 unsigned HOST_WIDE_INT retval[2]) |
3520 { | 3545 { |
3521 if (under4k && !res.under4k) | 3546 if (under4k && !res.posunder4k) |
3522 return false; | 3547 return false; |
3523 | 3548 |
3524 /* The minimum return value. */ | 3549 /* The minimum return value. */ |
3525 retval[0] = res.range.min; | 3550 retval[0] = res.range.min; |
3526 | 3551 |
3571 Return true if the call is removed and gsi_next should not be performed | 3596 Return true if the call is removed and gsi_next should not be performed |
3572 in the caller. */ | 3597 in the caller. */ |
3573 | 3598 |
3574 static bool | 3599 static bool |
3575 try_substitute_return_value (gimple_stmt_iterator *gsi, | 3600 try_substitute_return_value (gimple_stmt_iterator *gsi, |
3576 const pass_sprintf_length::call_info &info, | 3601 const sprintf_dom_walker::call_info &info, |
3577 const format_result &res) | 3602 const format_result &res) |
3578 { | 3603 { |
3579 tree lhs = gimple_get_lhs (info.callstmt); | 3604 tree lhs = gimple_get_lhs (info.callstmt); |
3580 | 3605 |
3581 /* Set to true when the entire call has been removed. */ | 3606 /* Set to true when the entire call has been removed. */ |
3666 : "out-of"); | 3691 : "out-of"); |
3667 | 3692 |
3668 const char *what = setrange ? "Setting" : "Discarding"; | 3693 const char *what = setrange ? "Setting" : "Discarding"; |
3669 if (retval[0] != retval[1]) | 3694 if (retval[0] != retval[1]) |
3670 fprintf (dump_file, | 3695 fprintf (dump_file, |
3671 " %s %s-bounds return value range [%llu, %llu].\n", | 3696 " %s %s-bounds return value range [" |
3672 what, inbounds, | 3697 HOST_WIDE_INT_PRINT_UNSIGNED ", " |
3673 (unsigned long long)retval[0], | 3698 HOST_WIDE_INT_PRINT_UNSIGNED "].\n", |
3674 (unsigned long long)retval[1]); | 3699 what, inbounds, retval[0], retval[1]); |
3675 else | 3700 else |
3676 fprintf (dump_file, " %s %s-bounds return value %llu.\n", | 3701 fprintf (dump_file, " %s %s-bounds return value " |
3677 what, inbounds, (unsigned long long)retval[0]); | 3702 HOST_WIDE_INT_PRINT_UNSIGNED ".\n", |
3703 what, inbounds, retval[0]); | |
3678 } | 3704 } |
3679 } | 3705 } |
3680 | 3706 |
3681 if (dump_file) | 3707 if (dump_file) |
3682 fputc ('\n', dump_file); | 3708 fputc ('\n', dump_file); |
3688 RES by replacing it with a simpler and presumably more efficient | 3714 RES by replacing it with a simpler and presumably more efficient |
3689 call (such as strcpy). */ | 3715 call (such as strcpy). */ |
3690 | 3716 |
3691 static bool | 3717 static bool |
3692 try_simplify_call (gimple_stmt_iterator *gsi, | 3718 try_simplify_call (gimple_stmt_iterator *gsi, |
3693 const pass_sprintf_length::call_info &info, | 3719 const sprintf_dom_walker::call_info &info, |
3694 const format_result &res) | 3720 const format_result &res) |
3695 { | 3721 { |
3696 unsigned HOST_WIDE_INT dummy[2]; | 3722 unsigned HOST_WIDE_INT dummy[2]; |
3697 if (!is_call_safe (info, res, info.retval_used (), dummy)) | 3723 if (!is_call_safe (info, res, info.retval_used (), dummy)) |
3698 return false; | 3724 return false; |
3715 /* Determine if a GIMPLE CALL is to one of the sprintf-like built-in | 3741 /* Determine if a GIMPLE CALL is to one of the sprintf-like built-in |
3716 functions and if so, handle it. Return true if the call is removed | 3742 functions and if so, handle it. Return true if the call is removed |
3717 and gsi_next should not be performed in the caller. */ | 3743 and gsi_next should not be performed in the caller. */ |
3718 | 3744 |
3719 bool | 3745 bool |
3720 pass_sprintf_length::handle_gimple_call (gimple_stmt_iterator *gsi) | 3746 sprintf_dom_walker::handle_gimple_call (gimple_stmt_iterator *gsi) |
3721 { | 3747 { |
3722 call_info info = call_info (); | 3748 call_info info = call_info (); |
3723 | 3749 |
3724 info.callstmt = gsi_stmt (*gsi); | 3750 info.callstmt = gsi_stmt (*gsi); |
3725 if (!gimple_call_builtin_p (info.callstmt, BUILT_IN_NORMAL)) | 3751 if (!gimple_call_builtin_p (info.callstmt, BUILT_IN_NORMAL)) |
3869 else if (TREE_CODE (size) == SSA_NAME) | 3895 else if (TREE_CODE (size) == SSA_NAME) |
3870 { | 3896 { |
3871 /* Try to determine the range of values of the argument | 3897 /* Try to determine the range of values of the argument |
3872 and use the greater of the two at level 1 and the smaller | 3898 and use the greater of the two at level 1 and the smaller |
3873 of them at level 2. */ | 3899 of them at level 2. */ |
3874 wide_int min, max; | 3900 value_range *vr = evrp_range_analyzer.get_value_range (size); |
3875 enum value_range_type range_type | 3901 if (range_int_cst_p (vr)) |
3876 = get_range_info (size, &min, &max); | 3902 dstsize = (warn_level < 2 |
3877 if (range_type == VR_RANGE) | 3903 ? TREE_INT_CST_LOW (vr->max ()) |
3878 { | 3904 : TREE_INT_CST_LOW (vr->min ())); |
3879 dstsize | |
3880 = (warn_level < 2 | |
3881 ? wi::fits_uhwi_p (max) ? max.to_uhwi () : max.to_shwi () | |
3882 : wi::fits_uhwi_p (min) ? min.to_uhwi () : min.to_shwi ()); | |
3883 } | |
3884 | 3905 |
3885 /* The destination size is not constant. If the function is | 3906 /* The destination size is not constant. If the function is |
3886 bounded (e.g., snprintf) a lower bound of zero doesn't | 3907 bounded (e.g., snprintf) a lower bound of zero doesn't |
3887 necessarily imply it can be eliminated. */ | 3908 necessarily imply it can be eliminated. */ |
3888 dstsize_cst_p = false; | 3909 dstsize_cst_p = false; |
3956 /* The result is the number of bytes output by the formatted function, | 3977 /* The result is the number of bytes output by the formatted function, |
3957 including the terminating NUL. */ | 3978 including the terminating NUL. */ |
3958 format_result res = format_result (); | 3979 format_result res = format_result (); |
3959 | 3980 |
3960 bool success = compute_format_length (info, &res); | 3981 bool success = compute_format_length (info, &res); |
3982 if (res.warned) | |
3983 gimple_set_no_warning (info.callstmt, true); | |
3961 | 3984 |
3962 /* When optimizing and the printf return value optimization is enabled, | 3985 /* When optimizing and the printf return value optimization is enabled, |
3963 attempt to substitute the computed result for the return value of | 3986 attempt to substitute the computed result for the return value of |
3964 the call. Avoid this optimization when -frounding-math is in effect | 3987 the call. Avoid this optimization when -frounding-math is in effect |
3965 and the format string contains a floating point directive. */ | 3988 and the format string contains a floating point directive. */ |
3980 } | 4003 } |
3981 | 4004 |
3982 return call_removed; | 4005 return call_removed; |
3983 } | 4006 } |
3984 | 4007 |
4008 edge | |
4009 sprintf_dom_walker::before_dom_children (basic_block bb) | |
4010 { | |
4011 evrp_range_analyzer.enter (bb); | |
4012 for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si); ) | |
4013 { | |
4014 /* Iterate over statements, looking for function calls. */ | |
4015 gimple *stmt = gsi_stmt (si); | |
4016 | |
4017 /* First record ranges generated by this statement. */ | |
4018 evrp_range_analyzer.record_ranges_from_stmt (stmt, false); | |
4019 | |
4020 if (is_gimple_call (stmt) && handle_gimple_call (&si)) | |
4021 /* If handle_gimple_call returns true, the iterator is | |
4022 already pointing to the next statement. */ | |
4023 continue; | |
4024 | |
4025 gsi_next (&si); | |
4026 } | |
4027 return NULL; | |
4028 } | |
4029 | |
4030 void | |
4031 sprintf_dom_walker::after_dom_children (basic_block bb) | |
4032 { | |
4033 evrp_range_analyzer.leave (bb); | |
4034 } | |
4035 | |
3985 /* Execute the pass for function FUN. */ | 4036 /* Execute the pass for function FUN. */ |
3986 | 4037 |
3987 unsigned int | 4038 unsigned int |
3988 pass_sprintf_length::execute (function *fun) | 4039 pass_sprintf_length::execute (function *fun) |
3989 { | 4040 { |
3990 init_target_to_host_charmap (); | 4041 init_target_to_host_charmap (); |
3991 | 4042 |
3992 basic_block bb; | 4043 calculate_dominance_info (CDI_DOMINATORS); |
3993 FOR_EACH_BB_FN (bb, fun) | 4044 |
3994 { | 4045 sprintf_dom_walker sprintf_dom_walker; |
3995 for (gimple_stmt_iterator si = gsi_start_bb (bb); !gsi_end_p (si); ) | 4046 sprintf_dom_walker.walk (ENTRY_BLOCK_PTR_FOR_FN (fun)); |
3996 { | |
3997 /* Iterate over statements, looking for function calls. */ | |
3998 gimple *stmt = gsi_stmt (si); | |
3999 | |
4000 if (is_gimple_call (stmt) && handle_gimple_call (&si)) | |
4001 /* If handle_gimple_call returns true, the iterator is | |
4002 already pointing to the next statement. */ | |
4003 continue; | |
4004 | |
4005 gsi_next (&si); | |
4006 } | |
4007 } | |
4008 | 4047 |
4009 /* Clean up object size info. */ | 4048 /* Clean up object size info. */ |
4010 fini_object_sizes (); | 4049 fini_object_sizes (); |
4011 | |
4012 return 0; | 4050 return 0; |
4013 } | 4051 } |
4014 | 4052 |
4015 } /* Unnamed namespace. */ | 4053 } /* Unnamed namespace. */ |
4016 | 4054 |