Branch data Line data Source code
1 : : /* Implementation of gcc_rich_location class
2 : : Copyright (C) 2014-2024 Free Software Foundation, Inc.
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 : :
41 : : /* Add a range to the rich_location, covering expression EXPR,
42 : : using LABEL if non-NULL. */
43 : :
44 : : void
45 : 1073 : gcc_rich_location::add_expr (tree expr,
46 : : range_label *label,
47 : : const char *highlight_color)
48 : : {
49 : 1073 : gcc_assert (expr);
50 : :
51 : 1073 : if (CAN_HAVE_RANGE_P (expr))
52 : 1073 : add_range (EXPR_LOCATION (expr), SHOW_RANGE_WITHOUT_CARET, label,
53 : : highlight_color);
54 : 1073 : }
55 : :
56 : : /* If T is an expression, add a range for it to the rich_location,
57 : : using LABEL if non-NULL. */
58 : :
59 : : void
60 : 1722 : gcc_rich_location::maybe_add_expr (tree t, range_label *label,
61 : : const char *highlight_color)
62 : : {
63 : 1722 : if (EXPR_P (t))
64 : 1065 : add_expr (t, label, highlight_color);
65 : 1722 : }
66 : :
67 : : /* Add a fixit hint suggesting replacing the range at MISSPELLED_TOKEN_LOC
68 : : with the identifier HINT_ID. */
69 : :
70 : : void
71 : 71 : gcc_rich_location::add_fixit_misspelled_id (location_t misspelled_token_loc,
72 : : tree hint_id)
73 : : {
74 : 71 : gcc_assert (TREE_CODE (hint_id) == IDENTIFIER_NODE);
75 : :
76 : 71 : add_fixit_replace (misspelled_token_loc, IDENTIFIER_POINTER (hint_id));
77 : 71 : }
78 : :
79 : : /* Return true if there is nothing on LOC's line before LOC. */
80 : :
81 : : static bool
82 : 11 : blank_line_before_p (file_cache &fc,
83 : : location_t loc)
84 : : {
85 : 11 : expanded_location exploc = expand_location (loc);
86 : 11 : char_span line = fc.get_source_line (exploc.file, exploc.line);
87 : 11 : if (!line)
88 : : return false;
89 : 22 : if (line.length () < (size_t)exploc.column)
90 : : return false;
91 : : /* Columns are 1-based. */
92 : 31 : for (int column = 1; column < exploc.column; ++column)
93 : 21 : 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
104 : 20 : use_new_line (file_cache &fc,
105 : : location_t insertion_point, location_t indent,
106 : : location_t *out_start_of_line)
107 : : {
108 : 20 : if (indent == UNKNOWN_LOCATION)
109 : : return false;
110 : 11 : const line_map *indent_map = linemap_lookup (line_table, indent);
111 : 11 : if (linemap_macro_expansion_map_p (indent_map))
112 : : return false;
113 : :
114 : 11 : if (!blank_line_before_p (fc, insertion_point))
115 : : return false;
116 : :
117 : : /* Locate the start of the line containing INSERTION_POINT. */
118 : 10 : const line_map *insertion_point_map
119 : 10 : = linemap_lookup (line_table, insertion_point);
120 : 10 : if (linemap_macro_expansion_map_p (insertion_point_map))
121 : : return false;
122 : 10 : const line_map_ordinary *ordmap
123 : 10 : = linemap_check_ordinary (insertion_point_map);
124 : 10 : expanded_location exploc_insertion_point = expand_location (insertion_point);
125 : 10 : location_t start_of_line
126 : 20 : = linemap_position_for_line_and_column (line_table, ordmap,
127 : 10 : exploc_insertion_point.line, 1);
128 : 10 : *out_start_of_line = start_of_line;
129 : 10 : 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 : 20 : gcc_rich_location::add_fixit_insert_formatted (const char *content,
167 : : location_t insertion_point,
168 : : location_t indent)
169 : : {
170 : 20 : location_t start_of_line;
171 : 20 : if (use_new_line (global_dc->get_file_cache (),
172 : : insertion_point, indent, &start_of_line))
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 : 10 : int indent_column = LOCATION_COLUMN (get_start (indent));
179 : 10 : pretty_printer tmp_pp;
180 : 10 : pretty_printer *pp = &tmp_pp;
181 : : /* Columns are 1-based. */
182 : 48 : for (int column = 1; column < indent_column; ++column)
183 : 38 : pp_space (pp);
184 : 10 : pp_string (pp, content);
185 : 10 : pp_newline (pp);
186 : :
187 : 10 : add_fixit_insert_before (start_of_line, pp_formatted_text (pp));
188 : 10 : }
189 : : else
190 : 10 : add_fixit_insert_before (insertion_point, content);
191 : 20 : }
|