Mercurial > hg > CbC > CbC_gcc
annotate gcc/tree-diagnostic.c @ 158:494b0b89df80 default tip
...
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 18:13:55 +0900 |
parents | 1830386684a0 |
children |
rev | line source |
---|---|
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1 /* Language-independent diagnostic subroutines for the GNU Compiler |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
2 Collection that are only for use in the compilers proper and not |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
3 the driver or other programs. |
145 | 4 Copyright (C) 1999-2020 Free Software Foundation, Inc. |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
5 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
6 This file is part of GCC. |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
7 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
8 GCC is free software; you can redistribute it and/or modify it under |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
9 the terms of the GNU General Public License as published by the Free |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
10 Software Foundation; either version 3, or (at your option) any later |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
11 version. |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
12 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
16 for more details. |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
17 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
18 You should have received a copy of the GNU General Public License |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
19 along with GCC; see the file COPYING3. If not see |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
20 <http://www.gnu.org/licenses/>. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
21 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
22 #include "config.h" |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
23 #include "system.h" |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
24 #include "coretypes.h" |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
25 #include "tree.h" |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
26 #include "diagnostic.h" |
111 | 27 #include "tree-pretty-print.h" |
28 #include "gimple-pretty-print.h" | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
29 #include "tree-diagnostic.h" |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
30 #include "langhooks.h" |
111 | 31 #include "intl.h" |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
32 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
33 /* Prints out, if necessary, the name of the current function |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
34 that caused an error. Called from all error and warning functions. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
35 void |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
36 diagnostic_report_current_function (diagnostic_context *context, |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
37 diagnostic_info *diagnostic) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
38 { |
111 | 39 diagnostic_report_current_module (context, diagnostic_location (diagnostic)); |
40 lang_hooks.print_error_function (context, LOCATION_FILE (input_location), | |
41 diagnostic); | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
42 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
43 |
111 | 44 static void |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
45 default_tree_diagnostic_starter (diagnostic_context *context, |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
46 diagnostic_info *diagnostic) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
47 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
48 diagnostic_report_current_function (context, diagnostic); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
49 pp_set_prefix (context->printer, diagnostic_build_prefix (context, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
50 diagnostic)); |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
51 } |
111 | 52 |
53 /* This is a pair made of a location and the line map it originated | |
54 from. It's used in the maybe_unwind_expanded_macro_loc function | |
55 below. */ | |
56 struct loc_map_pair | |
57 { | |
58 const line_map_macro *map; | |
145 | 59 location_t where; |
111 | 60 }; |
61 | |
62 | |
63 /* Unwind the different macro expansions that lead to the token which | |
64 location is WHERE and emit diagnostics showing the resulting | |
65 unwound macro expansion trace. Let's look at an example to see how | |
66 the trace looks like. Suppose we have this piece of code, | |
67 artificially annotated with the line numbers to increase | |
68 legibility: | |
69 | |
70 $ cat -n test.c | |
71 1 #define OPERATE(OPRD1, OPRT, OPRD2) \ | |
72 2 OPRD1 OPRT OPRD2; | |
73 3 | |
74 4 #define SHIFTL(A,B) \ | |
75 5 OPERATE (A,<<,B) | |
76 6 | |
77 7 #define MULT(A) \ | |
78 8 SHIFTL (A,1) | |
79 9 | |
80 10 void | |
81 11 g () | |
82 12 { | |
83 13 MULT (1.0);// 1.0 << 1; <-- so this is an error. | |
84 14 } | |
85 | |
86 Here is the diagnostic that we want the compiler to generate: | |
87 | |
88 test.c: In function ‘g’: | |
89 test.c:5:14: error: invalid operands to binary << (have ‘double’ and ‘int’) | |
90 test.c:2:9: note: in definition of macro 'OPERATE' | |
91 test.c:8:3: note: in expansion of macro 'SHIFTL' | |
92 test.c:13:3: note: in expansion of macro 'MULT' | |
93 | |
94 The part that goes from the third to the fifth line of this | |
95 diagnostic (the lines containing the 'note:' string) is called the | |
96 unwound macro expansion trace. That's the part generated by this | |
97 function. */ | |
98 | |
145 | 99 void |
111 | 100 maybe_unwind_expanded_macro_loc (diagnostic_context *context, |
145 | 101 location_t where) |
111 | 102 { |
103 const struct line_map *map; | |
104 auto_vec<loc_map_pair> loc_vec; | |
105 unsigned ix; | |
106 loc_map_pair loc, *iter; | |
107 | |
145 | 108 const location_t original_loc = where; |
109 | |
111 | 110 map = linemap_lookup (line_table, where); |
111 if (!linemap_macro_expansion_map_p (map)) | |
112 return; | |
113 | |
114 /* Let's unwind the macros that got expanded and led to the token | |
115 which location is WHERE. We are going to store these macros into | |
116 LOC_VEC, so that we can later walk it at our convenience to | |
117 display a somewhat meaningful trace of the macro expansion | |
118 history to the user. Note that the first macro of the trace | |
119 (which is OPERATE in the example above) is going to be stored at | |
120 the beginning of LOC_VEC. */ | |
121 | |
122 do | |
123 { | |
124 loc.where = where; | |
125 loc.map = linemap_check_macro (map); | |
126 | |
127 loc_vec.safe_push (loc); | |
128 | |
129 /* WHERE is the location of a token inside the expansion of a | |
130 macro. MAP is the map holding the locations of that macro | |
131 expansion. Let's get the location of the token inside the | |
132 context that triggered the expansion of this macro. | |
133 This is basically how we go "down" in the trace of macro | |
134 expansions that led to WHERE. */ | |
135 where = linemap_unwind_toward_expansion (line_table, where, &map); | |
136 } while (linemap_macro_expansion_map_p (map)); | |
137 | |
138 /* Now map is set to the map of the location in the source that | |
139 first triggered the macro expansion. This must be an ordinary map. */ | |
140 const line_map_ordinary *ord_map = linemap_check_ordinary (map); | |
141 | |
142 /* Walk LOC_VEC and print the macro expansion trace, unless the | |
143 first macro which expansion triggered this trace was expanded | |
144 inside a system header. */ | |
145 int saved_location_line = | |
145 | 146 expand_location_to_spelling_point (original_loc).line; |
111 | 147 |
148 if (!LINEMAP_SYSP (ord_map)) | |
149 FOR_EACH_VEC_ELT (loc_vec, ix, iter) | |
150 { | |
151 /* Sometimes, in the unwound macro expansion trace, we want to | |
152 print a part of the context that shows where, in the | |
153 definition of the relevant macro, is the token (we are | |
154 looking at) used. That is the case in the introductory | |
155 comment of this function, where we print: | |
156 | |
157 test.c:2:9: note: in definition of macro 'OPERATE'. | |
158 | |
159 We print that "macro definition context" because the | |
160 diagnostic line (emitted by the call to | |
161 pp_ouput_formatted_text in diagnostic_report_diagnostic): | |
162 | |
163 test.c:5:14: error: invalid operands to binary << (have ‘double’ and ‘int’) | |
164 | |
165 does not point into the definition of the macro where the | |
166 token '<<' (that is an argument to the function-like macro | |
167 OPERATE) is used. So we must "display" the line of that | |
168 macro definition context to the user somehow. | |
169 | |
170 A contrario, when the first interesting diagnostic line | |
171 points into the definition of the macro, we don't need to | |
172 display any line for that macro definition in the trace | |
173 anymore, otherwise it'd be redundant. */ | |
174 | |
175 /* Okay, now here is what we want. For each token resulting | |
176 from macro expansion we want to show: 1/ where in the | |
177 definition of the macro the token comes from; 2/ where the | |
178 macro got expanded. */ | |
179 | |
180 /* Resolve the location iter->where into the locus 1/ of the | |
181 comment above. */ | |
145 | 182 location_t resolved_def_loc = |
111 | 183 linemap_resolve_location (line_table, iter->where, |
184 LRK_MACRO_DEFINITION_LOCATION, NULL); | |
185 | |
186 /* Don't print trace for locations that are reserved or from | |
187 within a system header. */ | |
188 const line_map_ordinary *m = NULL; | |
145 | 189 location_t l = |
111 | 190 linemap_resolve_location (line_table, resolved_def_loc, |
191 LRK_SPELLING_LOCATION, &m); | |
192 if (l < RESERVED_LOCATION_COUNT || LINEMAP_SYSP (m)) | |
193 continue; | |
194 | |
195 /* We need to print the context of the macro definition only | |
196 when the locus of the first displayed diagnostic (displayed | |
197 before this trace) was inside the definition of the | |
198 macro. */ | |
199 int resolved_def_loc_line = SOURCE_LINE (m, l); | |
200 if (ix == 0 && saved_location_line != resolved_def_loc_line) | |
201 { | |
202 diagnostic_append_note (context, resolved_def_loc, | |
203 "in definition of macro %qs", | |
204 linemap_map_get_macro_name (iter->map)); | |
205 /* At this step, as we've printed the context of the macro | |
206 definition, we don't want to print the context of its | |
207 expansion, otherwise, it'd be redundant. */ | |
208 continue; | |
209 } | |
210 | |
211 /* Resolve the location of the expansion point of the macro | |
212 which expansion gave the token represented by def_loc. | |
213 This is the locus 2/ of the earlier comment. */ | |
145 | 214 location_t resolved_exp_loc = |
111 | 215 linemap_resolve_location (line_table, |
216 MACRO_MAP_EXPANSION_POINT_LOCATION (iter->map), | |
217 LRK_MACRO_DEFINITION_LOCATION, NULL); | |
218 | |
219 diagnostic_append_note (context, resolved_exp_loc, | |
220 "in expansion of macro %qs", | |
221 linemap_map_get_macro_name (iter->map)); | |
222 } | |
223 } | |
224 | |
225 /* This is a diagnostic finalizer implementation that is aware of | |
226 virtual locations produced by libcpp. | |
227 | |
228 It has to be called by the diagnostic finalizer of front ends that | |
229 uses libcpp and wish to get diagnostics involving tokens resulting | |
230 from macro expansion. | |
231 | |
232 For a given location, if said location belongs to a token | |
233 resulting from a macro expansion, this starter prints the context | |
234 of the token. E.g, for multiply nested macro expansion, it | |
235 unwinds the nested macro expansions and prints them in a manner | |
236 that is similar to what is done for function call stacks, or | |
237 template instantiation contexts. */ | |
238 void | |
239 virt_loc_aware_diagnostic_finalizer (diagnostic_context *context, | |
240 diagnostic_info *diagnostic) | |
241 { | |
145 | 242 maybe_unwind_expanded_macro_loc (context, diagnostic_location (diagnostic)); |
111 | 243 } |
244 | |
245 /* Default tree printer. Handles declarations only. */ | |
246 bool | |
247 default_tree_printer (pretty_printer *pp, text_info *text, const char *spec, | |
248 int precision, bool wide, bool set_locus, bool hash, | |
131 | 249 bool *, const char **) |
111 | 250 { |
251 tree t; | |
252 | |
253 /* FUTURE: %+x should set the locus. */ | |
254 if (precision != 0 || wide || hash) | |
255 return false; | |
256 | |
257 switch (*spec) | |
258 { | |
259 case 'E': | |
260 t = va_arg (*text->args_ptr, tree); | |
261 if (TREE_CODE (t) == IDENTIFIER_NODE) | |
262 { | |
263 pp_identifier (pp, IDENTIFIER_POINTER (t)); | |
264 return true; | |
265 } | |
266 break; | |
267 | |
268 case 'D': | |
269 t = va_arg (*text->args_ptr, tree); | |
270 if (VAR_P (t) && DECL_HAS_DEBUG_EXPR_P (t)) | |
271 t = DECL_DEBUG_EXPR (t); | |
272 break; | |
273 | |
274 case 'F': | |
275 case 'T': | |
276 t = va_arg (*text->args_ptr, tree); | |
277 break; | |
278 | |
279 case 'G': | |
280 percent_G_format (text); | |
281 return true; | |
282 | |
283 case 'K': | |
284 t = va_arg (*text->args_ptr, tree); | |
131 | 285 percent_K_format (text, EXPR_LOCATION (t), TREE_BLOCK (t)); |
111 | 286 return true; |
287 | |
288 default: | |
289 return false; | |
290 } | |
291 | |
292 if (set_locus) | |
131 | 293 text->set_location (0, DECL_SOURCE_LOCATION (t), SHOW_RANGE_WITH_CARET); |
111 | 294 |
295 if (DECL_P (t)) | |
296 { | |
297 const char *n = DECL_NAME (t) | |
298 ? identifier_to_locale (lang_hooks.decl_printable_name (t, 2)) | |
299 : _("<anonymous>"); | |
300 pp_string (pp, n); | |
301 } | |
302 else | |
303 dump_generic_node (pp, t, 0, TDF_SLIM, 0); | |
304 | |
305 return true; | |
306 } | |
307 | |
308 /* Sets CONTEXT to use language independent diagnostics. */ | |
309 void | |
310 tree_diagnostics_defaults (diagnostic_context *context) | |
311 { | |
312 diagnostic_starter (context) = default_tree_diagnostic_starter; | |
313 diagnostic_finalizer (context) = default_diagnostic_finalizer; | |
314 diagnostic_format_decoder (context) = default_tree_printer; | |
145 | 315 context->print_path = default_tree_diagnostic_path_printer; |
316 context->make_json_for_path = default_tree_make_json_for_path; | |
111 | 317 } |