Mercurial > hg > CbC > CbC_gcc
comparison gcc/c-family/c-format.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 /* Check calls to formatted I/O functions (-Wformat). | 1 /* Check calls to formatted I/O functions (-Wformat). |
2 Copyright (C) 1992-2017 Free Software Foundation, Inc. | 2 Copyright (C) 1992-2018 Free Software Foundation, Inc. |
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 |
7 the terms of the GNU General Public License as published by the Free | 7 the terms of the GNU General Public License as published by the Free |
30 #include "langhooks.h" | 30 #include "langhooks.h" |
31 #include "c-format.h" | 31 #include "c-format.h" |
32 #include "diagnostic.h" | 32 #include "diagnostic.h" |
33 #include "substring-locations.h" | 33 #include "substring-locations.h" |
34 #include "selftest.h" | 34 #include "selftest.h" |
35 #include "selftest-diagnostic.h" | |
35 #include "builtins.h" | 36 #include "builtins.h" |
36 #include "attribs.h" | 37 #include "attribs.h" |
38 #include "gcc-rich-location.h" | |
37 | 39 |
38 /* Handle attributes associated with format checking. */ | 40 /* Handle attributes associated with format checking. */ |
39 | 41 |
40 /* This must be in the same order as format_types, except for | 42 /* This must be in the same order as format_types, except for |
41 format_type_error. Target-specific format types do not have | 43 format_type_error. Target-specific format types do not have |
42 matching enum values. */ | 44 matching enum values. */ |
43 enum format_type { printf_format_type, asm_fprintf_format_type, | 45 enum format_type { printf_format_type, asm_fprintf_format_type, |
44 gcc_diag_format_type, gcc_tdiag_format_type, | 46 gcc_diag_format_type, gcc_tdiag_format_type, |
45 gcc_cdiag_format_type, | 47 gcc_cdiag_format_type, |
46 gcc_cxxdiag_format_type, gcc_gfc_format_type, | 48 gcc_cxxdiag_format_type, gcc_gfc_format_type, |
49 gcc_dump_printf_format_type, | |
47 gcc_objc_string_format_type, | 50 gcc_objc_string_format_type, |
48 format_type_error = -1}; | 51 format_type_error = -1}; |
49 | 52 |
50 struct function_format_info | 53 struct function_format_info |
51 { | 54 { |
54 unsigned HOST_WIDE_INT first_arg_num; /* number of first arg (zero for varargs) */ | 57 unsigned HOST_WIDE_INT first_arg_num; /* number of first arg (zero for varargs) */ |
55 }; | 58 }; |
56 | 59 |
57 /* Initialized in init_dynamic_diag_info. */ | 60 /* Initialized in init_dynamic_diag_info. */ |
58 static GTY(()) tree local_tree_type_node; | 61 static GTY(()) tree local_tree_type_node; |
59 static GTY(()) tree local_gcall_ptr_node; | 62 static GTY(()) tree local_gimple_ptr_node; |
60 static GTY(()) tree locus; | 63 static GTY(()) tree locus; |
61 | 64 |
62 static bool decode_format_attr (tree, function_format_info *, int); | 65 static bool decode_format_attr (tree, function_format_info *, int); |
63 static int decode_format_type (const char *); | 66 static int decode_format_type (const char *); |
64 | 67 |
95 be emitted. Fix it. */ | 98 be emitted. Fix it. */ |
96 char_idx -= 1; | 99 char_idx -= 1; |
97 | 100 |
98 substring_loc fmt_loc (fmt_string_loc, string_type, char_idx, char_idx, | 101 substring_loc fmt_loc (fmt_string_loc, string_type, char_idx, char_idx, |
99 char_idx); | 102 char_idx); |
100 bool warned = format_warning_va (fmt_loc, UNKNOWN_LOCATION, NULL, opt, | 103 format_string_diagnostic_t diag (fmt_loc, NULL, UNKNOWN_LOCATION, NULL, |
101 gmsgid, &ap); | 104 NULL); |
105 bool warned = diag.emit_warning_va (opt, gmsgid, &ap); | |
102 va_end (ap); | 106 va_end (ap); |
103 | 107 |
104 return warned; | 108 return warned; |
105 } | 109 } |
106 | 110 |
459 | 463 |
460 /* The custom diagnostics all accept the same length specifiers. */ | 464 /* The custom diagnostics all accept the same length specifiers. */ |
461 #define gcc_tdiag_length_specs gcc_diag_length_specs | 465 #define gcc_tdiag_length_specs gcc_diag_length_specs |
462 #define gcc_cdiag_length_specs gcc_diag_length_specs | 466 #define gcc_cdiag_length_specs gcc_diag_length_specs |
463 #define gcc_cxxdiag_length_specs gcc_diag_length_specs | 467 #define gcc_cxxdiag_length_specs gcc_diag_length_specs |
468 #define gcc_dump_printf_length_specs gcc_diag_length_specs | |
464 | 469 |
465 /* This differs from printf_length_specs only in that "Z" is not accepted. */ | 470 /* This differs from printf_length_specs only in that "Z" is not accepted. */ |
466 static const format_length_info scanf_length_specs[] = | 471 static const format_length_info scanf_length_specs[] = |
467 { | 472 { |
468 { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99, 0 }, | 473 { "h", FMT_LEN_h, STD_C89, "hh", FMT_LEN_hh, STD_C99, 0 }, |
548 | 553 |
549 #define gcc_tdiag_flag_pairs gcc_diag_flag_pairs | 554 #define gcc_tdiag_flag_pairs gcc_diag_flag_pairs |
550 #define gcc_cdiag_flag_pairs gcc_diag_flag_pairs | 555 #define gcc_cdiag_flag_pairs gcc_diag_flag_pairs |
551 #define gcc_cxxdiag_flag_pairs gcc_diag_flag_pairs | 556 #define gcc_cxxdiag_flag_pairs gcc_diag_flag_pairs |
552 #define gcc_gfc_flag_pairs gcc_diag_flag_pairs | 557 #define gcc_gfc_flag_pairs gcc_diag_flag_pairs |
558 #define gcc_dump_printf_flag_pairs gcc_diag_flag_pairs | |
553 | 559 |
554 static const format_flag_spec gcc_diag_flag_specs[] = | 560 static const format_flag_spec gcc_diag_flag_specs[] = |
555 { | 561 { |
556 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89 }, | 562 { '+', 0, 0, 0, N_("'+' flag"), N_("the '+' printf flag"), STD_C89 }, |
557 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89 }, | 563 { '#', 0, 0, 0, N_("'#' flag"), N_("the '#' printf flag"), STD_C89 }, |
563 | 569 |
564 #define gcc_tdiag_flag_specs gcc_diag_flag_specs | 570 #define gcc_tdiag_flag_specs gcc_diag_flag_specs |
565 #define gcc_cdiag_flag_specs gcc_diag_flag_specs | 571 #define gcc_cdiag_flag_specs gcc_diag_flag_specs |
566 #define gcc_cxxdiag_flag_specs gcc_diag_flag_specs | 572 #define gcc_cxxdiag_flag_specs gcc_diag_flag_specs |
567 #define gcc_gfc_flag_specs gcc_diag_flag_specs | 573 #define gcc_gfc_flag_specs gcc_diag_flag_specs |
574 #define gcc_dump_printf_flag_specs gcc_diag_flag_specs | |
568 | 575 |
569 static const format_flag_spec scanf_flag_specs[] = | 576 static const format_flag_spec scanf_flag_specs[] = |
570 { | 577 { |
571 { '*', 0, 0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89 }, | 578 { '*', 0, 0, 0, N_("assignment suppression"), N_("the assignment suppression scanf feature"), STD_C89 }, |
572 { 'a', 0, 0, 0, N_("'a' flag"), N_("the 'a' scanf flag"), STD_EXT }, | 579 { 'a', 0, 0, 0, N_("'a' flag"), N_("the 'a' scanf flag"), STD_EXT }, |
677 { "z", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | 684 { "z", 0, STD_C89, NOARGUMENTS, "", "", NULL }, |
678 { "@", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | 685 { "@", 0, STD_C89, NOARGUMENTS, "", "", NULL }, |
679 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } | 686 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } |
680 }; | 687 }; |
681 | 688 |
689 /* GCC-specific format_char_info arrays. */ | |
690 | |
691 /* The conversion specifiers implemented within pp_format, and thus supported | |
692 by all pretty_printer instances within GCC. */ | |
693 | |
694 #define PP_FORMAT_CHAR_TABLE \ | |
695 { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \ | |
696 { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \ | |
697 { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \ | |
698 { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \ | |
699 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL }, \ | |
700 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, \ | |
701 { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "//cR", NULL }, \ | |
702 { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL }, \ | |
703 { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL }, \ | |
704 { "'" , 0, STD_C89, NOARGUMENTS, "", "", NULL }, \ | |
705 { "R", 0, STD_C89, NOARGUMENTS, "", "\\", NULL }, \ | |
706 { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, \ | |
707 { "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_diag_char_table[0] } | |
708 | |
682 static const format_char_info gcc_diag_char_table[] = | 709 static const format_char_info gcc_diag_char_table[] = |
683 { | 710 { |
684 /* C89 conversion specifiers. */ | 711 /* The conversion specifiers implemented within pp_format. */ |
685 { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | 712 PP_FORMAT_CHAR_TABLE, |
686 { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | 713 |
687 { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | |
688 { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | |
689 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL }, | |
690 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, | |
691 | |
692 /* Custom conversion specifiers. */ | |
693 | |
694 /* G requires a "gcall*" argument at runtime. */ | |
695 { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, | |
696 /* K requires a "tree" argument at runtime. */ | |
697 { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, | |
698 | |
699 { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "//cR", NULL }, | |
700 { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL }, | |
701 { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL }, | |
702 { "'" , 0, STD_C89, NOARGUMENTS, "", "", NULL }, | |
703 { "R", 0, STD_C89, NOARGUMENTS, "", "\\", NULL }, | |
704 { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, | |
705 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } | 714 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } |
706 }; | 715 }; |
707 | 716 |
708 static const format_char_info gcc_tdiag_char_table[] = | 717 static const format_char_info gcc_tdiag_char_table[] = |
709 { | 718 { |
710 /* C89 conversion specifiers. */ | 719 /* The conversion specifiers implemented within pp_format. */ |
711 { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | 720 PP_FORMAT_CHAR_TABLE, |
712 { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | 721 |
713 { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | 722 /* Custom conversion specifiers implemented by default_tree_printer. */ |
714 { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | |
715 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL }, | |
716 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, | |
717 | |
718 /* Custom conversion specifiers. */ | |
719 | 723 |
720 /* These will require a "tree" at runtime. */ | 724 /* These will require a "tree" at runtime. */ |
721 { "DFTV", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "'", NULL }, | 725 { "DFTV", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "'", NULL }, |
722 { "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL }, | 726 { "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL }, |
723 { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, | 727 { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, |
724 | 728 |
725 /* G requires a "gcall*" argument at runtime. */ | 729 /* G requires a "gimple*" argument at runtime. */ |
726 { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, | 730 { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, |
727 | 731 |
728 { "v", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL }, | |
729 | |
730 { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "/cR", NULL }, | |
731 { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL }, | |
732 { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL }, | |
733 { "'", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | |
734 { "R", 0, STD_C89, NOARGUMENTS, "", "\\", NULL }, | |
735 { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, | |
736 { "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_tdiag_char_table[0] }, | |
737 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } | 732 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } |
738 }; | 733 }; |
739 | 734 |
740 static const format_char_info gcc_cdiag_char_table[] = | 735 static const format_char_info gcc_cdiag_char_table[] = |
741 { | 736 { |
742 /* C89 conversion specifiers. */ | 737 /* The conversion specifiers implemented within pp_format. */ |
743 { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | 738 PP_FORMAT_CHAR_TABLE, |
744 { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | 739 |
745 { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | 740 /* Custom conversion specifiers implemented by c_tree_printer. */ |
746 { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | |
747 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL }, | |
748 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, | |
749 | |
750 /* Custom conversion specifiers. */ | |
751 | 741 |
752 /* These will require a "tree" at runtime. */ | 742 /* These will require a "tree" at runtime. */ |
753 { "DFTV", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "'", NULL }, | 743 { "DFTV", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "'", NULL }, |
754 { "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL }, | 744 { "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL }, |
755 { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, | 745 { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, |
756 | 746 |
757 /* G requires a "gcall*" argument at runtime. */ | 747 /* G requires a "gimple*" argument at runtime. */ |
758 { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, | 748 { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, |
759 | 749 |
760 { "v", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL }, | 750 { "v", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL }, |
761 | 751 |
762 { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "/cR", NULL }, | |
763 { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL }, | |
764 { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL }, | |
765 { "'", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | |
766 { "R", 0, STD_C89, NOARGUMENTS, "", "\\", NULL }, | |
767 { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, | |
768 { "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_tdiag_char_table[0] }, | |
769 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } | 752 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } |
770 }; | 753 }; |
771 | 754 |
772 static const format_char_info gcc_cxxdiag_char_table[] = | 755 static const format_char_info gcc_cxxdiag_char_table[] = |
773 { | 756 { |
774 /* C89 conversion specifiers. */ | 757 /* The conversion specifiers implemented within pp_format. */ |
775 { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | 758 PP_FORMAT_CHAR_TABLE, |
776 { "ox", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | 759 |
777 { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | 760 /* Custom conversion specifiers implemented by cp_printer. */ |
778 { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | |
779 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "pq", "cR", NULL }, | |
780 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, | |
781 | |
782 /* Custom conversion specifiers. */ | |
783 | 761 |
784 /* These will require a "tree" at runtime. */ | 762 /* These will require a "tree" at runtime. */ |
785 { "ADFHISTVX",1,STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "'", NULL }, | 763 { "ADFHISTVX",1,STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "'", NULL }, |
786 { "E", 1,STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL }, | 764 { "E", 1,STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL }, |
787 { "K", 1, STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, | 765 { "K", 1, STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, |
788 { "v", 0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL }, | 766 |
789 | 767 /* G requires a "gimple*" argument at runtime. */ |
790 /* G requires a "gcall*" argument at runtime. */ | |
791 { "G", 1, STD_C89,{ T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, | 768 { "G", 1, STD_C89,{ T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, |
792 | 769 |
793 /* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.) */ | 770 /* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.) */ |
794 { "CLOPQ",0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, | 771 { "CLOPQ",0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, |
795 | 772 |
796 { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "/cR", NULL }, | |
797 { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL }, | |
798 { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL }, | |
799 { "'", 0, STD_C89, NOARGUMENTS, "", "", NULL }, | |
800 { "R", 0, STD_C89, NOARGUMENTS, "", "\\", NULL }, | |
801 { "m", 0, STD_C89, NOARGUMENTS, "q", "", NULL }, | |
802 { "Z", 1, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "", &gcc_tdiag_char_table[0] }, | |
803 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } | 773 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } |
804 }; | 774 }; |
805 | 775 |
806 static const format_char_info gcc_gfc_char_table[] = | 776 static const format_char_info gcc_gfc_char_table[] = |
807 { | 777 { |
818 /* This will require a "locus" at runtime. */ | 788 /* This will require a "locus" at runtime. */ |
819 { "L", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "R", NULL }, | 789 { "L", 0, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "R", NULL }, |
820 | 790 |
821 /* These will require nothing. */ | 791 /* These will require nothing. */ |
822 { "<>",0, STD_C89, NOARGUMENTS, "", "", NULL }, | 792 { "<>",0, STD_C89, NOARGUMENTS, "", "", NULL }, |
793 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } | |
794 }; | |
795 | |
796 static const format_char_info gcc_dump_printf_char_table[] = | |
797 { | |
798 /* The conversion specifiers implemented within pp_format. */ | |
799 PP_FORMAT_CHAR_TABLE, | |
800 | |
801 /* Custom conversion specifiers implemented by dump_pretty_printer. */ | |
802 | |
803 /* E and G require a "gimple *" argument at runtime. */ | |
804 { "EG", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, | |
805 | |
806 /* T requires a "tree" at runtime. */ | |
807 { "T", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, | |
808 | |
823 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } | 809 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } |
824 }; | 810 }; |
825 | 811 |
826 static const format_char_info scan_char_table[] = | 812 static const format_char_info scan_char_table[] = |
827 { | 813 { |
920 gcc_gfc_flag_specs, gcc_gfc_flag_pairs, | 906 gcc_gfc_flag_specs, gcc_gfc_flag_pairs, |
921 FMT_FLAG_ARG_CONVERT, | 907 FMT_FLAG_ARG_CONVERT, |
922 0, 0, 0, 0, 0, 0, | 908 0, 0, 0, 0, 0, 0, |
923 NULL, NULL | 909 NULL, NULL |
924 }, | 910 }, |
911 { "gcc_dump_printf", gcc_dump_printf_length_specs, | |
912 gcc_dump_printf_char_table, "q+#", NULL, | |
913 gcc_dump_printf_flag_specs, gcc_dump_printf_flag_pairs, | |
914 FMT_FLAG_ARG_CONVERT, | |
915 0, 0, 'p', 0, 'L', 0, | |
916 NULL, &integer_type_node | |
917 }, | |
925 { "NSString", NULL, NULL, NULL, NULL, | 918 { "NSString", NULL, NULL, NULL, NULL, |
926 NULL, NULL, | 919 NULL, NULL, |
927 FMT_FLAG_ARG_CONVERT|FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL, 0, 0, 0, 0, 0, 0, | 920 FMT_FLAG_ARG_CONVERT|FMT_FLAG_PARSE_ARG_CONVERT_EXTERNAL, 0, 0, 0, 0, 0, 0, |
928 NULL, NULL | 921 NULL, NULL |
929 }, | 922 }, |
972 numbers. */ | 965 numbers. */ |
973 int number_dollar_extra_args; | 966 int number_dollar_extra_args; |
974 /* Number of leaves of the format argument that were wide string | 967 /* Number of leaves of the format argument that were wide string |
975 literals. */ | 968 literals. */ |
976 int number_wide; | 969 int number_wide; |
970 /* Number of leaves of the format argument that are not array of "char". */ | |
971 int number_non_char; | |
977 /* Number of leaves of the format argument that were empty strings. */ | 972 /* Number of leaves of the format argument that were empty strings. */ |
978 int number_empty; | 973 int number_empty; |
979 /* Number of leaves of the format argument that were unterminated | 974 /* Number of leaves of the format argument that were unterminated |
980 strings. */ | 975 strings. */ |
981 int number_unterminated; | 976 int number_unterminated; |
1108 | 1103 |
1109 /* Attempt to detect whether the current function might benefit | 1104 /* Attempt to detect whether the current function might benefit |
1110 from the format attribute if the called function is decorated | 1105 from the format attribute if the called function is decorated |
1111 with it. Avoid using calls with string literal formats for | 1106 with it. Avoid using calls with string literal formats for |
1112 guidance since those are unlikely to be viable candidates. */ | 1107 guidance since those are unlikely to be viable candidates. */ |
1113 if (warn_suggest_attribute_format && info.first_arg_num == 0 | 1108 if (warn_suggest_attribute_format |
1109 && current_function_decl != NULL_TREE | |
1110 && info.first_arg_num == 0 | |
1114 && (format_types[info.format_type].flags | 1111 && (format_types[info.format_type].flags |
1115 & (int) FMT_FLAG_ARG_CONVERT) | 1112 & (int) FMT_FLAG_ARG_CONVERT) |
1116 /* c_strlen will fail for a function parameter but succeed | 1113 /* c_strlen will fail for a function parameter but succeed |
1117 for a literal or constant array. */ | 1114 for a literal or constant array. */ |
1118 && !c_strlen (argarray[info.format_num - 1], 1)) | 1115 && !c_strlen (argarray[info.format_num - 1], 1)) |
1431 res.number_non_literal = 0; | 1428 res.number_non_literal = 0; |
1432 res.number_extra_args = 0; | 1429 res.number_extra_args = 0; |
1433 res.extra_arg_loc = UNKNOWN_LOCATION; | 1430 res.extra_arg_loc = UNKNOWN_LOCATION; |
1434 res.number_dollar_extra_args = 0; | 1431 res.number_dollar_extra_args = 0; |
1435 res.number_wide = 0; | 1432 res.number_wide = 0; |
1433 res.number_non_char = 0; | |
1436 res.number_empty = 0; | 1434 res.number_empty = 0; |
1437 res.number_unterminated = 0; | 1435 res.number_unterminated = 0; |
1438 res.number_other = 0; | 1436 res.number_other = 0; |
1439 res.format_string_loc = input_location; | 1437 res.format_string_loc = input_location; |
1440 | 1438 |
1507 format_types[info->format_type].name); | 1505 format_types[info->format_type].name); |
1508 | 1506 |
1509 if (res.number_wide > 0) | 1507 if (res.number_wide > 0) |
1510 warning_at (loc, OPT_Wformat_, "format is a wide character string"); | 1508 warning_at (loc, OPT_Wformat_, "format is a wide character string"); |
1511 | 1509 |
1510 if (res.number_non_char > 0) | |
1511 warning_at (loc, OPT_Wformat_, | |
1512 "format string is not an array of type %qs", "char"); | |
1513 | |
1512 if (res.number_unterminated > 0) | 1514 if (res.number_unterminated > 0) |
1513 warning_at (loc, OPT_Wformat_, "unterminated format string"); | 1515 warning_at (loc, OPT_Wformat_, "unterminated format string"); |
1514 } | 1516 } |
1515 | 1517 |
1516 /* Callback from check_function_arguments_recurse to check a | 1518 /* Callback from check_function_arguments_recurse to check a |
1534 tree array_size = 0; | 1536 tree array_size = 0; |
1535 tree array_init; | 1537 tree array_init; |
1536 | 1538 |
1537 location_t fmt_param_loc = EXPR_LOC_OR_LOC (format_tree, input_location); | 1539 location_t fmt_param_loc = EXPR_LOC_OR_LOC (format_tree, input_location); |
1538 | 1540 |
1539 if (VAR_P (format_tree)) | 1541 /* Pull out a constant value if the front end didn't, and handle location |
1540 { | 1542 wrappers. */ |
1541 /* Pull out a constant value if the front end didn't. */ | 1543 format_tree = fold_for_warn (format_tree); |
1542 format_tree = decl_constant_value (format_tree); | 1544 STRIP_NOPS (format_tree); |
1543 STRIP_NOPS (format_tree); | |
1544 } | |
1545 | 1545 |
1546 if (integer_zerop (format_tree)) | 1546 if (integer_zerop (format_tree)) |
1547 { | 1547 { |
1548 /* Skip to first argument to check, so we can see if this format | 1548 /* Skip to first argument to check, so we can see if this format |
1549 has any arguments (it shouldn't). */ | 1549 has any arguments (it shouldn't). */ |
1654 if (TREE_CODE (format_tree) != STRING_CST) | 1654 if (TREE_CODE (format_tree) != STRING_CST) |
1655 { | 1655 { |
1656 res->number_non_literal++; | 1656 res->number_non_literal++; |
1657 return; | 1657 return; |
1658 } | 1658 } |
1659 if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (format_tree))) != char_type_node) | 1659 tree underlying_type |
1660 { | 1660 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (format_tree))); |
1661 res->number_wide++; | 1661 if (underlying_type != char_type_node) |
1662 { | |
1663 if (underlying_type == char16_type_node | |
1664 || underlying_type == char32_type_node | |
1665 || underlying_type == wchar_type_node) | |
1666 res->number_wide++; | |
1667 else | |
1668 res->number_non_char++; | |
1662 return; | 1669 return; |
1663 } | 1670 } |
1664 format_chars = TREE_STRING_POINTER (format_tree); | 1671 format_chars = TREE_STRING_POINTER (format_tree); |
1665 format_length = TREE_STRING_LENGTH (format_tree); | 1672 format_length = TREE_STRING_LENGTH (format_tree); |
1666 if (array_size != 0) | 1673 if (array_size != 0) |
3497 if (start.column > finish.column) | 3504 if (start.column > finish.column) |
3498 return NULL; | 3505 return NULL; |
3499 if (caret.column > finish.column) | 3506 if (caret.column > finish.column) |
3500 return NULL; | 3507 return NULL; |
3501 | 3508 |
3502 int line_width; | 3509 char_span line = location_get_source_line (start.file, start.line); |
3503 const char *line = location_get_source_line (start.file, start.line, | 3510 if (!line) |
3504 &line_width); | |
3505 if (line == NULL) | |
3506 return NULL; | 3511 return NULL; |
3507 | 3512 |
3508 /* If we got this far, then we have the line containing the | 3513 /* If we got this far, then we have the line containing the |
3509 existing conversion specification. | 3514 existing conversion specification. |
3510 | 3515 |
3511 Generate a trimmed copy, containing the prefix part of the conversion | 3516 Generate a trimmed copy, containing the prefix part of the conversion |
3512 specification, up to the (but not including) the length modifier. | 3517 specification, up to the (but not including) the length modifier. |
3513 In the above example, this would be "%-+*.*". */ | 3518 In the above example, this would be "%-+*.*". */ |
3514 const char *current_content = line + start.column - 1; | |
3515 int length_up_to_type = caret.column - start.column; | 3519 int length_up_to_type = caret.column - start.column; |
3516 char *prefix = xstrndup (current_content, length_up_to_type); | 3520 char_span prefix_span = line.subspan (start.column - 1, length_up_to_type); |
3521 char *prefix = prefix_span.xstrdup (); | |
3517 | 3522 |
3518 /* Now attempt to generate a suggestion for the rest of the specification | 3523 /* Now attempt to generate a suggestion for the rest of the specification |
3519 (length modifier and conversion char), based on ARG_TYPE and | 3524 (length modifier and conversion char), based on ARG_TYPE and |
3520 CONVERSION_CHAR. | 3525 CONVERSION_CHAR. |
3521 In the above example, this would be "ld". */ | 3526 In the above example, this would be "ld". */ |
3532 char *result = concat (prefix, format_for_type, NULL); | 3537 char *result = concat (prefix, format_for_type, NULL); |
3533 free (format_for_type); | 3538 free (format_for_type); |
3534 free (prefix); | 3539 free (prefix); |
3535 return result; | 3540 return result; |
3536 } | 3541 } |
3542 | |
3543 /* Helper class for adding zero or more trailing '*' to types. | |
3544 | |
3545 The format type and name exclude any '*' for pointers, so those | |
3546 must be formatted manually. For all the types we currently have, | |
3547 this is adequate, but formats taking pointers to functions or | |
3548 arrays would require the full type to be built up in order to | |
3549 print it with %T. */ | |
3550 | |
3551 class indirection_suffix | |
3552 { | |
3553 public: | |
3554 indirection_suffix (int pointer_count) : m_pointer_count (pointer_count) {} | |
3555 | |
3556 /* Determine the size of the buffer (including NUL-terminator). */ | |
3557 | |
3558 size_t get_buffer_size () const | |
3559 { | |
3560 return m_pointer_count + 2; | |
3561 } | |
3562 | |
3563 /* Write the '*' to DST and add a NUL-terminator. */ | |
3564 | |
3565 void fill_buffer (char *dst) const | |
3566 { | |
3567 if (m_pointer_count == 0) | |
3568 dst[0] = 0; | |
3569 else if (c_dialect_cxx ()) | |
3570 { | |
3571 memset (dst, '*', m_pointer_count); | |
3572 dst[m_pointer_count] = 0; | |
3573 } | |
3574 else | |
3575 { | |
3576 dst[0] = ' '; | |
3577 memset (dst + 1, '*', m_pointer_count); | |
3578 dst[m_pointer_count + 1] = 0; | |
3579 } | |
3580 } | |
3581 | |
3582 private: | |
3583 int m_pointer_count; | |
3584 }; | |
3585 | |
3586 /* Subclass of range_label for labelling the range in the format string | |
3587 with the type in question, adding trailing '*' for pointer_count. */ | |
3588 | |
3589 class range_label_for_format_type_mismatch | |
3590 : public range_label_for_type_mismatch | |
3591 { | |
3592 public: | |
3593 range_label_for_format_type_mismatch (tree labelled_type, tree other_type, | |
3594 int pointer_count) | |
3595 : range_label_for_type_mismatch (labelled_type, other_type), | |
3596 m_pointer_count (pointer_count) | |
3597 { | |
3598 } | |
3599 | |
3600 label_text get_text (unsigned range_idx) const FINAL OVERRIDE | |
3601 { | |
3602 label_text text = range_label_for_type_mismatch::get_text (range_idx); | |
3603 if (text.m_buffer == NULL) | |
3604 return text; | |
3605 | |
3606 indirection_suffix suffix (m_pointer_count); | |
3607 char *p = (char *) alloca (suffix.get_buffer_size ()); | |
3608 suffix.fill_buffer (p); | |
3609 | |
3610 char *result = concat (text.m_buffer, p, NULL); | |
3611 text.maybe_free (); | |
3612 return label_text (result, true); | |
3613 } | |
3614 | |
3615 private: | |
3616 int m_pointer_count; | |
3617 }; | |
3537 | 3618 |
3538 /* Give a warning about a format argument of different type from that expected. | 3619 /* Give a warning about a format argument of different type from that expected. |
3539 The range of the diagnostic is taken from WHOLE_FMT_LOC; the caret location | 3620 The range of the diagnostic is taken from WHOLE_FMT_LOC; the caret location |
3540 is based on the location of the char at TYPE->offset_loc. | 3621 is based on the location of the char at TYPE->offset_loc. |
3541 PARAM_LOC is the location of the relevant argument, or UNKNOWN_LOCATION | 3622 PARAM_LOC is the location of the relevant argument, or UNKNOWN_LOCATION |
3581 const char *format_start = type->format_start; | 3662 const char *format_start = type->format_start; |
3582 int format_length = type->format_length; | 3663 int format_length = type->format_length; |
3583 int pointer_count = type->pointer_count; | 3664 int pointer_count = type->pointer_count; |
3584 int arg_num = type->arg_num; | 3665 int arg_num = type->arg_num; |
3585 | 3666 |
3586 char *p; | |
3587 /* If ARG_TYPE is a typedef with a misleading name (for example, | 3667 /* If ARG_TYPE is a typedef with a misleading name (for example, |
3588 size_t but not the standard size_t expected by printf %zu), avoid | 3668 size_t but not the standard size_t expected by printf %zu), avoid |
3589 printing the typedef name. */ | 3669 printing the typedef name. */ |
3590 if (wanted_type_name | 3670 if (wanted_type_name |
3591 && arg_type | 3671 && arg_type |
3593 && TREE_CODE (TYPE_NAME (arg_type)) == TYPE_DECL | 3673 && TREE_CODE (TYPE_NAME (arg_type)) == TYPE_DECL |
3594 && DECL_NAME (TYPE_NAME (arg_type)) | 3674 && DECL_NAME (TYPE_NAME (arg_type)) |
3595 && !strcmp (wanted_type_name, | 3675 && !strcmp (wanted_type_name, |
3596 lang_hooks.decl_printable_name (TYPE_NAME (arg_type), 2))) | 3676 lang_hooks.decl_printable_name (TYPE_NAME (arg_type), 2))) |
3597 arg_type = TYPE_MAIN_VARIANT (arg_type); | 3677 arg_type = TYPE_MAIN_VARIANT (arg_type); |
3598 /* The format type and name exclude any '*' for pointers, so those | 3678 |
3599 must be formatted manually. For all the types we currently have, | 3679 indirection_suffix suffix (pointer_count); |
3600 this is adequate, but formats taking pointers to functions or | 3680 char *p = (char *) alloca (suffix.get_buffer_size ()); |
3601 arrays would require the full type to be built up in order to | 3681 suffix.fill_buffer (p); |
3602 print it with %T. */ | |
3603 p = (char *) alloca (pointer_count + 2); | |
3604 if (pointer_count == 0) | |
3605 p[0] = 0; | |
3606 else if (c_dialect_cxx ()) | |
3607 { | |
3608 memset (p, '*', pointer_count); | |
3609 p[pointer_count] = 0; | |
3610 } | |
3611 else | |
3612 { | |
3613 p[0] = ' '; | |
3614 memset (p + 1, '*', pointer_count); | |
3615 p[pointer_count + 1] = 0; | |
3616 } | |
3617 | 3682 |
3618 /* WHOLE_FMT_LOC has the caret at the end of the range. | 3683 /* WHOLE_FMT_LOC has the caret at the end of the range. |
3619 Set the caret to be at the offset from TYPE. Subtract one | 3684 Set the caret to be at the offset from TYPE. Subtract one |
3620 from the offset for the same reason as in format_warning_at_char. */ | 3685 from the offset for the same reason as in format_warning_at_char. */ |
3621 substring_loc fmt_loc (whole_fmt_loc); | 3686 substring_loc fmt_loc (whole_fmt_loc); |
3622 fmt_loc.set_caret_index (type->offset_loc - 1); | 3687 fmt_loc.set_caret_index (type->offset_loc - 1); |
3623 | 3688 |
3689 range_label_for_format_type_mismatch fmt_label (wanted_type, arg_type, | |
3690 pointer_count); | |
3691 range_label_for_type_mismatch param_label (arg_type, wanted_type); | |
3692 | |
3624 /* Get a string for use as a replacement fix-it hint for the range in | 3693 /* Get a string for use as a replacement fix-it hint for the range in |
3625 fmt_loc, or NULL. */ | 3694 fmt_loc, or NULL. */ |
3626 char *corrected_substring | 3695 char *corrected_substring |
3627 = get_corrected_substring (fmt_loc, type, arg_type, fki, | 3696 = get_corrected_substring (fmt_loc, type, arg_type, fki, |
3628 offset_to_type_start, conversion_char); | 3697 offset_to_type_start, conversion_char); |
3629 | 3698 format_string_diagnostic_t diag (fmt_loc, &fmt_label, param_loc, ¶m_label, |
3699 corrected_substring); | |
3630 if (wanted_type_name) | 3700 if (wanted_type_name) |
3631 { | 3701 { |
3632 if (arg_type) | 3702 if (arg_type) |
3633 format_warning_at_substring | 3703 diag.emit_warning |
3634 (fmt_loc, param_loc, | 3704 (OPT_Wformat_, |
3635 corrected_substring, OPT_Wformat_, | |
3636 "%s %<%s%.*s%> expects argument of type %<%s%s%>, " | 3705 "%s %<%s%.*s%> expects argument of type %<%s%s%>, " |
3637 "but argument %d has type %qT", | 3706 "but argument %d has type %qT", |
3638 gettext (kind_descriptions[kind]), | 3707 gettext (kind_descriptions[kind]), |
3639 (kind == CF_KIND_FORMAT ? "%" : ""), | 3708 (kind == CF_KIND_FORMAT ? "%" : ""), |
3640 format_length, format_start, | 3709 format_length, format_start, |
3641 wanted_type_name, p, arg_num, arg_type); | 3710 wanted_type_name, p, arg_num, arg_type); |
3642 else | 3711 else |
3643 format_warning_at_substring | 3712 diag.emit_warning |
3644 (fmt_loc, param_loc, | 3713 (OPT_Wformat_, |
3645 corrected_substring, OPT_Wformat_, | |
3646 "%s %<%s%.*s%> expects a matching %<%s%s%> argument", | 3714 "%s %<%s%.*s%> expects a matching %<%s%s%> argument", |
3647 gettext (kind_descriptions[kind]), | 3715 gettext (kind_descriptions[kind]), |
3648 (kind == CF_KIND_FORMAT ? "%" : ""), | 3716 (kind == CF_KIND_FORMAT ? "%" : ""), |
3649 format_length, format_start, wanted_type_name, p); | 3717 format_length, format_start, wanted_type_name, p); |
3650 } | 3718 } |
3651 else | 3719 else |
3652 { | 3720 { |
3653 if (arg_type) | 3721 if (arg_type) |
3654 format_warning_at_substring | 3722 diag.emit_warning |
3655 (fmt_loc, param_loc, | 3723 (OPT_Wformat_, |
3656 corrected_substring, OPT_Wformat_, | |
3657 "%s %<%s%.*s%> expects argument of type %<%T%s%>, " | 3724 "%s %<%s%.*s%> expects argument of type %<%T%s%>, " |
3658 "but argument %d has type %qT", | 3725 "but argument %d has type %qT", |
3659 gettext (kind_descriptions[kind]), | 3726 gettext (kind_descriptions[kind]), |
3660 (kind == CF_KIND_FORMAT ? "%" : ""), | 3727 (kind == CF_KIND_FORMAT ? "%" : ""), |
3661 format_length, format_start, | 3728 format_length, format_start, |
3662 wanted_type, p, arg_num, arg_type); | 3729 wanted_type, p, arg_num, arg_type); |
3663 else | 3730 else |
3664 format_warning_at_substring | 3731 diag.emit_warning |
3665 (fmt_loc, param_loc, | 3732 (OPT_Wformat_, |
3666 corrected_substring, OPT_Wformat_, | |
3667 "%s %<%s%.*s%> expects a matching %<%T%s%> argument", | 3733 "%s %<%s%.*s%> expects a matching %<%T%s%> argument", |
3668 gettext (kind_descriptions[kind]), | 3734 gettext (kind_descriptions[kind]), |
3669 (kind == CF_KIND_FORMAT ? "%" : ""), | 3735 (kind == CF_KIND_FORMAT ? "%" : ""), |
3670 format_length, format_start, wanted_type, p); | 3736 format_length, format_start, wanted_type, p); |
3671 } | 3737 } |
3861 } | 3927 } |
3862 else | 3928 else |
3863 local_tree_type_node = void_type_node; | 3929 local_tree_type_node = void_type_node; |
3864 } | 3930 } |
3865 | 3931 |
3866 /* Similar to the above but for gcall*. */ | 3932 /* Similar to the above but for gimple*. */ |
3867 if (!local_gcall_ptr_node | 3933 if (!local_gimple_ptr_node |
3868 || local_gcall_ptr_node == void_type_node) | 3934 || local_gimple_ptr_node == void_type_node) |
3869 { | 3935 { |
3870 if ((local_gcall_ptr_node = maybe_get_identifier ("gcall"))) | 3936 if ((local_gimple_ptr_node = maybe_get_identifier ("gimple"))) |
3871 { | 3937 { |
3872 local_gcall_ptr_node | 3938 local_gimple_ptr_node |
3873 = identifier_global_value (local_gcall_ptr_node); | 3939 = identifier_global_value (local_gimple_ptr_node); |
3874 if (local_gcall_ptr_node) | 3940 if (local_gimple_ptr_node) |
3875 { | 3941 { |
3876 if (TREE_CODE (local_gcall_ptr_node) != TYPE_DECL) | 3942 if (TREE_CODE (local_gimple_ptr_node) != TYPE_DECL) |
3877 { | 3943 { |
3878 error ("%<gcall%> is not defined as a type"); | 3944 error ("%<gimple%> is not defined as a type"); |
3879 local_gcall_ptr_node = 0; | 3945 local_gimple_ptr_node = 0; |
3880 } | 3946 } |
3881 else | 3947 else |
3882 local_gcall_ptr_node = TREE_TYPE (local_gcall_ptr_node); | 3948 local_gimple_ptr_node = TREE_TYPE (local_gimple_ptr_node); |
3883 } | 3949 } |
3884 } | 3950 } |
3885 else | 3951 else |
3886 local_gcall_ptr_node = void_type_node; | 3952 local_gimple_ptr_node = void_type_node; |
3887 } | 3953 } |
3888 | 3954 |
3889 static tree hwi; | 3955 static tree hwi; |
3890 | 3956 |
3891 if (!hwi) | 3957 if (!hwi) |
3928 if (!diag_ls) | 3994 if (!diag_ls) |
3929 dynamic_format_types[gcc_diag_format_type].length_char_specs = | 3995 dynamic_format_types[gcc_diag_format_type].length_char_specs = |
3930 dynamic_format_types[gcc_tdiag_format_type].length_char_specs = | 3996 dynamic_format_types[gcc_tdiag_format_type].length_char_specs = |
3931 dynamic_format_types[gcc_cdiag_format_type].length_char_specs = | 3997 dynamic_format_types[gcc_cdiag_format_type].length_char_specs = |
3932 dynamic_format_types[gcc_cxxdiag_format_type].length_char_specs = | 3998 dynamic_format_types[gcc_cxxdiag_format_type].length_char_specs = |
3999 dynamic_format_types[gcc_dump_printf_format_type].length_char_specs = | |
3933 diag_ls = (format_length_info *) | 4000 diag_ls = (format_length_info *) |
3934 xmemdup (gcc_diag_length_specs, | 4001 xmemdup (gcc_diag_length_specs, |
3935 sizeof (gcc_diag_length_specs), | 4002 sizeof (gcc_diag_length_specs), |
3936 sizeof (gcc_diag_length_specs)); | 4003 sizeof (gcc_diag_length_specs)); |
3937 if (hwi) | 4004 if (hwi) |
3954 gcc_tdiag_char_table; | 4021 gcc_tdiag_char_table; |
3955 dynamic_format_types[gcc_cdiag_format_type].conversion_specs = | 4022 dynamic_format_types[gcc_cdiag_format_type].conversion_specs = |
3956 gcc_cdiag_char_table; | 4023 gcc_cdiag_char_table; |
3957 dynamic_format_types[gcc_cxxdiag_format_type].conversion_specs = | 4024 dynamic_format_types[gcc_cxxdiag_format_type].conversion_specs = |
3958 gcc_cxxdiag_char_table; | 4025 gcc_cxxdiag_char_table; |
4026 dynamic_format_types[gcc_dump_printf_format_type].conversion_specs = | |
4027 gcc_dump_printf_char_table; | |
3959 } | 4028 } |
3960 | 4029 |
3961 #ifdef TARGET_FORMAT_TYPES | 4030 #ifdef TARGET_FORMAT_TYPES |
3962 extern const format_kind_info TARGET_FORMAT_TYPES[]; | 4031 extern const format_kind_info TARGET_FORMAT_TYPES[]; |
3963 #endif | 4032 #endif |
4108 if (info.format_type == asm_fprintf_format_type | 4177 if (info.format_type == asm_fprintf_format_type |
4109 || info.format_type == gcc_gfc_format_type | 4178 || info.format_type == gcc_gfc_format_type |
4110 || info.format_type == gcc_diag_format_type | 4179 || info.format_type == gcc_diag_format_type |
4111 || info.format_type == gcc_tdiag_format_type | 4180 || info.format_type == gcc_tdiag_format_type |
4112 || info.format_type == gcc_cdiag_format_type | 4181 || info.format_type == gcc_cdiag_format_type |
4113 || info.format_type == gcc_cxxdiag_format_type) | 4182 || info.format_type == gcc_cxxdiag_format_type |
4183 || info.format_type == gcc_dump_printf_format_type) | |
4114 { | 4184 { |
4115 /* Our first time through, we have to make sure that our | 4185 /* Our first time through, we have to make sure that our |
4116 format_type data is allocated dynamically and is modifiable. */ | 4186 format_type data is allocated dynamically and is modifiable. */ |
4117 if (!dynamic_format_types) | 4187 if (!dynamic_format_types) |
4118 format_types = dynamic_format_types = (format_kind_info *) | 4188 format_types = dynamic_format_types = (format_kind_info *) |
4130 /* If this is one of the diagnostic attributes, then we have to | 4200 /* If this is one of the diagnostic attributes, then we have to |
4131 initialize 'location_t' and 'tree' at runtime. */ | 4201 initialize 'location_t' and 'tree' at runtime. */ |
4132 else if (info.format_type == gcc_diag_format_type | 4202 else if (info.format_type == gcc_diag_format_type |
4133 || info.format_type == gcc_tdiag_format_type | 4203 || info.format_type == gcc_tdiag_format_type |
4134 || info.format_type == gcc_cdiag_format_type | 4204 || info.format_type == gcc_cdiag_format_type |
4135 || info.format_type == gcc_cxxdiag_format_type) | 4205 || info.format_type == gcc_cxxdiag_format_type |
4206 || info.format_type == gcc_dump_printf_format_type) | |
4136 init_dynamic_diag_info (); | 4207 init_dynamic_diag_info (); |
4137 else | 4208 else |
4138 gcc_unreachable (); | 4209 gcc_unreachable (); |
4139 } | 4210 } |
4140 | 4211 |
4240 ASSERT_FORMAT_FOR_TYPE_STREQ ("le", build_pointer_type (double_type_node), 'e'); | 4311 ASSERT_FORMAT_FOR_TYPE_STREQ ("le", build_pointer_type (double_type_node), 'e'); |
4241 } | 4312 } |
4242 | 4313 |
4243 #undef ASSERT_FORMAT_FOR_TYPE_STREQ | 4314 #undef ASSERT_FORMAT_FOR_TYPE_STREQ |
4244 | 4315 |
4316 /* Exercise the type-printing label code, to give some coverage | |
4317 under "make selftest-valgrind" (in particular, to ensure that | |
4318 the label-printing machinery doesn't leak). */ | |
4319 | |
4320 static void | |
4321 test_type_mismatch_range_labels () | |
4322 { | |
4323 /* Create a tempfile and write some text to it. | |
4324 ....................0000000001 11111111 12 22222222 | |
4325 ....................1234567890 12345678 90 12345678. */ | |
4326 const char *content = " printf (\"msg: %i\\n\", msg);\n"; | |
4327 temp_source_file tmp (SELFTEST_LOCATION, ".c", content); | |
4328 line_table_test ltt; | |
4329 | |
4330 linemap_add (line_table, LC_ENTER, false, tmp.get_filename (), 1); | |
4331 | |
4332 location_t c17 = linemap_position_for_column (line_table, 17); | |
4333 ASSERT_EQ (LOCATION_COLUMN (c17), 17); | |
4334 location_t c18 = linemap_position_for_column (line_table, 18); | |
4335 location_t c24 = linemap_position_for_column (line_table, 24); | |
4336 location_t c26 = linemap_position_for_column (line_table, 26); | |
4337 | |
4338 /* Don't attempt to run the tests if column data might be unavailable. */ | |
4339 if (c26 > LINE_MAP_MAX_LOCATION_WITH_COLS) | |
4340 return; | |
4341 | |
4342 location_t fmt = make_location (c18, c17, c18); | |
4343 ASSERT_EQ (LOCATION_COLUMN (fmt), 18); | |
4344 | |
4345 location_t param = make_location (c24, c24, c26); | |
4346 ASSERT_EQ (LOCATION_COLUMN (param), 24); | |
4347 | |
4348 range_label_for_format_type_mismatch fmt_label (char_type_node, | |
4349 integer_type_node, 1); | |
4350 range_label_for_type_mismatch param_label (integer_type_node, | |
4351 char_type_node); | |
4352 gcc_rich_location richloc (fmt, &fmt_label); | |
4353 richloc.add_range (param, SHOW_RANGE_WITHOUT_CARET, ¶m_label); | |
4354 | |
4355 test_diagnostic_context dc; | |
4356 diagnostic_show_locus (&dc, &richloc, DK_ERROR); | |
4357 if (c_dialect_cxx ()) | |
4358 /* "char*", without a space. */ | |
4359 ASSERT_STREQ ("\n" | |
4360 " printf (\"msg: %i\\n\", msg);\n" | |
4361 " ~^ ~~~\n" | |
4362 " | |\n" | |
4363 " char* int\n", | |
4364 pp_formatted_text (dc.printer)); | |
4365 else | |
4366 /* "char *", with a space. */ | |
4367 ASSERT_STREQ ("\n" | |
4368 " printf (\"msg: %i\\n\", msg);\n" | |
4369 " ~^ ~~~\n" | |
4370 " | |\n" | |
4371 " | int\n" | |
4372 " char *\n", | |
4373 pp_formatted_text (dc.printer)); | |
4374 } | |
4375 | |
4245 /* Run all of the selftests within this file. */ | 4376 /* Run all of the selftests within this file. */ |
4246 | 4377 |
4247 void | 4378 void |
4248 c_format_c_tests () | 4379 c_format_c_tests () |
4249 { | 4380 { |
4250 test_get_modifier_for_format_len (); | 4381 test_get_modifier_for_format_len (); |
4251 test_get_format_for_type_printf (); | 4382 test_get_format_for_type_printf (); |
4252 test_get_format_for_type_scanf (); | 4383 test_get_format_for_type_scanf (); |
4384 test_type_mismatch_range_labels (); | |
4253 } | 4385 } |
4254 | 4386 |
4255 } // namespace selftest | 4387 } // namespace selftest |
4256 | 4388 |
4257 #endif /* CHECKING_P */ | 4389 #endif /* CHECKING_P */ |