111
|
1 /* Implementation of gcc_rich_location class
|
145
|
2 Copyright (C) 2014-2020 Free Software Foundation, Inc.
|
111
|
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"
|
|
26 #include "vec.h"
|
|
27 #include "input.h"
|
|
28 #include "alias.h"
|
|
29 #include "symtab.h"
|
|
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
|
131
|
41 /* Add a range to the rich_location, covering expression EXPR,
|
|
42 using LABEL if non-NULL. */
|
111
|
43
|
|
44 void
|
131
|
45 gcc_rich_location::add_expr (tree expr, range_label *label)
|
111
|
46 {
|
|
47 gcc_assert (expr);
|
|
48
|
|
49 if (CAN_HAVE_RANGE_P (expr))
|
131
|
50 add_range (EXPR_LOCATION (expr), SHOW_RANGE_WITHOUT_CARET, label);
|
111
|
51 }
|
|
52
|
131
|
53 /* If T is an expression, add a range for it to the rich_location,
|
|
54 using LABEL if non-NULL. */
|
111
|
55
|
|
56 void
|
131
|
57 gcc_rich_location::maybe_add_expr (tree t, range_label *label)
|
111
|
58 {
|
|
59 if (EXPR_P (t))
|
131
|
60 add_expr (t, label);
|
111
|
61 }
|
|
62
|
|
63 /* Add a fixit hint suggesting replacing the range at MISSPELLED_TOKEN_LOC
|
|
64 with the identifier HINT_ID. */
|
|
65
|
|
66 void
|
|
67 gcc_rich_location::add_fixit_misspelled_id (location_t misspelled_token_loc,
|
|
68 tree hint_id)
|
|
69 {
|
|
70 gcc_assert (TREE_CODE (hint_id) == IDENTIFIER_NODE);
|
|
71
|
|
72 add_fixit_replace (misspelled_token_loc, IDENTIFIER_POINTER (hint_id));
|
|
73 }
|
131
|
74
|
|
75 /* Return true if there is nothing on LOC's line before LOC. */
|
|
76
|
|
77 static bool
|
|
78 blank_line_before_p (location_t loc)
|
|
79 {
|
|
80 expanded_location exploc = expand_location (loc);
|
|
81 char_span line = location_get_source_line (exploc.file, exploc.line);
|
|
82 if (!line)
|
|
83 return false;
|
|
84 if (line.length () < (size_t)exploc.column)
|
|
85 return false;
|
|
86 /* Columns are 1-based. */
|
|
87 for (int column = 1; column < exploc.column; ++column)
|
|
88 if (!ISSPACE (line[column - 1]))
|
|
89 return false;
|
|
90 return true;
|
|
91 }
|
|
92
|
|
93 /* Subroutine of gcc_rich_location::add_fixit_insert_formatted.
|
|
94 Return true if we should add the content on its own line,
|
|
95 false otherwise.
|
|
96 If true is returned then *OUT_START_OF_LINE is written to. */
|
|
97
|
|
98 static bool
|
|
99 use_new_line (location_t insertion_point, location_t indent,
|
|
100 location_t *out_start_of_line)
|
|
101 {
|
|
102 if (indent == UNKNOWN_LOCATION)
|
|
103 return false;
|
|
104 const line_map *indent_map = linemap_lookup (line_table, indent);
|
|
105 if (linemap_macro_expansion_map_p (indent_map))
|
|
106 return false;
|
|
107
|
|
108 if (!blank_line_before_p (insertion_point))
|
|
109 return false;
|
|
110
|
|
111 /* Locate the start of the line containing INSERTION_POINT. */
|
|
112 const line_map *insertion_point_map
|
|
113 = linemap_lookup (line_table, insertion_point);
|
|
114 if (linemap_macro_expansion_map_p (insertion_point_map))
|
|
115 return false;
|
|
116 const line_map_ordinary *ordmap
|
|
117 = linemap_check_ordinary (insertion_point_map);
|
|
118 expanded_location exploc_insertion_point = expand_location (insertion_point);
|
|
119 location_t start_of_line
|
|
120 = linemap_position_for_line_and_column (line_table, ordmap,
|
|
121 exploc_insertion_point.line, 1);
|
|
122 *out_start_of_line = start_of_line;
|
|
123 return true;
|
|
124 }
|
|
125
|
|
126 /* Add a fix-it hint suggesting the insertion of CONTENT before
|
|
127 INSERTION_POINT.
|
|
128
|
|
129 Attempt to handle formatting: if INSERTION_POINT is the first thing on
|
|
130 its line, and INDENT is sufficiently sane, then add CONTENT on its own
|
|
131 line, using the indentation of INDENT.
|
|
132 Otherwise, add CONTENT directly before INSERTION_POINT.
|
|
133
|
|
134 For example, adding "CONTENT;" with the closing brace as the insertion
|
|
135 point and "INDENT;" as the indentation point:
|
|
136
|
|
137 if ()
|
|
138 {
|
|
139 INDENT;
|
|
140 }
|
|
141
|
|
142 would lead to:
|
|
143
|
|
144 if ()
|
|
145 {
|
|
146 INDENT;
|
|
147 CONTENT;
|
|
148 }
|
|
149
|
|
150 but adding it to:
|
|
151
|
|
152 if () {INDENT;}
|
|
153
|
|
154 would lead to:
|
|
155
|
|
156 if () {INDENT;CONTENT;}
|
|
157 */
|
|
158
|
|
159 void
|
|
160 gcc_rich_location::add_fixit_insert_formatted (const char *content,
|
|
161 location_t insertion_point,
|
|
162 location_t indent)
|
|
163 {
|
|
164 location_t start_of_line;
|
|
165 if (use_new_line (insertion_point, indent, &start_of_line))
|
|
166 {
|
|
167 /* Add CONTENT on its own line, using the indentation of INDENT. */
|
|
168
|
|
169 /* Generate an insertion string, indenting by the amount INDENT
|
|
170 was indented. */
|
|
171 int indent_column = LOCATION_COLUMN (get_start (indent));
|
|
172 pretty_printer tmp_pp;
|
|
173 pretty_printer *pp = &tmp_pp;
|
|
174 /* Columns are 1-based. */
|
|
175 for (int column = 1; column < indent_column; ++column)
|
|
176 pp_space (pp);
|
|
177 pp_string (pp, content);
|
|
178 pp_newline (pp);
|
|
179
|
|
180 add_fixit_insert_before (start_of_line, pp_formatted_text (pp));
|
|
181 }
|
|
182 else
|
|
183 add_fixit_insert_before (insertion_point, content);
|
|
184 }
|
145
|
185
|
|
186 /* Implementation of range_label::get_text for
|
|
187 maybe_range_label_for_tree_type_mismatch.
|
|
188
|
|
189 If both expressions are non-NULL, then generate text describing
|
|
190 the first expression's type (using the other expression's type
|
|
191 for comparison, analogous to %H and %I in the C++ frontend, but
|
|
192 on expressions rather than types). */
|
|
193
|
|
194 label_text
|
|
195 maybe_range_label_for_tree_type_mismatch::get_text (unsigned range_idx) const
|
|
196 {
|
|
197 if (m_expr == NULL_TREE
|
|
198 || !EXPR_P (m_expr))
|
|
199 return label_text::borrow (NULL);
|
|
200 tree expr_type = TREE_TYPE (m_expr);
|
|
201
|
|
202 tree other_type = NULL_TREE;
|
|
203 if (m_other_expr && EXPR_P (m_other_expr))
|
|
204 other_type = TREE_TYPE (m_other_expr);
|
|
205
|
|
206 range_label_for_type_mismatch inner (expr_type, other_type);
|
|
207 return inner.get_text (range_idx);
|
|
208 }
|
|
209
|
|
210 /* binary_op_rich_location's ctor.
|
|
211
|
|
212 If use_operator_loc_p (LOC, ARG0, ARG1), then attempt to make a 3-location
|
|
213 rich_location of the form:
|
|
214
|
|
215 arg_0 op arg_1
|
|
216 ~~~~~ ^~ ~~~~~
|
|
217 | |
|
|
218 | arg1 type
|
|
219 arg0 type
|
|
220
|
|
221 labelling the types of the arguments if SHOW_TYPES is true.
|
|
222
|
|
223 Otherwise, make a 1-location rich_location using the compound
|
|
224 location within LOC:
|
|
225
|
|
226 arg_0 op arg_1
|
|
227 ~~~~~~^~~~~~~~
|
|
228
|
|
229 for which we can't label the types. */
|
|
230
|
|
231 binary_op_rich_location::binary_op_rich_location (const op_location_t &loc,
|
|
232 tree arg0, tree arg1,
|
|
233 bool show_types)
|
|
234 : gcc_rich_location (loc.m_combined_loc),
|
|
235 m_label_for_arg0 (arg0, arg1),
|
|
236 m_label_for_arg1 (arg1, arg0)
|
|
237 {
|
|
238 /* Default (above) to using the combined loc.
|
|
239 Potentially override it here: if we have location information for the
|
|
240 operator and for both arguments, then split them all out.
|
|
241 Alternatively, override it if we don't have the combined location. */
|
|
242 if (use_operator_loc_p (loc, arg0, arg1))
|
|
243 {
|
|
244 set_range (0, loc.m_operator_loc, SHOW_RANGE_WITH_CARET);
|
|
245 maybe_add_expr (arg0, show_types ? &m_label_for_arg0 : NULL);
|
|
246 maybe_add_expr (arg1, show_types ? &m_label_for_arg1 : NULL);
|
|
247 }
|
|
248 }
|
|
249
|
|
250 /* Determine if binary_op_rich_location's ctor should attempt to make
|
|
251 a 3-location rich_location (the location of the operator and of
|
|
252 the 2 arguments), or fall back to a 1-location rich_location showing
|
|
253 just the combined location of the operation as a whole. */
|
|
254
|
|
255 bool
|
|
256 binary_op_rich_location::use_operator_loc_p (const op_location_t &loc,
|
|
257 tree arg0, tree arg1)
|
|
258 {
|
|
259 /* If we don't have a combined location, then use the operator location,
|
|
260 and try to add ranges for the operators. */
|
|
261 if (loc.m_combined_loc == UNKNOWN_LOCATION)
|
|
262 return true;
|
|
263
|
|
264 /* If we don't have the operator location, then use the
|
|
265 combined location. */
|
|
266 if (loc.m_operator_loc == UNKNOWN_LOCATION)
|
|
267 return false;
|
|
268
|
|
269 /* We have both operator location and combined location: only use the
|
|
270 operator location if we have locations for both arguments. */
|
|
271 return (EXPR_HAS_LOCATION (arg0)
|
|
272 && EXPR_HAS_LOCATION (arg1));
|
|
273 }
|