]>
Commit | Line | Data |
---|---|---|
ebedc9a3 | 1 | /* Implementation of gcc_rich_location class |
a945c346 | 2 | Copyright (C) 2014-2024 Free Software Foundation, Inc. |
ebedc9a3 DM |
3 | |
4 | This file is part of GCC. | |
5 | ||
6 | GCC is free software; you can redistribute it and/or modify it under | |
7 | the terms of the GNU General Public License as published by the Free | |
8 | Software Foundation; either version 3, or (at your option) any later | |
9 | version. | |
10 | ||
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GCC; see the file COPYING3. If not see | |
18 | <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include "config.h" | |
21 | #include "system.h" | |
22 | #include "coretypes.h" | |
23 | #include "tm.h" | |
24 | #include "rtl.h" | |
25 | #include "hash-set.h" | |
ebedc9a3 | 26 | #include "vec.h" |
ebedc9a3 DM |
27 | #include "input.h" |
28 | #include "alias.h" | |
29 | #include "symtab.h" | |
ebedc9a3 DM |
30 | #include "inchash.h" |
31 | #include "tree-core.h" | |
32 | #include "tree.h" | |
33 | #include "diagnostic-core.h" | |
34 | #include "gcc-rich-location.h" | |
35 | #include "print-tree.h" | |
36 | #include "pretty-print.h" | |
37 | #include "intl.h" | |
38 | #include "cpplib.h" | |
39 | #include "diagnostic.h" | |
40 | ||
96e6ae57 DM |
41 | /* Add a range to the rich_location, covering expression EXPR, |
42 | using LABEL if non-NULL. */ | |
ebedc9a3 DM |
43 | |
44 | void | |
7d73c01c DM |
45 | gcc_rich_location::add_expr (tree expr, |
46 | range_label *label, | |
47 | const char *highlight_color) | |
ebedc9a3 DM |
48 | { |
49 | gcc_assert (expr); | |
50 | ||
40499f81 | 51 | if (CAN_HAVE_RANGE_P (expr)) |
7d73c01c DM |
52 | add_range (EXPR_LOCATION (expr), SHOW_RANGE_WITHOUT_CARET, label, |
53 | highlight_color); | |
ebedc9a3 DM |
54 | } |
55 | ||
96e6ae57 DM |
56 | /* If T is an expression, add a range for it to the rich_location, |
57 | using LABEL if non-NULL. */ | |
ebedc9a3 DM |
58 | |
59 | void | |
7d73c01c DM |
60 | gcc_rich_location::maybe_add_expr (tree t, range_label *label, |
61 | const char *highlight_color) | |
ebedc9a3 DM |
62 | { |
63 | if (EXPR_P (t)) | |
7d73c01c | 64 | add_expr (t, label, highlight_color); |
ebedc9a3 | 65 | } |
264757fb DM |
66 | |
67 | /* Add a fixit hint suggesting replacing the range at MISSPELLED_TOKEN_LOC | |
68 | with the identifier HINT_ID. */ | |
69 | ||
70 | void | |
71 | gcc_rich_location::add_fixit_misspelled_id (location_t misspelled_token_loc, | |
72 | tree hint_id) | |
73 | { | |
74 | gcc_assert (TREE_CODE (hint_id) == IDENTIFIER_NODE); | |
75 | ||
f9087798 | 76 | add_fixit_replace (misspelled_token_loc, IDENTIFIER_POINTER (hint_id)); |
de6a69ee | 77 | } |
1a3a7b4e DM |
78 | |
79 | /* Return true if there is nothing on LOC's line before LOC. */ | |
80 | ||
81 | static bool | |
1bdd665a DM |
82 | blank_line_before_p (file_cache &fc, |
83 | location_t loc) | |
1a3a7b4e DM |
84 | { |
85 | expanded_location exploc = expand_location (loc); | |
1bdd665a | 86 | char_span line = fc.get_source_line (exploc.file, exploc.line); |
1a3a7b4e DM |
87 | if (!line) |
88 | return false; | |
89 | if (line.length () < (size_t)exploc.column) | |
90 | return false; | |
91 | /* Columns are 1-based. */ | |
92 | for (int column = 1; column < exploc.column; ++column) | |
93 | if (!ISSPACE (line[column - 1])) | |
94 | return false; | |
95 | return true; | |
96 | } | |
97 | ||
98 | /* Subroutine of gcc_rich_location::add_fixit_insert_formatted. | |
99 | Return true if we should add the content on its own line, | |
100 | false otherwise. | |
101 | If true is returned then *OUT_START_OF_LINE is written to. */ | |
102 | ||
103 | static bool | |
1bdd665a DM |
104 | use_new_line (file_cache &fc, |
105 | location_t insertion_point, location_t indent, | |
1a3a7b4e DM |
106 | location_t *out_start_of_line) |
107 | { | |
108 | if (indent == UNKNOWN_LOCATION) | |
109 | return false; | |
110 | const line_map *indent_map = linemap_lookup (line_table, indent); | |
111 | if (linemap_macro_expansion_map_p (indent_map)) | |
112 | return false; | |
113 | ||
1bdd665a | 114 | if (!blank_line_before_p (fc, insertion_point)) |
1a3a7b4e DM |
115 | return false; |
116 | ||
117 | /* Locate the start of the line containing INSERTION_POINT. */ | |
118 | const line_map *insertion_point_map | |
119 | = linemap_lookup (line_table, insertion_point); | |
120 | if (linemap_macro_expansion_map_p (insertion_point_map)) | |
121 | return false; | |
122 | const line_map_ordinary *ordmap | |
123 | = linemap_check_ordinary (insertion_point_map); | |
124 | expanded_location exploc_insertion_point = expand_location (insertion_point); | |
125 | location_t start_of_line | |
126 | = linemap_position_for_line_and_column (line_table, ordmap, | |
127 | exploc_insertion_point.line, 1); | |
128 | *out_start_of_line = start_of_line; | |
129 | return true; | |
130 | } | |
131 | ||
132 | /* Add a fix-it hint suggesting the insertion of CONTENT before | |
133 | INSERTION_POINT. | |
134 | ||
135 | Attempt to handle formatting: if INSERTION_POINT is the first thing on | |
136 | its line, and INDENT is sufficiently sane, then add CONTENT on its own | |
137 | line, using the indentation of INDENT. | |
138 | Otherwise, add CONTENT directly before INSERTION_POINT. | |
139 | ||
140 | For example, adding "CONTENT;" with the closing brace as the insertion | |
141 | point and "INDENT;" as the indentation point: | |
142 | ||
143 | if () | |
144 | { | |
145 | INDENT; | |
146 | } | |
147 | ||
148 | would lead to: | |
149 | ||
150 | if () | |
151 | { | |
152 | INDENT; | |
153 | CONTENT; | |
154 | } | |
155 | ||
156 | but adding it to: | |
157 | ||
158 | if () {INDENT;} | |
159 | ||
160 | would lead to: | |
161 | ||
162 | if () {INDENT;CONTENT;} | |
163 | */ | |
164 | ||
165 | void | |
166 | gcc_rich_location::add_fixit_insert_formatted (const char *content, | |
167 | location_t insertion_point, | |
168 | location_t indent) | |
169 | { | |
170 | location_t start_of_line; | |
1bdd665a DM |
171 | if (use_new_line (global_dc->get_file_cache (), |
172 | insertion_point, indent, &start_of_line)) | |
1a3a7b4e DM |
173 | { |
174 | /* Add CONTENT on its own line, using the indentation of INDENT. */ | |
175 | ||
176 | /* Generate an insertion string, indenting by the amount INDENT | |
177 | was indented. */ | |
178 | int indent_column = LOCATION_COLUMN (get_start (indent)); | |
179 | pretty_printer tmp_pp; | |
180 | pretty_printer *pp = &tmp_pp; | |
181 | /* Columns are 1-based. */ | |
182 | for (int column = 1; column < indent_column; ++column) | |
183 | pp_space (pp); | |
184 | pp_string (pp, content); | |
185 | pp_newline (pp); | |
186 | ||
187 | add_fixit_insert_before (start_of_line, pp_formatted_text (pp)); | |
188 | } | |
189 | else | |
190 | add_fixit_insert_before (insertion_point, content); | |
191 | } |