1 | /* Prints out trees in human readable form. |
2 | Copyright (C) 1992-2023 Free Software Foundation, Inc. |
3 | Hacked by Michael Tiemann (tiemann@cygnus.com) |
4 | |
5 | This file is part of GCC. |
6 | |
7 | GCC is free software; you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by |
9 | the Free Software Foundation; either version 3, or (at your option) |
10 | any later version. |
11 | |
12 | GCC is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | GNU General Public License for more details. |
16 | |
17 | You should have received a copy of the GNU General Public License |
18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. */ |
20 | |
21 | |
22 | #include "config.h" |
23 | #include "system.h" |
24 | #include "coretypes.h" |
25 | #include "cp-tree.h" |
26 | #include "print-tree.h" |
27 | |
28 | void |
29 | cxx_print_decl (FILE *file, tree node, int indent) |
30 | { |
31 | if (TREE_CODE (node) == FIELD_DECL) |
32 | { |
33 | if (DECL_MUTABLE_P (node)) |
34 | { |
35 | indent_to (file, indent + 3); |
36 | fprintf (stream: file, format: " mutable " ); |
37 | } |
38 | return; |
39 | } |
40 | |
41 | if (TREE_CODE (node) == FUNCTION_DECL) |
42 | { |
43 | int flags = TFF_DECL_SPECIFIERS|TFF_RETURN_TYPE |
44 | |TFF_FUNCTION_DEFAULT_ARGUMENTS|TFF_EXCEPTION_SPECIFICATION ; |
45 | indent_to (file, indent + 3); |
46 | fprintf (stream: file, format: " full-name \"%s\"" , decl_as_string (node, flags)); |
47 | } |
48 | else if (TREE_CODE (node) == TEMPLATE_DECL) |
49 | { |
50 | print_node (file, "result" , DECL_TEMPLATE_RESULT (node), indent + 4); |
51 | print_node (file, "parms" , DECL_TEMPLATE_PARMS (node), indent + 4); |
52 | indent_to (file, indent + 3); |
53 | fprintf (stream: file, format: " full-name \"%s\"" , |
54 | decl_as_string (node, TFF_TEMPLATE_HEADER)); |
55 | } |
56 | |
57 | bool need_indent = true; |
58 | |
59 | tree ntnode = STRIP_TEMPLATE (node); |
60 | if (TREE_CODE (ntnode) == FUNCTION_DECL |
61 | || TREE_CODE (ntnode) == VAR_DECL |
62 | || TREE_CODE (ntnode) == TYPE_DECL |
63 | || TREE_CODE (ntnode) == CONCEPT_DECL |
64 | || TREE_CODE (ntnode) == NAMESPACE_DECL) |
65 | { |
66 | unsigned m = 0; |
67 | if (DECL_LANG_SPECIFIC (ntnode) && DECL_MODULE_IMPORT_P (ntnode)) |
68 | m = get_importing_module (ntnode, true); |
69 | |
70 | if (const char *name = m == ~0u ? "" : module_name (m, header_ok: true)) |
71 | { |
72 | if (need_indent) |
73 | indent_to (file, indent + 3); |
74 | fprintf (stream: file, format: " module %d:%s" , m, name); |
75 | need_indent = false; |
76 | } |
77 | |
78 | if (DECL_LANG_SPECIFIC (ntnode)) |
79 | { |
80 | if (DECL_MODULE_PURVIEW_P (ntnode)) |
81 | { |
82 | if (need_indent) |
83 | indent_to (file, indent + 3); |
84 | fprintf (stream: file, format: " purview" ); |
85 | need_indent = false; |
86 | } |
87 | if (DECL_MODULE_ATTACH_P (ntnode)) |
88 | { |
89 | if (need_indent) |
90 | indent_to (file, indent + 3); |
91 | fprintf (stream: file, format: " attached" ); |
92 | need_indent = false; |
93 | } |
94 | } |
95 | } |
96 | |
97 | if (DECL_MODULE_EXPORT_P (node)) |
98 | { |
99 | if (need_indent) |
100 | indent_to (file, indent + 3); |
101 | fprintf (stream: file, format: " exported" ); |
102 | need_indent = false; |
103 | } |
104 | |
105 | if (!CODE_CONTAINS_STRUCT (TREE_CODE (node), TS_DECL_COMMON) |
106 | || !DECL_LANG_SPECIFIC (node)) |
107 | return; |
108 | |
109 | if (DECL_EXTERNAL (node) && DECL_NOT_REALLY_EXTERN (node)) |
110 | { |
111 | if (need_indent) |
112 | indent_to (file, indent + 3); |
113 | fprintf (stream: file, format: " not-really-extern" ); |
114 | need_indent = false; |
115 | } |
116 | |
117 | if (TREE_CODE (node) == FUNCTION_DECL |
118 | && DECL_PENDING_INLINE_INFO (node)) |
119 | { |
120 | if (need_indent) |
121 | indent_to (file, indent + 3); |
122 | fprintf (stream: file, format: " pending-inline-info %p" , |
123 | (void *) DECL_PENDING_INLINE_INFO (node)); |
124 | need_indent = false; |
125 | } |
126 | |
127 | if ((VAR_OR_FUNCTION_DECL_P (node) |
128 | || TREE_CODE (node) == FIELD_DECL |
129 | || TREE_CODE (node) == TYPE_DECL |
130 | || TREE_CODE (node) == CONCEPT_DECL |
131 | || TREE_CODE (node) == TEMPLATE_DECL) |
132 | && DECL_TEMPLATE_INFO (node)) |
133 | { |
134 | print_node (file, "template-info" , DECL_TEMPLATE_INFO (node), |
135 | indent + 4); |
136 | indent_to (file, indent + 3); |
137 | fprintf (stream: file, format: " use_template=%d" , DECL_USE_TEMPLATE (node)); |
138 | } |
139 | } |
140 | |
141 | void |
142 | cxx_print_type (FILE *file, tree node, int indent) |
143 | { |
144 | if (tree ti = TYPE_TEMPLATE_INFO (node)) |
145 | print_node (file, "template-info" , ti, indent + 4); |
146 | |
147 | switch (TREE_CODE (node)) |
148 | { |
149 | case BOUND_TEMPLATE_TEMPLATE_PARM: |
150 | case TEMPLATE_TYPE_PARM: |
151 | case TEMPLATE_TEMPLATE_PARM: |
152 | print_node (file, "tpi" , TEMPLATE_TYPE_PARM_INDEX (node), indent + 4); |
153 | return; |
154 | |
155 | case FUNCTION_TYPE: |
156 | case METHOD_TYPE: |
157 | if (TYPE_RAISES_EXCEPTIONS (node)) |
158 | print_node (file, "throws" , TYPE_RAISES_EXCEPTIONS (node), indent + 4); |
159 | return; |
160 | |
161 | case RECORD_TYPE: |
162 | case UNION_TYPE: |
163 | break; |
164 | |
165 | case DECLTYPE_TYPE: |
166 | print_node (file, "expr" , DECLTYPE_TYPE_EXPR (node), indent + 4); |
167 | return; |
168 | |
169 | case DEPENDENT_OPERATOR_TYPE: |
170 | print_node (file, "saved_lookups" , |
171 | DEPENDENT_OPERATOR_TYPE_SAVED_LOOKUPS (node), |
172 | indent + 4); |
173 | return; |
174 | |
175 | case TYPENAME_TYPE: |
176 | print_node (file, "fullname" , TYPENAME_TYPE_FULLNAME (node), |
177 | indent + 4); |
178 | return; |
179 | |
180 | case TYPEOF_TYPE: |
181 | print_node (file, "expr" , TYPEOF_TYPE_EXPR (node), indent + 4); |
182 | return; |
183 | |
184 | case BASES: |
185 | if (BASES_DIRECT (node)) |
186 | fputs (s: " direct" , stream: file); |
187 | print_node (file, "type" , BASES_TYPE (node), indent + 4); |
188 | return; |
189 | |
190 | case TYPE_PACK_EXPANSION: |
191 | print_node (file, "pattern" , PACK_EXPANSION_PATTERN (node), indent + 4); |
192 | print_node (file, "args" , PACK_EXPANSION_EXTRA_ARGS (node), indent + 4); |
193 | return; |
194 | |
195 | default: |
196 | return; |
197 | } |
198 | |
199 | if (TYPE_PTRMEMFUNC_P (node)) |
200 | print_node (file, "ptrmemfunc fn type" , TYPE_PTRMEMFUNC_FN_TYPE (node), |
201 | indent + 4); |
202 | |
203 | if (! CLASS_TYPE_P (node)) |
204 | return; |
205 | |
206 | indent_to (file, indent + 4); |
207 | fprintf (stream: file, format: "full-name \"%s\"" , |
208 | type_as_string (node, TFF_CLASS_KEY_OR_ENUM)); |
209 | |
210 | indent_to (file, indent + 3); |
211 | |
212 | if (TYPE_NEEDS_CONSTRUCTING (node)) |
213 | fputs ( s: " needs-constructor" , stream: file); |
214 | if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (node)) |
215 | fputs (s: " needs-destructor" , stream: file); |
216 | if (TYPE_HAS_DEFAULT_CONSTRUCTOR (node)) |
217 | fputs (s: " X()" , stream: file); |
218 | if (TYPE_HAS_CONVERSION (node)) |
219 | fputs (s: " has-type-conversion" , stream: file); |
220 | if (TYPE_HAS_COPY_CTOR (node)) |
221 | { |
222 | if (TYPE_HAS_CONST_COPY_CTOR (node)) |
223 | fputs (s: " X(constX&)" , stream: file); |
224 | else |
225 | fputs (s: " X(X&)" , stream: file); |
226 | } |
227 | if (TYPE_HAS_NEW_OPERATOR (node)) |
228 | fputs (s: " new" , stream: file); |
229 | if (TYPE_HAS_ARRAY_NEW_OPERATOR (node)) |
230 | fputs (s: " new[]" , stream: file); |
231 | if (TYPE_GETS_DELETE (node) & 1) |
232 | fputs (s: " delete" , stream: file); |
233 | if (TYPE_GETS_DELETE (node) & 2) |
234 | fputs (s: " delete[]" , stream: file); |
235 | if (TYPE_HAS_COPY_ASSIGN (node)) |
236 | fputs (s: " this=(X&)" , stream: file); |
237 | |
238 | if (TREE_CODE (node) == RECORD_TYPE) |
239 | { |
240 | if (TYPE_BINFO (node)) |
241 | fprintf (stream: file, format: " n_parents=%d" , |
242 | BINFO_N_BASE_BINFOS (TYPE_BINFO (node))); |
243 | else |
244 | fprintf (stream: file, format: " no-binfo" ); |
245 | |
246 | fprintf (stream: file, format: " use_template=%d" , CLASSTYPE_USE_TEMPLATE (node)); |
247 | if (CLASSTYPE_INTERFACE_ONLY (node)) |
248 | fprintf (stream: file, format: " interface-only" ); |
249 | if (CLASSTYPE_INTERFACE_UNKNOWN (node)) |
250 | fprintf (stream: file, format: " interface-unknown" ); |
251 | } |
252 | } |
253 | |
254 | void |
255 | cxx_print_identifier (FILE *file, tree node, int indent) |
256 | { |
257 | if (indent == 0) |
258 | fprintf (stream: file, format: " " ); |
259 | else |
260 | indent_to (file, indent + 4); |
261 | fprintf (stream: file, format: "%s local bindings <%p>" , get_identifier_kind_name (node), |
262 | (void *) IDENTIFIER_BINDING (node)); |
263 | } |
264 | |
265 | void |
266 | cxx_print_lambda_node (FILE *file, tree node, int indent) |
267 | { |
268 | if (LAMBDA_EXPR_MUTABLE_P (node)) |
269 | fprintf (stream: file, format: " /mutable" ); |
270 | fprintf (stream: file, format: " default_capture_mode=[" ); |
271 | switch (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (node)) |
272 | { |
273 | case CPLD_NONE: |
274 | fprintf (stream: file, format: "NONE" ); |
275 | break; |
276 | case CPLD_COPY: |
277 | fprintf (stream: file, format: "COPY" ); |
278 | break; |
279 | case CPLD_REFERENCE: |
280 | fprintf (stream: file, format: "CPLD_REFERENCE" ); |
281 | break; |
282 | default: |
283 | fprintf (stream: file, format: "??" ); |
284 | break; |
285 | } |
286 | fprintf (stream: file, format: "] " ); |
287 | print_node (file, "capture_list" , LAMBDA_EXPR_CAPTURE_LIST (node), indent + 4); |
288 | print_node (file, "this_capture" , LAMBDA_EXPR_THIS_CAPTURE (node), indent + 4); |
289 | } |
290 | |
291 | void |
292 | cxx_print_xnode (FILE *file, tree node, int indent) |
293 | { |
294 | switch (TREE_CODE (node)) |
295 | { |
296 | case BASELINK: |
297 | print_node (file, "functions" , BASELINK_FUNCTIONS (node), indent + 4); |
298 | print_node (file, "binfo" , BASELINK_BINFO (node), indent + 4); |
299 | print_node (file, "access_binfo" , BASELINK_ACCESS_BINFO (node), |
300 | indent + 4); |
301 | print_node (file, "optype" , BASELINK_OPTYPE (node), indent + 4); |
302 | break; |
303 | case OVERLOAD: |
304 | print_node (file, "function" , OVL_FUNCTION (node), indent + 4); |
305 | print_node (file, "next" , OVL_CHAIN (node), indent + 4); |
306 | break; |
307 | case BINDING_VECTOR: |
308 | { |
309 | unsigned len = BINDING_VECTOR_NUM_CLUSTERS (node); |
310 | print_node (file, "name" , BINDING_VECTOR_NAME (node), indent + 4); |
311 | fprintf (stream: file, format: " clusters %u, alloc %u" , len, |
312 | BINDING_VECTOR_ALLOC_CLUSTERS (node)); |
313 | for (unsigned ix = 0; ix != len; ix++) |
314 | { |
315 | binding_cluster *cluster = &BINDING_VECTOR_CLUSTER (node, ix); |
316 | char pfx[32]; |
317 | for (unsigned jx = 0; jx != BINDING_VECTOR_SLOTS_PER_CLUSTER; jx++) |
318 | if (cluster->indices[jx].span) |
319 | { |
320 | int len = sprintf (s: pfx, format: "module:%u" , |
321 | cluster->indices[jx].base); |
322 | if (cluster->indices[jx].span > 1) |
323 | len += sprintf (s: &pfx[len], format: "(+%u)" , |
324 | cluster->indices[jx].span); |
325 | len += sprintf (s: &pfx[len], format: " cluster:%u/%u" , ix, jx); |
326 | binding_slot &slot = cluster->slots[jx]; |
327 | if (slot.is_lazy ()) |
328 | { |
329 | indent_to (file, indent + 4); |
330 | unsigned lazy = slot.get_lazy (); |
331 | fprintf (stream: file, format: "%s snum:%u" , pfx, lazy); |
332 | } |
333 | else if (slot) |
334 | print_node (file, pfx, slot, indent + 4); |
335 | else |
336 | { |
337 | indent_to (file, indent + 4); |
338 | fprintf (stream: file, format: "%s NULL" , pfx); |
339 | } |
340 | } |
341 | } |
342 | } |
343 | break; |
344 | case TEMPLATE_PARM_INDEX: |
345 | print_node (file, "decl" , TEMPLATE_PARM_DECL (node), indent+4); |
346 | indent_to (file, indent + 3); |
347 | fprintf (stream: file, format: "index %d level %d orig_level %d" , |
348 | TEMPLATE_PARM_IDX (node), TEMPLATE_PARM_LEVEL (node), |
349 | TEMPLATE_PARM_ORIG_LEVEL (node)); |
350 | break; |
351 | case TEMPLATE_INFO: |
352 | print_node (file, "template" , TI_TEMPLATE (node), indent+4); |
353 | print_node (file, "args" , TI_ARGS (node), indent+4); |
354 | if (TI_TEMPLATE (node) |
355 | && PRIMARY_TEMPLATE_P (TI_TEMPLATE (node))) |
356 | print_node (file, "partial" , TI_PARTIAL_INFO (node), indent+4); |
357 | if (TI_PENDING_TEMPLATE_FLAG (node)) |
358 | { |
359 | indent_to (file, indent + 3); |
360 | fprintf (stream: file, format: "pending_template" ); |
361 | } |
362 | break; |
363 | case CONSTRAINT_INFO: |
364 | { |
365 | tree_constraint_info *cinfo = (tree_constraint_info *)node; |
366 | if (cinfo->template_reqs) |
367 | print_node (file, "template_reqs" , cinfo->template_reqs, indent+4); |
368 | if (cinfo->declarator_reqs) |
369 | print_node (file, "declarator_reqs" , cinfo->declarator_reqs, |
370 | indent+4); |
371 | print_node (file, "associated_constr" , |
372 | cinfo->associated_constr, indent+4); |
373 | break; |
374 | } |
375 | case ARGUMENT_PACK_SELECT: |
376 | print_node (file, "pack" , ARGUMENT_PACK_SELECT_FROM_PACK (node), |
377 | indent+4); |
378 | indent_to (file, indent + 3); |
379 | fprintf (stream: file, format: "index %d" , ARGUMENT_PACK_SELECT_INDEX (node)); |
380 | break; |
381 | case DEFERRED_NOEXCEPT: |
382 | print_node (file, "pattern" , DEFERRED_NOEXCEPT_PATTERN (node), indent+4); |
383 | print_node (file, "args" , DEFERRED_NOEXCEPT_ARGS (node), indent+4); |
384 | break; |
385 | case TRAIT_EXPR: |
386 | indent_to (file, indent+4); |
387 | fprintf (stream: file, format: "kind %d" , TRAIT_EXPR_KIND (node)); |
388 | print_node (file, "type 1" , TRAIT_EXPR_TYPE1 (node), indent+4); |
389 | if (TRAIT_EXPR_TYPE2 (node)) |
390 | print_node (file, "type 2" , TRAIT_EXPR_TYPE2 (node), indent+4); |
391 | break; |
392 | case LAMBDA_EXPR: |
393 | cxx_print_lambda_node (file, node, indent); |
394 | break; |
395 | case STATIC_ASSERT: |
396 | if (location_t loc = STATIC_ASSERT_SOURCE_LOCATION (node)) |
397 | { |
398 | expanded_location xloc = expand_location (loc); |
399 | indent_to (file, indent+4); |
400 | fprintf (stream: file, format: "%s:%d:%d" , xloc.file, xloc.line, xloc.column); |
401 | } |
402 | print_node (file, "condition" , STATIC_ASSERT_CONDITION (node), indent+4); |
403 | if (tree message = STATIC_ASSERT_MESSAGE (node)) |
404 | print_node (file, "message" , message, indent+4); |
405 | break; |
406 | case PTRMEM_CST: |
407 | print_node (file, "member" , PTRMEM_CST_MEMBER (node), indent+4); |
408 | break; |
409 | default: |
410 | break; |
411 | } |
412 | } |
413 | |
414 | /* Print the node NODE on standard error, for debugging. */ |
415 | |
416 | DEBUG_FUNCTION void |
417 | debug_tree (cp_expr node) |
418 | { |
419 | debug_tree (node.get_value()); |
420 | } |
421 | |
422 | DEBUG_FUNCTION void |
423 | debug_overload (tree node) |
424 | { |
425 | FILE *file = stdout; |
426 | |
427 | for (lkp_iterator iter (node); iter; ++iter) |
428 | { |
429 | tree decl = *iter; |
430 | auto xloc = expand_location (DECL_SOURCE_LOCATION (decl)); |
431 | auto fullname = decl_as_string (decl, 0); |
432 | bool using_p = iter.using_p (); |
433 | bool hidden_p = iter.hidden_p (); |
434 | |
435 | fprintf (stream: file, format: "%p:%c%c %s:%d:%d \"%s\"\n" , (void *)decl, |
436 | hidden_p ? 'H' : '-', |
437 | using_p ? 'U' : '-', |
438 | xloc.file, xloc.line, xloc.column, fullname); |
439 | } |
440 | } |
441 | |