1 | /* Declarations relating to class gcc_rich_location |
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 | #ifndef GCC_RICH_LOCATION_H |
21 | #define GCC_RICH_LOCATION_H |
22 | |
23 | #include "rich-location.h" |
24 | |
25 | /* A gcc_rich_location is libcpp's rich_location with additional |
26 | helper methods for working with gcc's types. The class is not |
27 | copyable or assignable because rich_location isn't. */ |
28 | |
29 | class gcc_rich_location : public rich_location |
30 | { |
31 | public: |
32 | /* Constructors. */ |
33 | |
34 | /* Constructing from a location. */ |
35 | explicit gcc_rich_location (location_t loc, const range_label *label = NULL) |
36 | : rich_location (line_table, loc, label) |
37 | { |
38 | } |
39 | |
40 | /* Methods for adding ranges via gcc entities. */ |
41 | void |
42 | add_expr (tree expr, range_label *label); |
43 | |
44 | void |
45 | maybe_add_expr (tree t, range_label *label); |
46 | |
47 | void add_fixit_misspelled_id (location_t misspelled_token_loc, |
48 | tree hint_id); |
49 | |
50 | /* If LOC is within the spans of lines that will already be printed for |
51 | this gcc_rich_location, then add it as a secondary location |
52 | and return true. |
53 | |
54 | Otherwise return false. |
55 | |
56 | This allows for a diagnostic to compactly print secondary locations |
57 | in one diagnostic when these are near enough the primary locations for |
58 | diagnostics-show-locus.c to cope with them, and to fall back to |
59 | printing them via a note otherwise e.g.: |
60 | |
61 | gcc_rich_location richloc (primary_loc); |
62 | bool added secondary = richloc.add_location_if_nearby (secondary_loc); |
63 | error_at (&richloc, "main message"); |
64 | if (!added secondary) |
65 | inform (secondary_loc, "message for secondary"); |
66 | |
67 | Implemented in diagnostic-show-locus.cc. */ |
68 | |
69 | bool add_location_if_nearby (location_t loc, |
70 | bool restrict_to_current_line_spans = true, |
71 | const range_label *label = NULL); |
72 | |
73 | /* Add a fix-it hint suggesting the insertion of CONTENT before |
74 | INSERTION_POINT. |
75 | |
76 | Attempt to handle formatting: if INSERTION_POINT is the first thing on |
77 | its line, and INDENT is sufficiently sane, then add CONTENT on its own |
78 | line, using the indentation of INDENT. |
79 | Otherwise, add CONTENT directly before INSERTION_POINT. |
80 | |
81 | For example, adding "CONTENT;" with the closing brace as the insertion |
82 | point and using "INDENT;" for indentation: |
83 | |
84 | if () |
85 | { |
86 | INDENT; |
87 | } |
88 | |
89 | would lead to: |
90 | |
91 | if () |
92 | { |
93 | INDENT; |
94 | CONTENT; |
95 | } |
96 | |
97 | but adding it to: |
98 | |
99 | if () {INDENT;} |
100 | |
101 | would lead to: |
102 | |
103 | if () {INDENT;CONTENT;} |
104 | */ |
105 | void add_fixit_insert_formatted (const char *content, |
106 | location_t insertion_point, |
107 | location_t indent); |
108 | }; |
109 | |
110 | /* Concrete subclass of libcpp's range_label. |
111 | Simple implementation using a string literal. */ |
112 | |
113 | class text_range_label : public range_label |
114 | { |
115 | public: |
116 | text_range_label (const char *text) : m_text (text) {} |
117 | |
118 | label_text get_text (unsigned /*range_idx*/) const final override |
119 | { |
120 | return label_text::borrow (buffer: m_text); |
121 | } |
122 | |
123 | private: |
124 | const char *m_text; |
125 | }; |
126 | |
127 | /* Concrete subclass of libcpp's range_label for use in |
128 | diagnostics involving mismatched types. |
129 | |
130 | Each frontend that uses this should supply its own implementation. |
131 | |
132 | Generate a label describing LABELLED_TYPE. The frontend may use |
133 | OTHER_TYPE where appropriate for highlighting the differences between |
134 | the two types (analogous to C++'s use of %H and %I with |
135 | template types). |
136 | |
137 | Either or both of LABELLED_TYPE and OTHER_TYPE may be NULL_TREE. |
138 | If LABELLED_TYPE is NULL_TREE, then there is no label. |
139 | |
140 | For example, this rich_location could use two instances of |
141 | range_label_for_type_mismatch: |
142 | |
143 | printf ("arg0: %i arg1: %s arg2: %i", |
144 | ^~ |
145 | | |
146 | const char * |
147 | 100, 101, 102); |
148 | ~~~ |
149 | | |
150 | int |
151 | |
152 | (a) the label for "%s" with LABELLED_TYPE for "const char*" and |
153 | (b) the label for "101" with LABELLED TYPE for "int" |
154 | where each one uses the other's type as OTHER_TYPE. */ |
155 | |
156 | class range_label_for_type_mismatch : public range_label |
157 | { |
158 | public: |
159 | range_label_for_type_mismatch (tree labelled_type, tree other_type) |
160 | : m_labelled_type (labelled_type), m_other_type (other_type) |
161 | { |
162 | } |
163 | |
164 | label_text get_text (unsigned range_idx) const override; |
165 | |
166 | protected: |
167 | tree m_labelled_type; |
168 | tree m_other_type; |
169 | }; |
170 | |
171 | /* Subclass of range_label for labelling the type of EXPR when reporting |
172 | a type mismatch between EXPR and OTHER_EXPR. |
173 | Either or both of EXPR and OTHER_EXPR could be NULL. */ |
174 | |
175 | class maybe_range_label_for_tree_type_mismatch : public range_label |
176 | { |
177 | public: |
178 | maybe_range_label_for_tree_type_mismatch (tree expr, tree other_expr) |
179 | : m_expr (expr), m_other_expr (other_expr) |
180 | { |
181 | } |
182 | |
183 | label_text get_text (unsigned range_idx) const final override; |
184 | |
185 | private: |
186 | tree m_expr; |
187 | tree m_other_expr; |
188 | }; |
189 | |
190 | class op_location_t; |
191 | |
192 | /* A subclass of rich_location for showing problems with binary operations. |
193 | |
194 | If enough location information is available, the ctor will make a |
195 | 3-location rich_location of the form: |
196 | |
197 | arg_0 op arg_1 |
198 | ~~~~~ ^~ ~~~~~ |
199 | | | |
200 | | arg1 type |
201 | arg0 type |
202 | |
203 | labelling the types of the arguments if SHOW_TYPES is true. |
204 | |
205 | Otherwise, it will fall back to a 1-location rich_location using the |
206 | compound location within LOC: |
207 | |
208 | arg_0 op arg_1 |
209 | ~~~~~~^~~~~~~~ |
210 | |
211 | for which we can't label the types. */ |
212 | |
213 | class binary_op_rich_location : public gcc_rich_location |
214 | { |
215 | public: |
216 | binary_op_rich_location (const op_location_t &loc, |
217 | tree arg0, tree arg1, |
218 | bool show_types); |
219 | |
220 | private: |
221 | static bool use_operator_loc_p (const op_location_t &loc, |
222 | tree arg0, tree arg1); |
223 | |
224 | maybe_range_label_for_tree_type_mismatch m_label_for_arg0; |
225 | maybe_range_label_for_tree_type_mismatch m_label_for_arg1; |
226 | }; |
227 | |
228 | #endif /* GCC_RICH_LOCATION_H */ |
229 | |