1 | /* Subroutines common to both C and C++ pretty-printers. |
2 | Copyright (C) 2002-2023 Free Software Foundation, Inc. |
3 | Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net> |
4 | |
5 | This file is part of GCC. |
6 | |
7 | GCC is free software; you can redistribute it and/or modify it under |
8 | the terms of the GNU General Public License as published by the Free |
9 | Software Foundation; either version 3, or (at your option) any later |
10 | version. |
11 | |
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
15 | 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 | #include "config.h" |
22 | #include "system.h" |
23 | #include "coretypes.h" |
24 | #include "c-pretty-print.h" |
25 | #include "gimple-pretty-print.h" |
26 | #include "diagnostic.h" |
27 | #include "stor-layout.h" |
28 | #include "stringpool.h" |
29 | #include "attribs.h" |
30 | #include "intl.h" |
31 | #include "tree-pretty-print.h" |
32 | #include "selftest.h" |
33 | #include "langhooks.h" |
34 | #include "options.h" |
35 | #include "internal-fn.h" |
36 | #include "function.h" |
37 | #include "basic-block.h" |
38 | #include "gimple.h" |
39 | |
40 | /* The pretty-printer code is primarily designed to closely follow |
41 | (GNU) C and C++ grammars. That is to be contrasted with spaghetti |
42 | codes we used to have in the past. Following a structured |
43 | approach (preferably the official grammars) is believed to make it |
44 | much easier to add extensions and nifty pretty-printing effects that |
45 | takes expression or declaration contexts into account. */ |
46 | |
47 | |
48 | #define pp_c_maybe_whitespace(PP) \ |
49 | do { \ |
50 | if ((PP)->padding == pp_before) \ |
51 | pp_c_whitespace (PP); \ |
52 | } while (0) |
53 | |
54 | /* literal */ |
55 | static void pp_c_char (c_pretty_printer *, int); |
56 | |
57 | /* postfix-expression */ |
58 | static void pp_c_initializer_list (c_pretty_printer *, tree); |
59 | static void pp_c_brace_enclosed_initializer_list (c_pretty_printer *, tree); |
60 | |
61 | static void pp_c_additive_expression (c_pretty_printer *, tree); |
62 | static void pp_c_shift_expression (c_pretty_printer *, tree); |
63 | static void pp_c_relational_expression (c_pretty_printer *, tree); |
64 | static void pp_c_equality_expression (c_pretty_printer *, tree); |
65 | static void pp_c_and_expression (c_pretty_printer *, tree); |
66 | static void pp_c_exclusive_or_expression (c_pretty_printer *, tree); |
67 | static void pp_c_inclusive_or_expression (c_pretty_printer *, tree); |
68 | static void pp_c_logical_and_expression (c_pretty_printer *, tree); |
69 | |
70 | /* declarations. */ |
71 | |
72 | |
73 | /* Helper functions. */ |
74 | |
75 | void |
76 | pp_c_whitespace (c_pretty_printer *pp) |
77 | { |
78 | pp_space (pp); |
79 | pp->padding = pp_none; |
80 | } |
81 | |
82 | void |
83 | pp_c_left_paren (c_pretty_printer *pp) |
84 | { |
85 | pp_left_paren (pp); |
86 | pp->padding = pp_none; |
87 | } |
88 | |
89 | void |
90 | pp_c_right_paren (c_pretty_printer *pp) |
91 | { |
92 | pp_right_paren (pp); |
93 | pp->padding = pp_none; |
94 | } |
95 | |
96 | void |
97 | pp_c_left_brace (c_pretty_printer *pp) |
98 | { |
99 | pp_left_brace (pp); |
100 | pp->padding = pp_none; |
101 | } |
102 | |
103 | void |
104 | pp_c_right_brace (c_pretty_printer *pp) |
105 | { |
106 | pp_right_brace (pp); |
107 | pp->padding = pp_none; |
108 | } |
109 | |
110 | void |
111 | pp_c_left_bracket (c_pretty_printer *pp) |
112 | { |
113 | pp_left_bracket (pp); |
114 | pp->padding = pp_none; |
115 | } |
116 | |
117 | void |
118 | pp_c_right_bracket (c_pretty_printer *pp) |
119 | { |
120 | pp_right_bracket (pp); |
121 | pp->padding = pp_none; |
122 | } |
123 | |
124 | void |
125 | pp_c_dot (c_pretty_printer *pp) |
126 | { |
127 | pp_dot (pp); |
128 | pp->padding = pp_none; |
129 | } |
130 | |
131 | void |
132 | pp_c_ampersand (c_pretty_printer *pp) |
133 | { |
134 | pp_ampersand (pp); |
135 | pp->padding = pp_none; |
136 | } |
137 | |
138 | void |
139 | pp_c_star (c_pretty_printer *pp) |
140 | { |
141 | pp_star (pp); |
142 | pp->padding = pp_none; |
143 | } |
144 | |
145 | void |
146 | pp_c_arrow (c_pretty_printer *pp) |
147 | { |
148 | pp_arrow (pp); |
149 | pp->padding = pp_none; |
150 | } |
151 | |
152 | void |
153 | pp_c_semicolon (c_pretty_printer *pp) |
154 | { |
155 | pp_semicolon (pp); |
156 | pp->padding = pp_none; |
157 | } |
158 | |
159 | void |
160 | pp_c_complement (c_pretty_printer *pp) |
161 | { |
162 | pp_complement (pp); |
163 | pp->padding = pp_none; |
164 | } |
165 | |
166 | void |
167 | pp_c_exclamation (c_pretty_printer *pp) |
168 | { |
169 | pp_exclamation (pp); |
170 | pp->padding = pp_none; |
171 | } |
172 | |
173 | /* Print out the external representation of QUALIFIERS. */ |
174 | |
175 | void |
176 | pp_c_cv_qualifiers (c_pretty_printer *pp, int qualifiers, bool func_type) |
177 | { |
178 | const char *p = pp_last_position_in_text (pp); |
179 | |
180 | if (!qualifiers) |
181 | return; |
182 | |
183 | /* The C programming language does not have references, but it is much |
184 | simpler to handle those here rather than going through the same |
185 | logic in the C++ pretty-printer. */ |
186 | if (p != NULL && (*p == '*' || *p == '&')) |
187 | pp_c_whitespace (pp); |
188 | |
189 | if (qualifiers & TYPE_QUAL_ATOMIC) |
190 | pp_c_ws_string (pp, "_Atomic" ); |
191 | if (qualifiers & TYPE_QUAL_CONST) |
192 | pp_c_ws_string (pp, func_type ? "__attribute__((const))" : "const" ); |
193 | if (qualifiers & TYPE_QUAL_VOLATILE) |
194 | pp_c_ws_string (pp, func_type ? "__attribute__((noreturn))" : "volatile" ); |
195 | if (qualifiers & TYPE_QUAL_RESTRICT) |
196 | pp_c_ws_string (pp, (flag_isoc99 && !c_dialect_cxx () |
197 | ? "restrict" : "__restrict__" )); |
198 | } |
199 | |
200 | /* Pretty-print T using the type-cast notation '( type-name )'. */ |
201 | |
202 | void |
203 | pp_c_type_cast (c_pretty_printer *pp, tree t) |
204 | { |
205 | pp_c_left_paren (pp); |
206 | pp->type_id (t); |
207 | pp_c_right_paren (pp); |
208 | } |
209 | |
210 | /* We're about to pretty-print a pointer type as indicated by T. |
211 | Output a whitespace, if needed, preparing for subsequent output. */ |
212 | |
213 | void |
214 | pp_c_space_for_pointer_operator (c_pretty_printer *pp, tree t) |
215 | { |
216 | if (POINTER_TYPE_P (t)) |
217 | { |
218 | tree pointee = strip_pointer_operator (TREE_TYPE (t)); |
219 | if (TREE_CODE (pointee) != ARRAY_TYPE |
220 | && TREE_CODE (pointee) != FUNCTION_TYPE) |
221 | pp_c_whitespace (pp); |
222 | } |
223 | } |
224 | |
225 | |
226 | /* Declarations. */ |
227 | |
228 | /* C++ cv-qualifiers are called type-qualifiers in C. Print out the |
229 | cv-qualifiers of T. If T is a declaration then it is the cv-qualifier |
230 | of its type. Take care of possible extensions. |
231 | |
232 | type-qualifier-list: |
233 | type-qualifier |
234 | type-qualifier-list type-qualifier |
235 | |
236 | type-qualifier: |
237 | const |
238 | restrict -- C99 |
239 | __restrict__ -- GNU C |
240 | address-space-qualifier -- GNU C |
241 | volatile |
242 | _Atomic -- C11 |
243 | |
244 | address-space-qualifier: |
245 | identifier -- GNU C */ |
246 | |
247 | void |
248 | pp_c_type_qualifier_list (c_pretty_printer *pp, tree t) |
249 | { |
250 | int qualifiers; |
251 | |
252 | if (!t || t == error_mark_node) |
253 | return; |
254 | |
255 | if (!TYPE_P (t)) |
256 | t = TREE_TYPE (t); |
257 | |
258 | if (TREE_CODE (t) != ARRAY_TYPE) |
259 | { |
260 | qualifiers = TYPE_QUALS (t); |
261 | pp_c_cv_qualifiers (pp, qualifiers, |
262 | TREE_CODE (t) == FUNCTION_TYPE); |
263 | } |
264 | |
265 | if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (t))) |
266 | { |
267 | const char *as = c_addr_space_name (TYPE_ADDR_SPACE (t)); |
268 | pp_c_identifier (pp, as); |
269 | } |
270 | } |
271 | |
272 | /* pointer: |
273 | * type-qualifier-list(opt) |
274 | * type-qualifier-list(opt) pointer */ |
275 | |
276 | static void |
277 | pp_c_pointer (c_pretty_printer *pp, tree t) |
278 | { |
279 | if (!TYPE_P (t) && TREE_CODE (t) != TYPE_DECL) |
280 | t = TREE_TYPE (t); |
281 | switch (TREE_CODE (t)) |
282 | { |
283 | case POINTER_TYPE: |
284 | /* It is easier to handle C++ reference types here. */ |
285 | case REFERENCE_TYPE: |
286 | if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE) |
287 | pp_c_pointer (pp, TREE_TYPE (t)); |
288 | if (TREE_CODE (t) == POINTER_TYPE) |
289 | pp_c_star (pp); |
290 | else |
291 | { |
292 | pp_c_ampersand (pp); |
293 | if (TYPE_REF_IS_RVALUE (t)) |
294 | pp_c_ampersand (pp); |
295 | } |
296 | pp_c_type_qualifier_list (pp, t); |
297 | break; |
298 | |
299 | /* ??? This node is now in GENERIC and so shouldn't be here. But |
300 | we'll fix that later. */ |
301 | case DECL_EXPR: |
302 | pp->declaration (DECL_EXPR_DECL (t)); |
303 | pp_needs_newline (pp) = true; |
304 | break; |
305 | |
306 | default: |
307 | pp_unsupported_tree (pp, t); |
308 | } |
309 | } |
310 | |
311 | /* simple-type-specifier: |
312 | type-specifier |
313 | |
314 | type-specifier: |
315 | void |
316 | char |
317 | short |
318 | int |
319 | long |
320 | float |
321 | double |
322 | signed |
323 | unsigned |
324 | _Bool -- C99 |
325 | _Complex -- C99 |
326 | _Imaginary -- C99 |
327 | nullptr_t -- C23 |
328 | struct-or-union-specifier |
329 | enum-specifier |
330 | typedef-name. |
331 | |
332 | GNU extensions. |
333 | simple-type-specifier: |
334 | __complex__ |
335 | __vector__ */ |
336 | |
337 | void |
338 | c_pretty_printer::simple_type_specifier (tree t) |
339 | { |
340 | const enum tree_code code = TREE_CODE (t); |
341 | switch (code) |
342 | { |
343 | case ERROR_MARK: |
344 | translate_string ("<type-error>" ); |
345 | break; |
346 | |
347 | case IDENTIFIER_NODE: |
348 | pp_c_identifier (this, IDENTIFIER_POINTER (t)); |
349 | break; |
350 | |
351 | case VOID_TYPE: |
352 | case OPAQUE_TYPE: |
353 | case BOOLEAN_TYPE: |
354 | case INTEGER_TYPE: |
355 | case REAL_TYPE: |
356 | case FIXED_POINT_TYPE: |
357 | if (TYPE_NAME (t)) |
358 | { |
359 | t = TYPE_NAME (t); |
360 | simple_type_specifier (t); |
361 | } |
362 | else |
363 | { |
364 | int prec = TYPE_PRECISION (t); |
365 | tree common_t; |
366 | if (ALL_FIXED_POINT_MODE_P (TYPE_MODE (t))) |
367 | common_t = c_common_type_for_mode (TYPE_MODE (t), |
368 | TYPE_SATURATING (t)); |
369 | else |
370 | common_t = c_common_type_for_mode (TYPE_MODE (t), |
371 | TYPE_UNSIGNED (t)); |
372 | if (common_t && TYPE_NAME (common_t)) |
373 | { |
374 | simple_type_specifier (t: common_t); |
375 | if (TYPE_PRECISION (common_t) != prec) |
376 | { |
377 | pp_colon (this); |
378 | pp_decimal_int (this, prec); |
379 | } |
380 | } |
381 | else |
382 | { |
383 | switch (code) |
384 | { |
385 | case INTEGER_TYPE: |
386 | translate_string (TYPE_UNSIGNED (t) |
387 | ? "<unnamed-unsigned:" |
388 | : "<unnamed-signed:" ); |
389 | break; |
390 | case REAL_TYPE: |
391 | translate_string ("<unnamed-float:" ); |
392 | break; |
393 | case FIXED_POINT_TYPE: |
394 | translate_string ("<unnamed-fixed:" ); |
395 | break; |
396 | default: |
397 | gcc_unreachable (); |
398 | } |
399 | pp_decimal_int (this, prec); |
400 | pp_greater (this); |
401 | } |
402 | } |
403 | break; |
404 | |
405 | case BITINT_TYPE: |
406 | if (TYPE_NAME (t)) |
407 | { |
408 | t = TYPE_NAME (t); |
409 | simple_type_specifier (t); |
410 | } |
411 | else |
412 | { |
413 | int prec = TYPE_PRECISION (t); |
414 | if (TYPE_UNSIGNED (t)) |
415 | pp_c_ws_string (this, "unsigned" ); |
416 | pp_c_ws_string (this, "_BitInt(" );; |
417 | pp_decimal_int (this, prec); |
418 | pp_right_paren (this); |
419 | } |
420 | break; |
421 | |
422 | case TYPE_DECL: |
423 | if (DECL_NAME (t)) |
424 | id_expression (t); |
425 | else |
426 | translate_string ("<typedef-error>" ); |
427 | break; |
428 | |
429 | case UNION_TYPE: |
430 | case RECORD_TYPE: |
431 | case ENUMERAL_TYPE: |
432 | if (TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL) |
433 | /* Don't decorate the type if this is a typedef name. */; |
434 | else if (code == UNION_TYPE) |
435 | pp_c_ws_string (this, "union" ); |
436 | else if (code == RECORD_TYPE) |
437 | pp_c_ws_string (this, "struct" ); |
438 | else if (code == ENUMERAL_TYPE) |
439 | pp_c_ws_string (this, "enum" ); |
440 | else |
441 | translate_string ("<tag-error>" ); |
442 | |
443 | if (TYPE_NAME (t)) |
444 | id_expression (TYPE_NAME (t)); |
445 | else |
446 | translate_string ("<anonymous>" ); |
447 | break; |
448 | case NULLPTR_TYPE: |
449 | pp_c_ws_string (this, "nullptr_t" ); |
450 | break; |
451 | |
452 | default: |
453 | pp_unsupported_tree (this, t); |
454 | break; |
455 | } |
456 | } |
457 | |
458 | /* specifier-qualifier-list: |
459 | type-specifier specifier-qualifier-list-opt |
460 | type-qualifier specifier-qualifier-list-opt |
461 | |
462 | |
463 | Implementation note: Because of the non-linearities in array or |
464 | function declarations, this routine prints not just the |
465 | specifier-qualifier-list of such entities or types of such entities, |
466 | but also the 'pointer' production part of their declarators. The |
467 | remaining part is done by declarator() or abstract_declarator(). */ |
468 | |
469 | void |
470 | pp_c_specifier_qualifier_list (c_pretty_printer *pp, tree t) |
471 | { |
472 | const enum tree_code code = TREE_CODE (t); |
473 | |
474 | if (!(pp->flags & pp_c_flag_gnu_v3) && code != POINTER_TYPE) |
475 | pp_c_type_qualifier_list (pp, t); |
476 | switch (code) |
477 | { |
478 | case REFERENCE_TYPE: |
479 | case POINTER_TYPE: |
480 | { |
481 | /* Get the types-specifier of this type. */ |
482 | tree pointee = strip_pointer_operator (TREE_TYPE (t)); |
483 | pp_c_specifier_qualifier_list (pp, t: pointee); |
484 | if (TREE_CODE (pointee) == ARRAY_TYPE |
485 | || TREE_CODE (pointee) == FUNCTION_TYPE) |
486 | { |
487 | pp_c_whitespace (pp); |
488 | pp_c_left_paren (pp); |
489 | /* If we're dealing with the GNU form of attributes, print this: |
490 | void (__attribute__((noreturn)) *f) (); |
491 | If it is the standard [[]] attribute, we'll print the attribute |
492 | in c_pretty_printer::direct_abstract_declarator/FUNCTION_TYPE. */ |
493 | if (!cxx11_attribute_p (TYPE_ATTRIBUTES (pointee))) |
494 | pp_c_attributes_display (pp, TYPE_ATTRIBUTES (pointee)); |
495 | } |
496 | else if (!c_dialect_cxx ()) |
497 | pp_c_whitespace (pp); |
498 | pp_ptr_operator (pp, t); |
499 | } |
500 | break; |
501 | |
502 | case FUNCTION_TYPE: |
503 | case ARRAY_TYPE: |
504 | pp_c_specifier_qualifier_list (pp, TREE_TYPE (t)); |
505 | break; |
506 | |
507 | case VECTOR_TYPE: |
508 | case COMPLEX_TYPE: |
509 | if (code == COMPLEX_TYPE) |
510 | pp_c_ws_string (pp, (flag_isoc99 && !c_dialect_cxx () |
511 | ? "_Complex" : "__complex__" )); |
512 | else if (code == VECTOR_TYPE) |
513 | { |
514 | /* The syntax we print for vector types isn't real C or C++ syntax, |
515 | so it's better to print the type name if we have one. */ |
516 | tree name = TYPE_NAME (t); |
517 | if (!(pp->flags & pp_c_flag_gnu_v3) |
518 | && name |
519 | && TREE_CODE (name) == TYPE_DECL) |
520 | { |
521 | pp->id_expression (name); |
522 | break; |
523 | } |
524 | pp_c_ws_string (pp, "__vector" ); |
525 | pp_c_left_paren (pp); |
526 | pp_wide_integer (pp, TYPE_VECTOR_SUBPARTS (node: t)); |
527 | pp_c_right_paren (pp); |
528 | pp_c_whitespace (pp); |
529 | } |
530 | pp_c_specifier_qualifier_list (pp, TREE_TYPE (t)); |
531 | break; |
532 | |
533 | default: |
534 | pp->simple_type_specifier (t); |
535 | break; |
536 | } |
537 | if ((pp->flags & pp_c_flag_gnu_v3) && code != POINTER_TYPE) |
538 | pp_c_type_qualifier_list (pp, t); |
539 | } |
540 | |
541 | /* parameter-type-list: |
542 | parameter-list |
543 | parameter-list , ... |
544 | |
545 | parameter-list: |
546 | parameter-declaration |
547 | parameter-list , parameter-declaration |
548 | |
549 | parameter-declaration: |
550 | declaration-specifiers declarator |
551 | declaration-specifiers abstract-declarator(opt) */ |
552 | |
553 | void |
554 | pp_c_parameter_type_list (c_pretty_printer *pp, tree t) |
555 | { |
556 | bool want_parm_decl = DECL_P (t) && !(pp->flags & pp_c_flag_abstract); |
557 | tree parms = want_parm_decl ? DECL_ARGUMENTS (t) : TYPE_ARG_TYPES (t); |
558 | pp_c_left_paren (pp); |
559 | if (parms == void_list_node) |
560 | pp_c_ws_string (pp, "void" ); |
561 | else |
562 | { |
563 | bool first = true; |
564 | for ( ; parms && parms != void_list_node; parms = TREE_CHAIN (parms)) |
565 | { |
566 | if (!first) |
567 | pp_separate_with (pp, ','); |
568 | first = false; |
569 | pp->declaration_specifiers |
570 | (want_parm_decl ? parms : TREE_VALUE (parms)); |
571 | if (want_parm_decl) |
572 | pp->declarator (parms); |
573 | else |
574 | pp->abstract_declarator (TREE_VALUE (parms)); |
575 | } |
576 | if (!first && !parms) |
577 | { |
578 | pp_separate_with (pp, ','); |
579 | pp_string (pp, "..." ); |
580 | } |
581 | } |
582 | pp_c_right_paren (pp); |
583 | } |
584 | |
585 | /* abstract-declarator: |
586 | pointer |
587 | pointer(opt) direct-abstract-declarator */ |
588 | |
589 | void |
590 | c_pretty_printer::abstract_declarator (tree t) |
591 | { |
592 | if (TREE_CODE (t) == POINTER_TYPE) |
593 | { |
594 | if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE |
595 | || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE) |
596 | pp_c_right_paren (pp: this); |
597 | t = TREE_TYPE (t); |
598 | } |
599 | |
600 | direct_abstract_declarator (t); |
601 | } |
602 | |
603 | /* direct-abstract-declarator: |
604 | ( abstract-declarator ) |
605 | direct-abstract-declarator(opt) [ assignment-expression(opt) ] |
606 | direct-abstract-declarator(opt) [ * ] |
607 | direct-abstract-declarator(opt) ( parameter-type-list(opt) ) */ |
608 | |
609 | void |
610 | c_pretty_printer::direct_abstract_declarator (tree t) |
611 | { |
612 | bool add_space = false; |
613 | |
614 | switch (TREE_CODE (t)) |
615 | { |
616 | case POINTER_TYPE: |
617 | abstract_declarator (t); |
618 | break; |
619 | |
620 | case FUNCTION_TYPE: |
621 | pp_c_parameter_type_list (pp: this, t); |
622 | direct_abstract_declarator (TREE_TYPE (t)); |
623 | /* If this is the standard [[]] attribute, print |
624 | void (*)() [[noreturn]]; */ |
625 | if (cxx11_attribute_p (TYPE_ATTRIBUTES (t))) |
626 | { |
627 | pp_space (this); |
628 | pp_c_attributes_display (this, TYPE_ATTRIBUTES (t)); |
629 | } |
630 | break; |
631 | |
632 | case ARRAY_TYPE: |
633 | pp_c_left_bracket (pp: this); |
634 | |
635 | if (int quals = TYPE_QUALS (t)) |
636 | { |
637 | /* Print the array qualifiers such as in "T[const restrict 3]". */ |
638 | pp_c_cv_qualifiers (pp: this, qualifiers: quals, func_type: false); |
639 | add_space = true; |
640 | } |
641 | |
642 | if (tree arr = lookup_attribute (attr_name: "array" , TYPE_ATTRIBUTES (t))) |
643 | { |
644 | if (TREE_VALUE (arr)) |
645 | { |
646 | /* Print the specifier as in "T[static 3]" that's not actually |
647 | part of the type but may be added by the front end. */ |
648 | pp_c_ws_string (this, "static" ); |
649 | add_space = true; |
650 | } |
651 | else if (!TYPE_DOMAIN (t)) |
652 | /* For arrays of unspecified bound using the [*] notation. */ |
653 | pp_character (this, '*'); |
654 | } |
655 | |
656 | if (tree dom = TYPE_DOMAIN (t)) |
657 | { |
658 | if (tree maxval = TYPE_MAX_VALUE (dom)) |
659 | { |
660 | if (add_space) |
661 | pp_space (this); |
662 | |
663 | tree type = TREE_TYPE (maxval); |
664 | |
665 | if (tree_fits_shwi_p (maxval)) |
666 | pp_wide_integer (pp: this, i: tree_to_shwi (maxval) + 1); |
667 | else if (TREE_CODE (maxval) == INTEGER_CST) |
668 | expression (fold_build2 (PLUS_EXPR, type, maxval, |
669 | build_int_cst (type, 1))); |
670 | else |
671 | { |
672 | /* Strip the expressions from around a VLA bound added |
673 | internally to make it fit the domain mold, including |
674 | any casts. */ |
675 | if (TREE_CODE (maxval) == NOP_EXPR) |
676 | maxval = TREE_OPERAND (maxval, 0); |
677 | if (TREE_CODE (maxval) == PLUS_EXPR |
678 | && integer_all_onesp (TREE_OPERAND (maxval, 1))) |
679 | { |
680 | maxval = TREE_OPERAND (maxval, 0); |
681 | if (TREE_CODE (maxval) == NOP_EXPR) |
682 | maxval = TREE_OPERAND (maxval, 0); |
683 | } |
684 | if (TREE_CODE (maxval) == SAVE_EXPR) |
685 | { |
686 | maxval = TREE_OPERAND (maxval, 0); |
687 | if (TREE_CODE (maxval) == NOP_EXPR) |
688 | maxval = TREE_OPERAND (maxval, 0); |
689 | } |
690 | |
691 | expression (maxval); |
692 | } |
693 | } |
694 | else if (TYPE_SIZE (t)) |
695 | /* Print zero for zero-length arrays but not for flexible |
696 | array members whose TYPE_SIZE is null. */ |
697 | pp_string (this, "0" ); |
698 | } |
699 | pp_c_right_bracket (pp: this); |
700 | direct_abstract_declarator (TREE_TYPE (t)); |
701 | break; |
702 | |
703 | case IDENTIFIER_NODE: |
704 | case VOID_TYPE: |
705 | case OPAQUE_TYPE: |
706 | case BOOLEAN_TYPE: |
707 | case INTEGER_TYPE: |
708 | case REAL_TYPE: |
709 | case FIXED_POINT_TYPE: |
710 | case ENUMERAL_TYPE: |
711 | case BITINT_TYPE: |
712 | case RECORD_TYPE: |
713 | case UNION_TYPE: |
714 | case VECTOR_TYPE: |
715 | case COMPLEX_TYPE: |
716 | case TYPE_DECL: |
717 | case ERROR_MARK: |
718 | case NULLPTR_TYPE: |
719 | break; |
720 | |
721 | default: |
722 | pp_unsupported_tree (this, t); |
723 | break; |
724 | } |
725 | } |
726 | |
727 | /* type-name: |
728 | specifier-qualifier-list abstract-declarator(opt) */ |
729 | |
730 | void |
731 | c_pretty_printer::type_id (tree t) |
732 | { |
733 | pp_c_specifier_qualifier_list (pp: this, t); |
734 | abstract_declarator (t); |
735 | } |
736 | |
737 | /* storage-class-specifier: |
738 | typedef |
739 | extern |
740 | static |
741 | auto |
742 | register */ |
743 | |
744 | void |
745 | c_pretty_printer::storage_class_specifier (tree t) |
746 | { |
747 | if (TREE_CODE (t) == TYPE_DECL) |
748 | pp_c_ws_string (this, "typedef" ); |
749 | else if (DECL_P (t)) |
750 | { |
751 | if (DECL_REGISTER (t)) |
752 | pp_c_ws_string (this, "register" ); |
753 | else if (TREE_STATIC (t) && VAR_P (t)) |
754 | pp_c_ws_string (this, "static" ); |
755 | } |
756 | } |
757 | |
758 | /* function-specifier: |
759 | inline */ |
760 | |
761 | void |
762 | c_pretty_printer::function_specifier (tree t) |
763 | { |
764 | if (TREE_CODE (t) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (t)) |
765 | pp_c_ws_string (this, "inline" ); |
766 | } |
767 | |
768 | /* declaration-specifiers: |
769 | storage-class-specifier declaration-specifiers(opt) |
770 | type-specifier declaration-specifiers(opt) |
771 | type-qualifier declaration-specifiers(opt) |
772 | function-specifier declaration-specifiers(opt) */ |
773 | |
774 | void |
775 | c_pretty_printer::declaration_specifiers (tree t) |
776 | { |
777 | storage_class_specifier (t); |
778 | function_specifier (t); |
779 | pp_c_specifier_qualifier_list (pp: this, DECL_P (t) ? TREE_TYPE (t) : t); |
780 | } |
781 | |
782 | /* direct-declarator |
783 | identifier |
784 | ( declarator ) |
785 | direct-declarator [ type-qualifier-list(opt) assignment-expression(opt) ] |
786 | direct-declarator [ static type-qualifier-list(opt) assignment-expression(opt)] |
787 | direct-declarator [ type-qualifier-list static assignment-expression ] |
788 | direct-declarator [ type-qualifier-list * ] |
789 | direct-declarator ( parameter-type-list ) |
790 | direct-declarator ( identifier-list(opt) ) */ |
791 | |
792 | void |
793 | c_pretty_printer::direct_declarator (tree t) |
794 | { |
795 | switch (TREE_CODE (t)) |
796 | { |
797 | case VAR_DECL: |
798 | case PARM_DECL: |
799 | case TYPE_DECL: |
800 | case FIELD_DECL: |
801 | case LABEL_DECL: |
802 | pp_c_space_for_pointer_operator (pp: this, TREE_TYPE (t)); |
803 | pp_c_tree_decl_identifier (this, t); |
804 | break; |
805 | |
806 | case ARRAY_TYPE: |
807 | case POINTER_TYPE: |
808 | abstract_declarator (TREE_TYPE (t)); |
809 | break; |
810 | |
811 | case FUNCTION_TYPE: |
812 | pp_parameter_list (this, t); |
813 | abstract_declarator (TREE_TYPE (t)); |
814 | break; |
815 | |
816 | case FUNCTION_DECL: |
817 | pp_c_space_for_pointer_operator (pp: this, TREE_TYPE (TREE_TYPE (t))); |
818 | pp_c_tree_decl_identifier (this, t); |
819 | if (flags & pp_c_flag_abstract) |
820 | abstract_declarator (TREE_TYPE (t)); |
821 | else |
822 | { |
823 | pp_parameter_list (this, t); |
824 | abstract_declarator (TREE_TYPE (TREE_TYPE (t))); |
825 | } |
826 | break; |
827 | |
828 | case INTEGER_TYPE: |
829 | case REAL_TYPE: |
830 | case FIXED_POINT_TYPE: |
831 | case ENUMERAL_TYPE: |
832 | case BITINT_TYPE: |
833 | case UNION_TYPE: |
834 | case RECORD_TYPE: |
835 | break; |
836 | |
837 | default: |
838 | pp_unsupported_tree (this, t); |
839 | break; |
840 | } |
841 | } |
842 | |
843 | |
844 | /* declarator: |
845 | pointer(opt) direct-declarator */ |
846 | |
847 | void |
848 | c_pretty_printer::declarator (tree t) |
849 | { |
850 | switch (TREE_CODE (t)) |
851 | { |
852 | case INTEGER_TYPE: |
853 | case REAL_TYPE: |
854 | case FIXED_POINT_TYPE: |
855 | case ENUMERAL_TYPE: |
856 | case BITINT_TYPE: |
857 | case UNION_TYPE: |
858 | case RECORD_TYPE: |
859 | break; |
860 | |
861 | case VAR_DECL: |
862 | case PARM_DECL: |
863 | case FIELD_DECL: |
864 | case ARRAY_TYPE: |
865 | case FUNCTION_TYPE: |
866 | case FUNCTION_DECL: |
867 | case TYPE_DECL: |
868 | direct_declarator (t); |
869 | break; |
870 | |
871 | |
872 | default: |
873 | pp_unsupported_tree (this, t); |
874 | break; |
875 | } |
876 | } |
877 | |
878 | /* declaration: |
879 | declaration-specifiers init-declarator-list(opt) ; */ |
880 | |
881 | void |
882 | c_pretty_printer::declaration (tree t) |
883 | { |
884 | declaration_specifiers (t); |
885 | pp_c_init_declarator (this, t); |
886 | } |
887 | |
888 | /* Pretty-print ATTRIBUTES marked to be displayed on diagnostic. */ |
889 | |
890 | void |
891 | pp_c_attributes_display (c_pretty_printer *pp, tree a) |
892 | { |
893 | bool is_first = true; |
894 | |
895 | if (a == NULL_TREE) |
896 | return; |
897 | |
898 | const bool std_p = cxx11_attribute_p (a); |
899 | |
900 | for (; a != NULL_TREE; a = TREE_CHAIN (a)) |
901 | { |
902 | const struct attribute_spec *as |
903 | = lookup_attribute_spec (get_attribute_name (a)); |
904 | if (!as || as->affects_type_identity == false) |
905 | continue; |
906 | if (c_dialect_cxx () |
907 | && !strcmp (s1: "transaction_safe" , s2: as->name)) |
908 | /* In C++ transaction_safe is printed at the end of the declarator. */ |
909 | continue; |
910 | if (is_first) |
911 | { |
912 | if (std_p) |
913 | { |
914 | pp_c_left_bracket (pp); |
915 | pp_c_left_bracket (pp); |
916 | } |
917 | else |
918 | { |
919 | pp_c_ws_string (pp, "__attribute__" ); |
920 | pp_c_left_paren (pp); |
921 | pp_c_left_paren (pp); |
922 | } |
923 | is_first = false; |
924 | } |
925 | else |
926 | pp_separate_with (pp, ','); |
927 | tree ns; |
928 | if (std_p && (ns = get_attribute_namespace (a))) |
929 | { |
930 | pp_tree_identifier (pp, ns); |
931 | pp_colon (pp); |
932 | pp_colon (pp); |
933 | } |
934 | pp_tree_identifier (pp, get_attribute_name (a)); |
935 | if (TREE_VALUE (a)) |
936 | pp_c_call_argument_list (pp, TREE_VALUE (a)); |
937 | } |
938 | |
939 | if (!is_first) |
940 | { |
941 | if (std_p) |
942 | { |
943 | pp_c_right_bracket (pp); |
944 | pp_c_right_bracket (pp); |
945 | } |
946 | else |
947 | { |
948 | pp_c_right_paren (pp); |
949 | pp_c_right_paren (pp); |
950 | pp_c_whitespace (pp); |
951 | } |
952 | } |
953 | } |
954 | |
955 | /* function-definition: |
956 | declaration-specifiers declarator compound-statement */ |
957 | |
958 | void |
959 | pp_c_function_definition (c_pretty_printer *pp, tree t) |
960 | { |
961 | pp->declaration_specifiers (t); |
962 | pp->declarator (t); |
963 | pp_needs_newline (pp) = true; |
964 | pp->statement (DECL_SAVED_TREE (t)); |
965 | pp_newline_and_flush (pp); |
966 | } |
967 | |
968 | |
969 | /* Expressions. */ |
970 | |
971 | /* Print out a c-char. This is called solely for characters which are |
972 | in the *target* execution character set. We ought to convert them |
973 | back to the *host* execution character set before printing, but we |
974 | have no way to do this at present. A decent compromise is to print |
975 | all characters as if they were in the host execution character set, |
976 | and not attempt to recover any named escape characters, but render |
977 | all unprintables as octal escapes. If the host and target character |
978 | sets are the same, this produces relatively readable output. If they |
979 | are not the same, strings may appear as gibberish, but that's okay |
980 | (in fact, it may well be what the reader wants, e.g. if they are looking |
981 | to see if conversion to the target character set happened correctly). |
982 | |
983 | A special case: we need to prefix \, ", and ' with backslashes. It is |
984 | correct to do so for the *host*'s \, ", and ', because the rest of the |
985 | file appears in the host character set. */ |
986 | |
987 | static void |
988 | pp_c_char (c_pretty_printer *pp, int c) |
989 | { |
990 | if (ISPRINT (c)) |
991 | { |
992 | switch (c) |
993 | { |
994 | case '\\': pp_string (pp, "\\\\" ); break; |
995 | case '\'': pp_string (pp, "\\\'" ); break; |
996 | case '\"': pp_string (pp, "\\\"" ); break; |
997 | default: pp_character (pp, c); |
998 | } |
999 | } |
1000 | else |
1001 | pp_scalar (pp, "\\%03o" , (unsigned) c); |
1002 | } |
1003 | |
1004 | /* Print out a STRING literal. */ |
1005 | |
1006 | void |
1007 | pp_c_string_literal (c_pretty_printer *pp, tree s) |
1008 | { |
1009 | const char *p = TREE_STRING_POINTER (s); |
1010 | int n = TREE_STRING_LENGTH (s) - 1; |
1011 | int i; |
1012 | pp_doublequote (pp); |
1013 | for (i = 0; i < n; ++i) |
1014 | pp_c_char (pp, c: p[i]); |
1015 | pp_doublequote (pp); |
1016 | } |
1017 | |
1018 | /* Pretty-print a VOID_CST (void_node). */ |
1019 | |
1020 | static void |
1021 | pp_c_void_constant (c_pretty_printer *pp) |
1022 | { |
1023 | pp_c_type_cast (pp, void_type_node); |
1024 | pp_string (pp, "0" ); |
1025 | } |
1026 | |
1027 | /* Pretty-print an INTEGER literal. */ |
1028 | |
1029 | void |
1030 | pp_c_integer_constant (c_pretty_printer *pp, tree i) |
1031 | { |
1032 | if (tree_fits_shwi_p (i)) |
1033 | pp_wide_integer (pp, i: tree_to_shwi (i)); |
1034 | else if (tree_fits_uhwi_p (i)) |
1035 | pp_unsigned_wide_integer (pp, tree_to_uhwi (i)); |
1036 | else |
1037 | { |
1038 | wide_int wi = wi::to_wide (t: i); |
1039 | |
1040 | if (wi::lt_p (x: wi::to_wide (t: i), y: 0, TYPE_SIGN (TREE_TYPE (i)))) |
1041 | { |
1042 | pp_minus (pp); |
1043 | wi = -wi; |
1044 | } |
1045 | unsigned int prec = wi.get_precision (); |
1046 | if ((prec + 3) / 4 > sizeof (pp_buffer (pp)->digit_buffer) - 3) |
1047 | { |
1048 | char *buf = XALLOCAVEC (char, (prec + 3) / 4 + 3); |
1049 | print_hex (wi, buf); |
1050 | pp_string (pp, buf); |
1051 | } |
1052 | else |
1053 | { |
1054 | print_hex (wi, pp_buffer (pp)->digit_buffer); |
1055 | pp_string (pp, pp_buffer (pp)->digit_buffer); |
1056 | } |
1057 | } |
1058 | } |
1059 | |
1060 | /* Print out a CHARACTER literal. */ |
1061 | |
1062 | static void |
1063 | pp_c_character_constant (c_pretty_printer *pp, tree c) |
1064 | { |
1065 | pp_quote (pp); |
1066 | pp_c_char (pp, c: (unsigned) TREE_INT_CST_LOW (c)); |
1067 | pp_quote (pp); |
1068 | } |
1069 | |
1070 | /* Print out a BOOLEAN literal. */ |
1071 | |
1072 | static void |
1073 | pp_c_bool_constant (c_pretty_printer *pp, tree b) |
1074 | { |
1075 | if (b == boolean_false_node) |
1076 | { |
1077 | if (c_dialect_cxx ()) |
1078 | pp_c_ws_string (pp, "false" ); |
1079 | else if (flag_isoc99) |
1080 | pp_c_ws_string (pp, "_False" ); |
1081 | else |
1082 | pp_unsupported_tree (pp, b); |
1083 | } |
1084 | else if (b == boolean_true_node) |
1085 | { |
1086 | if (c_dialect_cxx ()) |
1087 | pp_c_ws_string (pp, "true" ); |
1088 | else if (flag_isoc99) |
1089 | pp_c_ws_string (pp, "_True" ); |
1090 | else |
1091 | pp_unsupported_tree (pp, b); |
1092 | } |
1093 | else if (TREE_CODE (b) == INTEGER_CST) |
1094 | pp_c_integer_constant (pp, i: b); |
1095 | else |
1096 | pp_unsupported_tree (pp, b); |
1097 | } |
1098 | |
1099 | /* Given a value e of ENUMERAL_TYPE: |
1100 | Print out the first ENUMERATOR id with value e, if one is found, |
1101 | else print out the value as a C-style cast (type-id)value. */ |
1102 | |
1103 | static void |
1104 | pp_c_enumeration_constant (c_pretty_printer *pp, tree e) |
1105 | { |
1106 | tree type = TREE_TYPE (e); |
1107 | tree value = NULL_TREE; |
1108 | |
1109 | /* Find the name of this constant. */ |
1110 | if ((pp->flags & pp_c_flag_gnu_v3) == 0) |
1111 | for (value = TYPE_VALUES (type); value != NULL_TREE; |
1112 | value = TREE_CHAIN (value)) |
1113 | if (tree_int_cst_equal (DECL_INITIAL (TREE_VALUE (value)), e)) |
1114 | break; |
1115 | |
1116 | if (value != NULL_TREE) |
1117 | pp->id_expression (TREE_PURPOSE (value)); |
1118 | else |
1119 | { |
1120 | /* Value must have been cast. */ |
1121 | pp_c_type_cast (pp, t: type); |
1122 | pp_c_integer_constant (pp, i: e); |
1123 | } |
1124 | } |
1125 | |
1126 | /* Print out a REAL value as a decimal-floating-constant. */ |
1127 | |
1128 | static void |
1129 | pp_c_floating_constant (c_pretty_printer *pp, tree r) |
1130 | { |
1131 | const struct real_format *fmt |
1132 | = REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (r))); |
1133 | |
1134 | REAL_VALUE_TYPE floating_cst = TREE_REAL_CST (r); |
1135 | bool is_decimal = floating_cst.decimal; |
1136 | |
1137 | /* See ISO C++ WG N1822. Note: The fraction 643/2136 approximates |
1138 | log10(2) to 7 significant digits. */ |
1139 | int max_digits10 = 2 + (is_decimal ? fmt->p : fmt->p * 643L / 2136); |
1140 | |
1141 | real_to_decimal (pp_buffer (pp)->digit_buffer, &TREE_REAL_CST (r), |
1142 | sizeof (pp_buffer (pp)->digit_buffer), |
1143 | max_digits10, 1); |
1144 | |
1145 | pp_string (pp, pp_buffer(pp)->digit_buffer); |
1146 | if (TREE_TYPE (r) == float_type_node) |
1147 | pp_character (pp, 'f'); |
1148 | else if (TREE_TYPE (r) == long_double_type_node) |
1149 | pp_character (pp, 'l'); |
1150 | else if (TREE_TYPE (r) == dfloat128_type_node) |
1151 | pp_string (pp, "dl" ); |
1152 | else if (TREE_TYPE (r) == dfloat64_type_node) |
1153 | pp_string (pp, "dd" ); |
1154 | else if (TREE_TYPE (r) == dfloat32_type_node) |
1155 | pp_string (pp, "df" ); |
1156 | else if (TREE_TYPE (r) != double_type_node) |
1157 | for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++) |
1158 | if (TREE_TYPE (r) == FLOATN_NX_TYPE_NODE (i)) |
1159 | { |
1160 | pp_character (pp, 'f'); |
1161 | pp_decimal_int (pp, floatn_nx_types[i].n); |
1162 | if (floatn_nx_types[i].extended) |
1163 | pp_character (pp, 'x'); |
1164 | break; |
1165 | } |
1166 | } |
1167 | |
1168 | /* Print out a FIXED value as a decimal-floating-constant. */ |
1169 | |
1170 | static void |
1171 | pp_c_fixed_constant (c_pretty_printer *pp, tree r) |
1172 | { |
1173 | fixed_to_decimal (pp_buffer (pp)->digit_buffer, &TREE_FIXED_CST (r), |
1174 | sizeof (pp_buffer (pp)->digit_buffer)); |
1175 | pp_string (pp, pp_buffer(pp)->digit_buffer); |
1176 | } |
1177 | |
1178 | /* Pretty-print a compound literal expression. GNU extensions include |
1179 | vector constants. */ |
1180 | |
1181 | static void |
1182 | pp_c_compound_literal (c_pretty_printer *pp, tree e) |
1183 | { |
1184 | tree type = TREE_TYPE (e); |
1185 | pp_c_type_cast (pp, t: type); |
1186 | |
1187 | switch (TREE_CODE (type)) |
1188 | { |
1189 | case RECORD_TYPE: |
1190 | case UNION_TYPE: |
1191 | case ARRAY_TYPE: |
1192 | case VECTOR_TYPE: |
1193 | case COMPLEX_TYPE: |
1194 | pp_c_brace_enclosed_initializer_list (pp, e); |
1195 | break; |
1196 | |
1197 | default: |
1198 | pp_unsupported_tree (pp, e); |
1199 | break; |
1200 | } |
1201 | } |
1202 | |
1203 | /* Pretty-print a COMPLEX_EXPR expression. */ |
1204 | |
1205 | static void |
1206 | pp_c_complex_expr (c_pretty_printer *pp, tree e) |
1207 | { |
1208 | /* Handle a few common special cases, otherwise fallback |
1209 | to printing it as compound literal. */ |
1210 | tree type = TREE_TYPE (e); |
1211 | tree realexpr = TREE_OPERAND (e, 0); |
1212 | tree imagexpr = TREE_OPERAND (e, 1); |
1213 | |
1214 | /* Cast of an COMPLEX_TYPE expression to a different COMPLEX_TYPE. */ |
1215 | if (TREE_CODE (realexpr) == NOP_EXPR |
1216 | && TREE_CODE (imagexpr) == NOP_EXPR |
1217 | && TREE_TYPE (realexpr) == TREE_TYPE (type) |
1218 | && TREE_TYPE (imagexpr) == TREE_TYPE (type) |
1219 | && TREE_CODE (TREE_OPERAND (realexpr, 0)) == REALPART_EXPR |
1220 | && TREE_CODE (TREE_OPERAND (imagexpr, 0)) == IMAGPART_EXPR |
1221 | && TREE_OPERAND (TREE_OPERAND (realexpr, 0), 0) |
1222 | == TREE_OPERAND (TREE_OPERAND (imagexpr, 0), 0)) |
1223 | { |
1224 | pp_c_type_cast (pp, t: type); |
1225 | pp->expression (TREE_OPERAND (TREE_OPERAND (realexpr, 0), 0)); |
1226 | return; |
1227 | } |
1228 | |
1229 | /* Cast of an scalar expression to COMPLEX_TYPE. */ |
1230 | if ((integer_zerop (imagexpr) || real_zerop (imagexpr)) |
1231 | && TREE_TYPE (realexpr) == TREE_TYPE (type)) |
1232 | { |
1233 | pp_c_type_cast (pp, t: type); |
1234 | if (TREE_CODE (realexpr) == NOP_EXPR) |
1235 | realexpr = TREE_OPERAND (realexpr, 0); |
1236 | pp->expression (realexpr); |
1237 | return; |
1238 | } |
1239 | |
1240 | pp_c_compound_literal (pp, e); |
1241 | } |
1242 | |
1243 | /* constant: |
1244 | integer-constant |
1245 | floating-constant |
1246 | fixed-point-constant |
1247 | enumeration-constant |
1248 | character-constant */ |
1249 | |
1250 | void |
1251 | c_pretty_printer::constant (tree e) |
1252 | { |
1253 | const enum tree_code code = TREE_CODE (e); |
1254 | |
1255 | switch (code) |
1256 | { |
1257 | case VOID_CST: |
1258 | pp_c_void_constant (pp: this); |
1259 | break; |
1260 | |
1261 | case INTEGER_CST: |
1262 | { |
1263 | tree type = TREE_TYPE (e); |
1264 | if (type == boolean_type_node) |
1265 | pp_c_bool_constant (pp: this, b: e); |
1266 | else if (type == char_type_node) |
1267 | pp_c_character_constant (pp: this, c: e); |
1268 | else if (TREE_CODE (type) == ENUMERAL_TYPE) |
1269 | pp_c_enumeration_constant (pp: this, e); |
1270 | else if (NULLPTR_TYPE_P (type)) |
1271 | pp_string (this, "nullptr" ); |
1272 | else |
1273 | pp_c_integer_constant (pp: this, i: e); |
1274 | } |
1275 | break; |
1276 | |
1277 | case REAL_CST: |
1278 | pp_c_floating_constant (pp: this, r: e); |
1279 | break; |
1280 | |
1281 | case FIXED_CST: |
1282 | pp_c_fixed_constant (pp: this, r: e); |
1283 | break; |
1284 | |
1285 | case STRING_CST: |
1286 | pp_c_string_literal (pp: this, s: e); |
1287 | break; |
1288 | |
1289 | case COMPLEX_CST: |
1290 | /* Sometimes, we are confused and we think a complex literal |
1291 | is a constant. Such thing is a compound literal which |
1292 | grammatically belongs to postfix-expr production. */ |
1293 | pp_c_compound_literal (pp: this, e); |
1294 | break; |
1295 | |
1296 | default: |
1297 | pp_unsupported_tree (this, e); |
1298 | break; |
1299 | } |
1300 | } |
1301 | |
1302 | /* Pretty-print a string such as an identifier, without changing its |
1303 | encoding, preceded by whitespace is necessary. */ |
1304 | |
1305 | void |
1306 | pp_c_ws_string (c_pretty_printer *pp, const char *str) |
1307 | { |
1308 | pp_c_maybe_whitespace (pp); |
1309 | pp_string (pp, str); |
1310 | pp->padding = pp_before; |
1311 | } |
1312 | |
1313 | void |
1314 | c_pretty_printer::translate_string (const char *gmsgid) |
1315 | { |
1316 | if (pp_translate_identifiers (this)) |
1317 | pp_c_ws_string (pp: this, _(gmsgid)); |
1318 | else |
1319 | pp_c_ws_string (pp: this, str: gmsgid); |
1320 | } |
1321 | |
1322 | /* Pretty-print an IDENTIFIER_NODE, which may contain UTF-8 sequences |
1323 | that need converting to the locale encoding, preceded by whitespace |
1324 | is necessary. */ |
1325 | |
1326 | void |
1327 | pp_c_identifier (c_pretty_printer *pp, const char *id) |
1328 | { |
1329 | pp_c_maybe_whitespace (pp); |
1330 | pp_identifier (pp, id); |
1331 | pp->padding = pp_before; |
1332 | } |
1333 | |
1334 | /* Pretty-print a C primary-expression. |
1335 | primary-expression: |
1336 | identifier |
1337 | constant |
1338 | string-literal |
1339 | ( expression ) */ |
1340 | |
1341 | void |
1342 | c_pretty_printer::primary_expression (tree e) |
1343 | { |
1344 | switch (TREE_CODE (e)) |
1345 | { |
1346 | case VAR_DECL: |
1347 | case PARM_DECL: |
1348 | case FIELD_DECL: |
1349 | case CONST_DECL: |
1350 | case FUNCTION_DECL: |
1351 | case LABEL_DECL: |
1352 | pp_c_tree_decl_identifier (this, e); |
1353 | break; |
1354 | |
1355 | case IDENTIFIER_NODE: |
1356 | pp_c_tree_identifier (this, e); |
1357 | break; |
1358 | |
1359 | case ERROR_MARK: |
1360 | translate_string (gmsgid: "<erroneous-expression>" ); |
1361 | break; |
1362 | |
1363 | case RESULT_DECL: |
1364 | translate_string (gmsgid: "<return-value>" ); |
1365 | break; |
1366 | |
1367 | case VOID_CST: |
1368 | case INTEGER_CST: |
1369 | case REAL_CST: |
1370 | case FIXED_CST: |
1371 | case STRING_CST: |
1372 | constant (e); |
1373 | break; |
1374 | |
1375 | case TARGET_EXPR: |
1376 | pp_c_ws_string (pp: this, str: "__builtin_memcpy" ); |
1377 | pp_c_left_paren (pp: this); |
1378 | pp_ampersand (this); |
1379 | primary_expression (TREE_OPERAND (e, 0)); |
1380 | pp_separate_with (this, ','); |
1381 | pp_ampersand (this); |
1382 | initializer (TREE_OPERAND (e, 1)); |
1383 | if (TREE_OPERAND (e, 2)) |
1384 | { |
1385 | pp_separate_with (this, ','); |
1386 | expression (TREE_OPERAND (e, 2)); |
1387 | } |
1388 | pp_c_right_paren (pp: this); |
1389 | break; |
1390 | |
1391 | case SSA_NAME: |
1392 | if (SSA_NAME_VAR (e)) |
1393 | { |
1394 | tree var = SSA_NAME_VAR (e); |
1395 | if (tree id = SSA_NAME_IDENTIFIER (e)) |
1396 | { |
1397 | const char *name = IDENTIFIER_POINTER (id); |
1398 | const char *dot; |
1399 | if (DECL_ARTIFICIAL (var) && (dot = strchr (s: name, c: '.'))) |
1400 | { |
1401 | /* Print the name without the . suffix (such as in VLAs). |
1402 | Use pp_c_identifier so that it can be converted into |
1403 | the appropriate encoding. */ |
1404 | size_t size = dot - name; |
1405 | char *ident = XALLOCAVEC (char, size + 1); |
1406 | memcpy (dest: ident, src: name, n: size); |
1407 | ident[size] = '\0'; |
1408 | pp_c_identifier (pp: this, id: ident); |
1409 | } |
1410 | else |
1411 | primary_expression (e: var); |
1412 | } |
1413 | else |
1414 | primary_expression (e: var); |
1415 | } |
1416 | else if (gimple_assign_single_p (SSA_NAME_DEF_STMT (e))) |
1417 | { |
1418 | /* Print only the right side of the GIMPLE assignment. */ |
1419 | gimple *def_stmt = SSA_NAME_DEF_STMT (e); |
1420 | pp_gimple_stmt_1 (this, def_stmt, 0, TDF_RHS_ONLY); |
1421 | } |
1422 | else |
1423 | expression (e); |
1424 | break; |
1425 | |
1426 | default: |
1427 | /* FIXME: Make sure we won't get into an infinite loop. */ |
1428 | if (location_wrapper_p (exp: e)) |
1429 | expression (e); |
1430 | else |
1431 | { |
1432 | pp_c_left_paren (pp: this); |
1433 | expression (e); |
1434 | pp_c_right_paren (pp: this); |
1435 | } |
1436 | break; |
1437 | } |
1438 | } |
1439 | |
1440 | /* Print out a C initializer -- also support C compound-literals. |
1441 | initializer: |
1442 | assignment-expression: |
1443 | { initializer-list } |
1444 | { initializer-list , } */ |
1445 | |
1446 | void |
1447 | c_pretty_printer::initializer (tree e) |
1448 | { |
1449 | if (TREE_CODE (e) == CONSTRUCTOR) |
1450 | pp_c_brace_enclosed_initializer_list (this, e); |
1451 | else |
1452 | expression (e); |
1453 | } |
1454 | |
1455 | /* init-declarator: |
1456 | declarator: |
1457 | declarator = initializer */ |
1458 | |
1459 | void |
1460 | pp_c_init_declarator (c_pretty_printer *pp, tree t) |
1461 | { |
1462 | pp->declarator (t); |
1463 | /* We don't want to output function definitions here. There are handled |
1464 | elsewhere (and the syntactic form is bogus anyway). */ |
1465 | if (TREE_CODE (t) != FUNCTION_DECL && DECL_INITIAL (t)) |
1466 | { |
1467 | tree init = DECL_INITIAL (t); |
1468 | /* This C++ bit is handled here because it is easier to do so. |
1469 | In templates, the C++ parser builds a TREE_LIST for a |
1470 | direct-initialization; the TREE_PURPOSE is the variable to |
1471 | initialize and the TREE_VALUE is the initializer. */ |
1472 | if (TREE_CODE (init) == TREE_LIST) |
1473 | { |
1474 | pp_c_left_paren (pp); |
1475 | pp->expression (TREE_VALUE (init)); |
1476 | pp_right_paren (pp); |
1477 | } |
1478 | else |
1479 | { |
1480 | pp_space (pp); |
1481 | pp_equal (pp); |
1482 | pp_space (pp); |
1483 | pp->initializer (e: init); |
1484 | } |
1485 | } |
1486 | } |
1487 | |
1488 | /* initializer-list: |
1489 | designation(opt) initializer |
1490 | initializer-list , designation(opt) initializer |
1491 | |
1492 | designation: |
1493 | designator-list = |
1494 | |
1495 | designator-list: |
1496 | designator |
1497 | designator-list designator |
1498 | |
1499 | designator: |
1500 | [ constant-expression ] |
1501 | identifier */ |
1502 | |
1503 | static void |
1504 | pp_c_initializer_list (c_pretty_printer *pp, tree e) |
1505 | { |
1506 | tree type = TREE_TYPE (e); |
1507 | const enum tree_code code = TREE_CODE (type); |
1508 | |
1509 | if (TREE_CODE (e) == CONSTRUCTOR) |
1510 | { |
1511 | pp_c_constructor_elts (pp, CONSTRUCTOR_ELTS (e)); |
1512 | return; |
1513 | } |
1514 | |
1515 | switch (code) |
1516 | { |
1517 | case RECORD_TYPE: |
1518 | case UNION_TYPE: |
1519 | case ARRAY_TYPE: |
1520 | { |
1521 | tree init = TREE_OPERAND (e, 0); |
1522 | for (; init != NULL_TREE; init = TREE_CHAIN (init)) |
1523 | { |
1524 | if (code == RECORD_TYPE || code == UNION_TYPE) |
1525 | { |
1526 | pp_c_dot (pp); |
1527 | pp->primary_expression (TREE_PURPOSE (init)); |
1528 | } |
1529 | else |
1530 | { |
1531 | pp_c_left_bracket (pp); |
1532 | if (TREE_PURPOSE (init)) |
1533 | pp->constant (TREE_PURPOSE (init)); |
1534 | pp_c_right_bracket (pp); |
1535 | } |
1536 | pp_c_whitespace (pp); |
1537 | pp_equal (pp); |
1538 | pp_c_whitespace (pp); |
1539 | pp->initializer (TREE_VALUE (init)); |
1540 | if (TREE_CHAIN (init)) |
1541 | pp_separate_with (pp, ','); |
1542 | } |
1543 | } |
1544 | return; |
1545 | |
1546 | case VECTOR_TYPE: |
1547 | if (TREE_CODE (e) == VECTOR_CST) |
1548 | { |
1549 | /* We don't create variable-length VECTOR_CSTs. */ |
1550 | unsigned int nunits = VECTOR_CST_NELTS (e).to_constant (); |
1551 | for (unsigned int i = 0; i < nunits; ++i) |
1552 | { |
1553 | if (i > 0) |
1554 | pp_separate_with (pp, ','); |
1555 | pp->expression (VECTOR_CST_ELT (e, i)); |
1556 | } |
1557 | } |
1558 | else |
1559 | break; |
1560 | return; |
1561 | |
1562 | case COMPLEX_TYPE: |
1563 | if (TREE_CODE (e) == COMPLEX_CST || TREE_CODE (e) == COMPLEX_EXPR) |
1564 | { |
1565 | const bool cst = TREE_CODE (e) == COMPLEX_CST; |
1566 | pp->expression (cst ? TREE_REALPART (e) : TREE_OPERAND (e, 0)); |
1567 | pp_separate_with (pp, ','); |
1568 | pp->expression (cst ? TREE_IMAGPART (e) : TREE_OPERAND (e, 1)); |
1569 | } |
1570 | else |
1571 | break; |
1572 | return; |
1573 | |
1574 | default: |
1575 | break; |
1576 | } |
1577 | |
1578 | pp_unsupported_tree (pp, type); |
1579 | } |
1580 | |
1581 | /* Pretty-print a brace-enclosed initializer-list. */ |
1582 | |
1583 | static void |
1584 | pp_c_brace_enclosed_initializer_list (c_pretty_printer *pp, tree l) |
1585 | { |
1586 | pp_c_left_brace (pp); |
1587 | pp_c_initializer_list (pp, e: l); |
1588 | pp_c_right_brace (pp); |
1589 | } |
1590 | |
1591 | |
1592 | /* This is a convenient function, used to bridge gap between C and C++ |
1593 | grammars. |
1594 | |
1595 | id-expression: |
1596 | identifier */ |
1597 | |
1598 | void |
1599 | c_pretty_printer::id_expression (tree t) |
1600 | { |
1601 | switch (TREE_CODE (t)) |
1602 | { |
1603 | case VAR_DECL: |
1604 | case PARM_DECL: |
1605 | case CONST_DECL: |
1606 | case TYPE_DECL: |
1607 | case FUNCTION_DECL: |
1608 | case FIELD_DECL: |
1609 | case LABEL_DECL: |
1610 | pp_c_tree_decl_identifier (this, t); |
1611 | break; |
1612 | |
1613 | case IDENTIFIER_NODE: |
1614 | pp_c_tree_identifier (this, t); |
1615 | break; |
1616 | |
1617 | default: |
1618 | pp_unsupported_tree (this, t); |
1619 | break; |
1620 | } |
1621 | } |
1622 | |
1623 | /* postfix-expression: |
1624 | primary-expression |
1625 | postfix-expression [ expression ] |
1626 | postfix-expression ( argument-expression-list(opt) ) |
1627 | postfix-expression . identifier |
1628 | postfix-expression -> identifier |
1629 | postfix-expression ++ |
1630 | postfix-expression -- |
1631 | ( type-name ) { initializer-list } |
1632 | ( type-name ) { initializer-list , } */ |
1633 | |
1634 | void |
1635 | c_pretty_printer::postfix_expression (tree e) |
1636 | { |
1637 | enum tree_code code = TREE_CODE (e); |
1638 | switch (code) |
1639 | { |
1640 | case POSTINCREMENT_EXPR: |
1641 | case POSTDECREMENT_EXPR: |
1642 | postfix_expression (TREE_OPERAND (e, 0)); |
1643 | pp_string (this, code == POSTINCREMENT_EXPR ? "++" : "--" ); |
1644 | break; |
1645 | |
1646 | case ARRAY_REF: |
1647 | postfix_expression (TREE_OPERAND (e, 0)); |
1648 | pp_c_left_bracket (pp: this); |
1649 | expression (TREE_OPERAND (e, 1)); |
1650 | pp_c_right_bracket (pp: this); |
1651 | break; |
1652 | |
1653 | case CALL_EXPR: |
1654 | { |
1655 | call_expr_arg_iterator iter; |
1656 | tree arg; |
1657 | if (CALL_EXPR_FN (e) != NULL_TREE) |
1658 | postfix_expression (CALL_EXPR_FN (e)); |
1659 | else |
1660 | pp_string (this, internal_fn_name (CALL_EXPR_IFN (e))); |
1661 | pp_c_left_paren (pp: this); |
1662 | FOR_EACH_CALL_EXPR_ARG (arg, iter, e) |
1663 | { |
1664 | expression (arg); |
1665 | if (more_call_expr_args_p (iter: &iter)) |
1666 | pp_separate_with (this, ','); |
1667 | } |
1668 | pp_c_right_paren (pp: this); |
1669 | break; |
1670 | } |
1671 | |
1672 | case UNORDERED_EXPR: |
1673 | pp_c_ws_string (pp: this, str: flag_isoc99 |
1674 | ? "isunordered" |
1675 | : "__builtin_isunordered" ); |
1676 | goto two_args_fun; |
1677 | |
1678 | case ORDERED_EXPR: |
1679 | pp_c_ws_string (pp: this, str: flag_isoc99 |
1680 | ? "!isunordered" |
1681 | : "!__builtin_isunordered" ); |
1682 | goto two_args_fun; |
1683 | |
1684 | case UNLT_EXPR: |
1685 | pp_c_ws_string (pp: this, str: flag_isoc99 |
1686 | ? "!isgreaterequal" |
1687 | : "!__builtin_isgreaterequal" ); |
1688 | goto two_args_fun; |
1689 | |
1690 | case UNLE_EXPR: |
1691 | pp_c_ws_string (pp: this, str: flag_isoc99 |
1692 | ? "!isgreater" |
1693 | : "!__builtin_isgreater" ); |
1694 | goto two_args_fun; |
1695 | |
1696 | case UNGT_EXPR: |
1697 | pp_c_ws_string (pp: this, str: flag_isoc99 |
1698 | ? "!islessequal" |
1699 | : "!__builtin_islessequal" ); |
1700 | goto two_args_fun; |
1701 | |
1702 | case UNGE_EXPR: |
1703 | pp_c_ws_string (pp: this, str: flag_isoc99 |
1704 | ? "!isless" |
1705 | : "!__builtin_isless" ); |
1706 | goto two_args_fun; |
1707 | |
1708 | case UNEQ_EXPR: |
1709 | pp_c_ws_string (pp: this, str: flag_isoc99 |
1710 | ? "!islessgreater" |
1711 | : "!__builtin_islessgreater" ); |
1712 | goto two_args_fun; |
1713 | |
1714 | case LTGT_EXPR: |
1715 | pp_c_ws_string (pp: this, str: flag_isoc99 |
1716 | ? "islessgreater" |
1717 | : "__builtin_islessgreater" ); |
1718 | goto two_args_fun; |
1719 | |
1720 | case MAX_EXPR: |
1721 | pp_c_ws_string (pp: this, str: "max" ); |
1722 | goto two_args_fun; |
1723 | |
1724 | case MIN_EXPR: |
1725 | pp_c_ws_string (pp: this, str: "min" ); |
1726 | goto two_args_fun; |
1727 | |
1728 | two_args_fun: |
1729 | pp_c_left_paren (pp: this); |
1730 | expression (TREE_OPERAND (e, 0)); |
1731 | pp_separate_with (this, ','); |
1732 | expression (TREE_OPERAND (e, 1)); |
1733 | pp_c_right_paren (pp: this); |
1734 | break; |
1735 | |
1736 | case ABS_EXPR: |
1737 | pp_c_ws_string (pp: this, str: "__builtin_abs" ); |
1738 | pp_c_left_paren (pp: this); |
1739 | expression (TREE_OPERAND (e, 0)); |
1740 | pp_c_right_paren (pp: this); |
1741 | break; |
1742 | |
1743 | case COMPONENT_REF: |
1744 | { |
1745 | tree object = TREE_OPERAND (e, 0); |
1746 | if (INDIRECT_REF_P (object)) |
1747 | { |
1748 | postfix_expression (TREE_OPERAND (object, 0)); |
1749 | pp_c_arrow (pp: this); |
1750 | } |
1751 | else |
1752 | { |
1753 | postfix_expression (e: object); |
1754 | pp_c_dot (pp: this); |
1755 | } |
1756 | expression (TREE_OPERAND (e, 1)); |
1757 | } |
1758 | break; |
1759 | |
1760 | case BIT_FIELD_REF: |
1761 | { |
1762 | tree type = TREE_TYPE (e); |
1763 | |
1764 | type = signed_or_unsigned_type_for (TYPE_UNSIGNED (type), type); |
1765 | if (type |
1766 | && tree_int_cst_equal (TYPE_SIZE (type), TREE_OPERAND (e, 1))) |
1767 | { |
1768 | HOST_WIDE_INT bitpos = tree_to_shwi (TREE_OPERAND (e, 2)); |
1769 | HOST_WIDE_INT size = tree_to_shwi (TYPE_SIZE (type)); |
1770 | if ((bitpos % size) == 0) |
1771 | { |
1772 | pp_c_left_paren (pp: this); |
1773 | pp_c_left_paren (pp: this); |
1774 | type_id (t: type); |
1775 | pp_c_star (pp: this); |
1776 | pp_c_right_paren (pp: this); |
1777 | pp_c_ampersand (pp: this); |
1778 | expression (TREE_OPERAND (e, 0)); |
1779 | pp_c_right_paren (pp: this); |
1780 | pp_c_left_bracket (pp: this); |
1781 | pp_wide_integer (pp: this, i: bitpos / size); |
1782 | pp_c_right_bracket (pp: this); |
1783 | break; |
1784 | } |
1785 | } |
1786 | pp_unsupported_tree (this, e); |
1787 | } |
1788 | break; |
1789 | |
1790 | case MEM_REF: |
1791 | case TARGET_MEM_REF: |
1792 | expression (e); |
1793 | break; |
1794 | |
1795 | case COMPLEX_CST: |
1796 | case VECTOR_CST: |
1797 | pp_c_compound_literal (pp: this, e); |
1798 | break; |
1799 | |
1800 | case COMPLEX_EXPR: |
1801 | pp_c_complex_expr (pp: this, e); |
1802 | break; |
1803 | |
1804 | case COMPOUND_LITERAL_EXPR: |
1805 | e = DECL_INITIAL (COMPOUND_LITERAL_EXPR_DECL (e)); |
1806 | /* Fall through. */ |
1807 | case CONSTRUCTOR: |
1808 | initializer (e); |
1809 | break; |
1810 | |
1811 | case VA_ARG_EXPR: |
1812 | pp_c_ws_string (pp: this, str: "__builtin_va_arg" ); |
1813 | pp_c_left_paren (pp: this); |
1814 | assignment_expression (TREE_OPERAND (e, 0)); |
1815 | pp_separate_with (this, ','); |
1816 | type_id (TREE_TYPE (e)); |
1817 | pp_c_right_paren (pp: this); |
1818 | break; |
1819 | |
1820 | case ADDR_EXPR: |
1821 | if (TREE_CODE (TREE_OPERAND (e, 0)) == FUNCTION_DECL) |
1822 | { |
1823 | id_expression (TREE_OPERAND (e, 0)); |
1824 | break; |
1825 | } |
1826 | /* fall through. */ |
1827 | |
1828 | default: |
1829 | primary_expression (e); |
1830 | break; |
1831 | } |
1832 | } |
1833 | |
1834 | /* Print out an expression-list; E is expected to be a TREE_LIST. */ |
1835 | |
1836 | void |
1837 | pp_c_expression_list (c_pretty_printer *pp, tree e) |
1838 | { |
1839 | for (; e != NULL_TREE; e = TREE_CHAIN (e)) |
1840 | { |
1841 | pp->expression (TREE_VALUE (e)); |
1842 | if (TREE_CHAIN (e)) |
1843 | pp_separate_with (pp, ','); |
1844 | } |
1845 | } |
1846 | |
1847 | /* Print out V, which contains the elements of a constructor. */ |
1848 | |
1849 | void |
1850 | pp_c_constructor_elts (c_pretty_printer *pp, vec<constructor_elt, va_gc> *v) |
1851 | { |
1852 | unsigned HOST_WIDE_INT ix; |
1853 | tree value; |
1854 | |
1855 | FOR_EACH_CONSTRUCTOR_VALUE (v, ix, value) |
1856 | { |
1857 | pp->expression (value); |
1858 | if (ix != vec_safe_length (v) - 1) |
1859 | pp_separate_with (pp, ','); |
1860 | } |
1861 | } |
1862 | |
1863 | /* Print out an expression-list in parens, as if it were the argument |
1864 | list to a function. */ |
1865 | |
1866 | void |
1867 | pp_c_call_argument_list (c_pretty_printer *pp, tree t) |
1868 | { |
1869 | pp_c_left_paren (pp); |
1870 | if (t && TREE_CODE (t) == TREE_LIST) |
1871 | pp_c_expression_list (pp, e: t); |
1872 | pp_c_right_paren (pp); |
1873 | } |
1874 | |
1875 | /* Try to fold *(type *)&op into op.fld.fld2[1] if possible. |
1876 | Only used for printing expressions. Should punt if ambiguous |
1877 | (e.g. in unions). */ |
1878 | |
1879 | static tree |
1880 | c_fold_indirect_ref_for_warn (location_t loc, tree type, tree op, |
1881 | offset_int &off) |
1882 | { |
1883 | tree optype = TREE_TYPE (op); |
1884 | if (off == 0) |
1885 | { |
1886 | if (lang_hooks.types_compatible_p (optype, type)) |
1887 | return op; |
1888 | /* *(foo *)&complexfoo => __real__ complexfoo */ |
1889 | else if (TREE_CODE (optype) == COMPLEX_TYPE |
1890 | && lang_hooks.types_compatible_p (type, TREE_TYPE (optype))) |
1891 | return build1_loc (loc, code: REALPART_EXPR, type, arg1: op); |
1892 | } |
1893 | /* ((foo*)&complexfoo)[1] => __imag__ complexfoo */ |
1894 | else if (TREE_CODE (optype) == COMPLEX_TYPE |
1895 | && lang_hooks.types_compatible_p (type, TREE_TYPE (optype)) |
1896 | && tree_to_uhwi (TYPE_SIZE_UNIT (type)) == off) |
1897 | { |
1898 | off = 0; |
1899 | return build1_loc (loc, code: IMAGPART_EXPR, type, arg1: op); |
1900 | } |
1901 | /* ((foo *)&fooarray)[x] => fooarray[x] */ |
1902 | if (TREE_CODE (optype) == ARRAY_TYPE |
1903 | && TYPE_SIZE_UNIT (TREE_TYPE (optype)) |
1904 | && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (optype))) == INTEGER_CST |
1905 | && !integer_zerop (TYPE_SIZE_UNIT (TREE_TYPE (optype)))) |
1906 | { |
1907 | tree type_domain = TYPE_DOMAIN (optype); |
1908 | tree min_val = size_zero_node; |
1909 | if (type_domain && TYPE_MIN_VALUE (type_domain)) |
1910 | min_val = TYPE_MIN_VALUE (type_domain); |
1911 | offset_int el_sz = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (optype))); |
1912 | offset_int idx = off / el_sz; |
1913 | offset_int rem = off % el_sz; |
1914 | if (TREE_CODE (min_val) == INTEGER_CST) |
1915 | { |
1916 | tree index |
1917 | = wide_int_to_tree (sizetype, cst: idx + wi::to_offset (t: min_val)); |
1918 | op = build4_loc (loc, code: ARRAY_REF, TREE_TYPE (optype), arg0: op, arg1: index, |
1919 | NULL_TREE, NULL_TREE); |
1920 | off = rem; |
1921 | if (tree ret = c_fold_indirect_ref_for_warn (loc, type, op, off)) |
1922 | return ret; |
1923 | return op; |
1924 | } |
1925 | } |
1926 | /* ((foo *)&struct_with_foo_field)[x] => COMPONENT_REF */ |
1927 | else if (TREE_CODE (optype) == RECORD_TYPE) |
1928 | { |
1929 | for (tree field = TYPE_FIELDS (optype); |
1930 | field; field = DECL_CHAIN (field)) |
1931 | if (TREE_CODE (field) == FIELD_DECL |
1932 | && TREE_TYPE (field) != error_mark_node |
1933 | && TYPE_SIZE_UNIT (TREE_TYPE (field)) |
1934 | && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (field))) == INTEGER_CST) |
1935 | { |
1936 | tree pos = byte_position (field); |
1937 | if (TREE_CODE (pos) != INTEGER_CST) |
1938 | continue; |
1939 | offset_int upos = wi::to_offset (t: pos); |
1940 | offset_int el_sz |
1941 | = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (field))); |
1942 | if (upos <= off && off < upos + el_sz) |
1943 | { |
1944 | /* The C++ pretty printers print scope of the FIELD_DECLs, |
1945 | so punt if it is something that can't be printed. */ |
1946 | if (c_dialect_cxx ()) |
1947 | if (tree scope = get_containing_scope (field)) |
1948 | if (TYPE_P (scope) && TYPE_NAME (scope) == NULL_TREE) |
1949 | break; |
1950 | tree cop = build3_loc (loc, code: COMPONENT_REF, TREE_TYPE (field), |
1951 | arg0: op, arg1: field, NULL_TREE); |
1952 | off = off - upos; |
1953 | if (tree ret = c_fold_indirect_ref_for_warn (loc, type, op: cop, |
1954 | off)) |
1955 | return ret; |
1956 | return cop; |
1957 | } |
1958 | } |
1959 | } |
1960 | /* Similarly for unions, but in this case try to be very conservative, |
1961 | only match if some field has type compatible with type and it is the |
1962 | only such field. */ |
1963 | else if (TREE_CODE (optype) == UNION_TYPE) |
1964 | { |
1965 | tree fld = NULL_TREE; |
1966 | for (tree field = TYPE_FIELDS (optype); |
1967 | field; field = DECL_CHAIN (field)) |
1968 | if (TREE_CODE (field) == FIELD_DECL |
1969 | && TREE_TYPE (field) != error_mark_node |
1970 | && lang_hooks.types_compatible_p (TREE_TYPE (field), type)) |
1971 | { |
1972 | if (fld) |
1973 | return NULL_TREE; |
1974 | else |
1975 | fld = field; |
1976 | } |
1977 | if (fld) |
1978 | { |
1979 | off = 0; |
1980 | return build3_loc (loc, code: COMPONENT_REF, TREE_TYPE (fld), arg0: op, arg1: fld, |
1981 | NULL_TREE); |
1982 | } |
1983 | } |
1984 | |
1985 | return NULL_TREE; |
1986 | } |
1987 | |
1988 | /* Print the MEM_REF expression REF, including its type and offset. |
1989 | Apply casts as necessary if the type of the access is different |
1990 | from the type of the accessed object. Produce compact output |
1991 | designed to include both the element index as well as any |
1992 | misalignment by preferring |
1993 | ((int*)((char*)p + 1))[2] |
1994 | over |
1995 | *(int*)((char*)p + 9) |
1996 | The former is more verbose but makes it clearer that the access |
1997 | to the third element of the array is misaligned by one byte. */ |
1998 | |
1999 | static void |
2000 | print_mem_ref (c_pretty_printer *pp, tree e) |
2001 | { |
2002 | tree arg = TREE_OPERAND (e, 0); |
2003 | |
2004 | /* The byte offset. Initially equal to the MEM_REF offset, then |
2005 | adjusted to the remainder of the division by the byte size of |
2006 | the access. */ |
2007 | offset_int byte_off = wi::to_offset (TREE_OPERAND (e, 1)); |
2008 | /* The result of dividing BYTE_OFF by the size of the access. */ |
2009 | offset_int elt_idx = 0; |
2010 | /* True to include a cast to char* (for a nonzero final BYTE_OFF). */ |
2011 | bool char_cast = false; |
2012 | tree op = NULL_TREE; |
2013 | bool array_ref_only = false; |
2014 | if (TREE_CODE (arg) == ADDR_EXPR) |
2015 | { |
2016 | op = c_fold_indirect_ref_for_warn (EXPR_LOCATION (e), TREE_TYPE (e), |
2017 | TREE_OPERAND (arg, 0), off&: byte_off); |
2018 | /* Try to fold it back to component, array ref or their combination, |
2019 | but print it only if the types and TBAA types are compatible. */ |
2020 | if (op |
2021 | && byte_off == 0 |
2022 | && lang_hooks.types_compatible_p (TREE_TYPE (e), TREE_TYPE (op)) |
2023 | && (!flag_strict_aliasing |
2024 | || (get_deref_alias_set (TREE_OPERAND (e, 1)) |
2025 | == get_alias_set (op)))) |
2026 | { |
2027 | pp->expression (op); |
2028 | return; |
2029 | } |
2030 | if (op == NULL_TREE) |
2031 | op = TREE_OPERAND (arg, 0); |
2032 | /* If the types or TBAA types are incompatible, undo the |
2033 | UNION_TYPE handling from c_fold_indirect_ref_for_warn, and similarly |
2034 | undo __real__/__imag__ the code below doesn't try to handle. */ |
2035 | if (op != TREE_OPERAND (arg, 0) |
2036 | && ((TREE_CODE (op) == COMPONENT_REF |
2037 | && TREE_CODE (TREE_TYPE (TREE_OPERAND (op, 0))) == UNION_TYPE) |
2038 | || TREE_CODE (op) == REALPART_EXPR |
2039 | || TREE_CODE (op) == IMAGPART_EXPR)) |
2040 | op = TREE_OPERAND (op, 0); |
2041 | if (op != TREE_OPERAND (arg, 0)) |
2042 | { |
2043 | array_ref_only = true; |
2044 | for (tree ref = op; ref != TREE_OPERAND (arg, 0); |
2045 | ref = TREE_OPERAND (ref, 0)) |
2046 | if (TREE_CODE (ref) != ARRAY_REF) |
2047 | { |
2048 | array_ref_only = false; |
2049 | break; |
2050 | } |
2051 | } |
2052 | } |
2053 | |
2054 | tree access_type = TREE_TYPE (e); |
2055 | tree arg_type = TREE_TYPE (TREE_TYPE (arg)); |
2056 | if (tree access_size = TYPE_SIZE_UNIT (access_type)) |
2057 | if (byte_off != 0 |
2058 | && TREE_CODE (access_size) == INTEGER_CST |
2059 | && !integer_zerop (access_size)) |
2060 | { |
2061 | offset_int asize = wi::to_offset (t: access_size); |
2062 | elt_idx = byte_off / asize; |
2063 | byte_off = byte_off % asize; |
2064 | } |
2065 | |
2066 | /* True to include a cast to the accessed type. */ |
2067 | const bool access_cast |
2068 | = ((op && op != TREE_OPERAND (arg, 0)) |
2069 | || VOID_TYPE_P (arg_type) |
2070 | || !lang_hooks.types_compatible_p (access_type, arg_type)); |
2071 | const bool has_off = byte_off != 0 || (op && op != TREE_OPERAND (arg, 0)); |
2072 | |
2073 | if (has_off && (byte_off != 0 || !array_ref_only)) |
2074 | { |
2075 | /* When printing the byte offset for a pointer to a type of |
2076 | a different size than char, include a cast to char* first, |
2077 | before printing the cast to a pointer to the accessed type. */ |
2078 | tree size = TYPE_SIZE (arg_type); |
2079 | if (size == NULL_TREE |
2080 | || TREE_CODE (size) != INTEGER_CST |
2081 | || wi::to_wide (t: size) != BITS_PER_UNIT) |
2082 | char_cast = true; |
2083 | } |
2084 | |
2085 | if (elt_idx == 0) |
2086 | pp_c_star (pp); |
2087 | else if (access_cast || char_cast) |
2088 | pp_c_left_paren (pp); |
2089 | |
2090 | if (access_cast) |
2091 | { |
2092 | /* Include a cast to the accessed type if it isn't compatible |
2093 | with the type of the referenced object (or if the object |
2094 | is typeless). */ |
2095 | pp_c_left_paren (pp); |
2096 | pp->type_id (t: build_pointer_type (access_type)); |
2097 | pp_c_right_paren (pp); |
2098 | } |
2099 | |
2100 | if (has_off) |
2101 | pp_c_left_paren (pp); |
2102 | |
2103 | if (char_cast) |
2104 | { |
2105 | /* Include a cast to char *. */ |
2106 | pp_c_left_paren (pp); |
2107 | pp->type_id (string_type_node); |
2108 | pp_c_right_paren (pp); |
2109 | } |
2110 | |
2111 | pp->unary_expression (arg); |
2112 | |
2113 | if (op && op != TREE_OPERAND (arg, 0)) |
2114 | { |
2115 | auto_vec<tree, 16> refs; |
2116 | tree ref; |
2117 | unsigned i; |
2118 | bool array_refs = true; |
2119 | for (ref = op; ref != TREE_OPERAND (arg, 0); ref = TREE_OPERAND (ref, 0)) |
2120 | refs.safe_push (obj: ref); |
2121 | FOR_EACH_VEC_ELT_REVERSE (refs, i, ref) |
2122 | if (array_refs && TREE_CODE (ref) == ARRAY_REF) |
2123 | { |
2124 | pp_c_left_bracket (pp); |
2125 | pp->expression (TREE_OPERAND (ref, 1)); |
2126 | pp_c_right_bracket (pp); |
2127 | } |
2128 | else |
2129 | { |
2130 | if (array_refs) |
2131 | { |
2132 | array_refs = false; |
2133 | pp_string (pp, " + offsetof" ); |
2134 | pp_c_left_paren (pp); |
2135 | pp->type_id (TREE_TYPE (TREE_OPERAND (ref, 0))); |
2136 | pp_comma (pp); |
2137 | } |
2138 | else if (TREE_CODE (ref) == COMPONENT_REF) |
2139 | pp_c_dot (pp); |
2140 | if (TREE_CODE (ref) == COMPONENT_REF) |
2141 | pp->expression (TREE_OPERAND (ref, 1)); |
2142 | else |
2143 | { |
2144 | pp_c_left_bracket (pp); |
2145 | pp->expression (TREE_OPERAND (ref, 1)); |
2146 | pp_c_right_bracket (pp); |
2147 | } |
2148 | } |
2149 | if (!array_refs) |
2150 | pp_c_right_paren (pp); |
2151 | } |
2152 | |
2153 | if (byte_off != 0) |
2154 | { |
2155 | pp_space (pp); |
2156 | pp_plus (pp); |
2157 | pp_space (pp); |
2158 | tree off = wide_int_to_tree (ssizetype, cst: byte_off); |
2159 | pp->constant (e: off); |
2160 | } |
2161 | |
2162 | if (has_off) |
2163 | pp_c_right_paren (pp); |
2164 | |
2165 | if (elt_idx != 0) |
2166 | { |
2167 | if (access_cast || char_cast) |
2168 | pp_c_right_paren (pp); |
2169 | |
2170 | pp_c_left_bracket (pp); |
2171 | tree idx = wide_int_to_tree (ssizetype, cst: elt_idx); |
2172 | pp->constant (e: idx); |
2173 | pp_c_right_bracket (pp); |
2174 | } |
2175 | } |
2176 | |
2177 | /* unary-expression: |
2178 | postfix-expression |
2179 | ++ cast-expression |
2180 | -- cast-expression |
2181 | unary-operator cast-expression |
2182 | sizeof unary-expression |
2183 | sizeof ( type-id ) |
2184 | |
2185 | unary-operator: one of |
2186 | * & + - ! ~ |
2187 | |
2188 | GNU extensions. |
2189 | unary-expression: |
2190 | __alignof__ unary-expression |
2191 | __alignof__ ( type-id ) |
2192 | __real__ unary-expression |
2193 | __imag__ unary-expression */ |
2194 | |
2195 | void |
2196 | c_pretty_printer::unary_expression (tree e) |
2197 | { |
2198 | enum tree_code code = TREE_CODE (e); |
2199 | switch (code) |
2200 | { |
2201 | case PREINCREMENT_EXPR: |
2202 | case PREDECREMENT_EXPR: |
2203 | pp_string (this, code == PREINCREMENT_EXPR ? "++" : "--" ); |
2204 | unary_expression (TREE_OPERAND (e, 0)); |
2205 | break; |
2206 | |
2207 | case ADDR_EXPR: |
2208 | case INDIRECT_REF: |
2209 | case NEGATE_EXPR: |
2210 | case BIT_NOT_EXPR: |
2211 | case TRUTH_NOT_EXPR: |
2212 | case CONJ_EXPR: |
2213 | /* String literal are used by address. */ |
2214 | if (code == ADDR_EXPR && TREE_CODE (TREE_OPERAND (e, 0)) != STRING_CST) |
2215 | pp_ampersand (this); |
2216 | else if (code == INDIRECT_REF) |
2217 | { |
2218 | tree type = TREE_TYPE (TREE_OPERAND (e, 0)); |
2219 | if (type && TREE_CODE (type) == REFERENCE_TYPE) |
2220 | /* Reference decay is implicit, don't print anything. */; |
2221 | else |
2222 | pp_c_star (pp: this); |
2223 | } |
2224 | else if (code == NEGATE_EXPR) |
2225 | pp_minus (this); |
2226 | else if (code == BIT_NOT_EXPR || code == CONJ_EXPR) |
2227 | pp_complement (this); |
2228 | else if (code == TRUTH_NOT_EXPR) |
2229 | pp_exclamation (this); |
2230 | pp_c_cast_expression (this, TREE_OPERAND (e, 0)); |
2231 | break; |
2232 | |
2233 | case MEM_REF: |
2234 | print_mem_ref (pp: this, e); |
2235 | break; |
2236 | |
2237 | case TARGET_MEM_REF: |
2238 | /* TARGET_MEM_REF can't appear directly from source, but can appear |
2239 | during late GIMPLE optimizations and through late diagnostic we might |
2240 | need to support it. Print it as dereferencing of a pointer after |
2241 | cast to the TARGET_MEM_REF type, with pointer arithmetics on some |
2242 | pointer to single byte types, so |
2243 | *(type *)((char *) ptr + step * index + index2) if all the operands |
2244 | are present and the casts are needed. */ |
2245 | pp_c_star (pp: this); |
2246 | if (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (TMR_BASE (e)))) == NULL_TREE |
2247 | || !integer_onep (TYPE_SIZE_UNIT |
2248 | (TREE_TYPE (TREE_TYPE (TMR_BASE (e)))))) |
2249 | { |
2250 | if (TYPE_SIZE_UNIT (TREE_TYPE (e)) |
2251 | && integer_onep (TYPE_SIZE_UNIT (TREE_TYPE (e)))) |
2252 | { |
2253 | pp_c_left_paren (pp: this); |
2254 | pp_c_type_cast (pp: this, t: build_pointer_type (TREE_TYPE (e))); |
2255 | } |
2256 | else |
2257 | { |
2258 | pp_c_type_cast (pp: this, t: build_pointer_type (TREE_TYPE (e))); |
2259 | pp_c_left_paren (pp: this); |
2260 | pp_c_type_cast (pp: this, t: build_pointer_type (char_type_node)); |
2261 | } |
2262 | } |
2263 | else if (!lang_hooks.types_compatible_p |
2264 | (TREE_TYPE (e), TREE_TYPE (TREE_TYPE (TMR_BASE (e))))) |
2265 | { |
2266 | pp_c_type_cast (pp: this, t: build_pointer_type (TREE_TYPE (e))); |
2267 | pp_c_left_paren (pp: this); |
2268 | } |
2269 | else |
2270 | pp_c_left_paren (pp: this); |
2271 | pp_c_cast_expression (this, TMR_BASE (e)); |
2272 | if (TMR_STEP (e) && TMR_INDEX (e)) |
2273 | { |
2274 | pp_plus (this); |
2275 | pp_c_cast_expression (this, TMR_INDEX (e)); |
2276 | pp_c_star (pp: this); |
2277 | pp_c_cast_expression (this, TMR_STEP (e)); |
2278 | } |
2279 | if (TMR_INDEX2 (e)) |
2280 | { |
2281 | pp_plus (this); |
2282 | pp_c_cast_expression (this, TMR_INDEX2 (e)); |
2283 | } |
2284 | if (!integer_zerop (TMR_OFFSET (e))) |
2285 | { |
2286 | pp_plus (this); |
2287 | pp_c_integer_constant (pp: this, |
2288 | fold_convert (ssizetype, TMR_OFFSET (e))); |
2289 | } |
2290 | pp_c_right_paren (pp: this); |
2291 | break; |
2292 | |
2293 | case REALPART_EXPR: |
2294 | case IMAGPART_EXPR: |
2295 | pp_c_ws_string (pp: this, str: code == REALPART_EXPR ? "__real__" : "__imag__" ); |
2296 | pp_c_whitespace (pp: this); |
2297 | unary_expression (TREE_OPERAND (e, 0)); |
2298 | break; |
2299 | |
2300 | default: |
2301 | postfix_expression (e); |
2302 | break; |
2303 | } |
2304 | } |
2305 | |
2306 | /* cast-expression: |
2307 | unary-expression |
2308 | ( type-name ) cast-expression */ |
2309 | |
2310 | void |
2311 | pp_c_cast_expression (c_pretty_printer *pp, tree e) |
2312 | { |
2313 | switch (TREE_CODE (e)) |
2314 | { |
2315 | case FLOAT_EXPR: |
2316 | case FIX_TRUNC_EXPR: |
2317 | CASE_CONVERT: |
2318 | case VIEW_CONVERT_EXPR: |
2319 | if (!location_wrapper_p (exp: e)) |
2320 | pp_c_type_cast (pp, TREE_TYPE (e)); |
2321 | pp_c_cast_expression (pp, TREE_OPERAND (e, 0)); |
2322 | break; |
2323 | |
2324 | default: |
2325 | pp->unary_expression (e); |
2326 | } |
2327 | } |
2328 | |
2329 | /* multiplicative-expression: |
2330 | cast-expression |
2331 | multiplicative-expression * cast-expression |
2332 | multiplicative-expression / cast-expression |
2333 | multiplicative-expression % cast-expression */ |
2334 | |
2335 | void |
2336 | c_pretty_printer::multiplicative_expression (tree e) |
2337 | { |
2338 | enum tree_code code = TREE_CODE (e); |
2339 | switch (code) |
2340 | { |
2341 | case MULT_EXPR: |
2342 | case TRUNC_DIV_EXPR: |
2343 | case TRUNC_MOD_EXPR: |
2344 | case EXACT_DIV_EXPR: |
2345 | case RDIV_EXPR: |
2346 | multiplicative_expression (TREE_OPERAND (e, 0)); |
2347 | pp_c_whitespace (pp: this); |
2348 | if (code == MULT_EXPR) |
2349 | pp_c_star (pp: this); |
2350 | else if (code != TRUNC_MOD_EXPR) |
2351 | pp_slash (this); |
2352 | else |
2353 | pp_modulo (this); |
2354 | pp_c_whitespace (pp: this); |
2355 | pp_c_cast_expression (pp: this, TREE_OPERAND (e, 1)); |
2356 | break; |
2357 | |
2358 | default: |
2359 | pp_c_cast_expression (pp: this, e); |
2360 | break; |
2361 | } |
2362 | } |
2363 | |
2364 | /* additive-expression: |
2365 | multiplicative-expression |
2366 | additive-expression + multiplicative-expression |
2367 | additive-expression - multiplicative-expression */ |
2368 | |
2369 | static void |
2370 | pp_c_additive_expression (c_pretty_printer *pp, tree e) |
2371 | { |
2372 | enum tree_code code = TREE_CODE (e); |
2373 | switch (code) |
2374 | { |
2375 | case POINTER_PLUS_EXPR: |
2376 | case PLUS_EXPR: |
2377 | case POINTER_DIFF_EXPR: |
2378 | case MINUS_EXPR: |
2379 | pp_c_additive_expression (pp, TREE_OPERAND (e, 0)); |
2380 | pp_c_whitespace (pp); |
2381 | if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR) |
2382 | pp_plus (pp); |
2383 | else |
2384 | pp_minus (pp); |
2385 | pp_c_whitespace (pp); |
2386 | { |
2387 | tree op1 = TREE_OPERAND (e, 1); |
2388 | if (code == POINTER_PLUS_EXPR |
2389 | && TREE_CODE (op1) == INTEGER_CST |
2390 | && tree_int_cst_sign_bit (op1)) |
2391 | /* A pointer minus an integer is represented internally as plus a very |
2392 | large number, don't expose that to users. */ |
2393 | op1 = convert (ssizetype, op1); |
2394 | pp->multiplicative_expression (e: op1); |
2395 | } |
2396 | break; |
2397 | |
2398 | default: |
2399 | pp->multiplicative_expression (e); |
2400 | break; |
2401 | } |
2402 | } |
2403 | |
2404 | /* additive-expression: |
2405 | additive-expression |
2406 | shift-expression << additive-expression |
2407 | shift-expression >> additive-expression */ |
2408 | |
2409 | static void |
2410 | pp_c_shift_expression (c_pretty_printer *pp, tree e) |
2411 | { |
2412 | enum tree_code code = TREE_CODE (e); |
2413 | switch (code) |
2414 | { |
2415 | case LSHIFT_EXPR: |
2416 | case RSHIFT_EXPR: |
2417 | case LROTATE_EXPR: |
2418 | case RROTATE_EXPR: |
2419 | pp_c_shift_expression (pp, TREE_OPERAND (e, 0)); |
2420 | pp_c_whitespace (pp); |
2421 | pp_string (pp, code == LSHIFT_EXPR ? "<<" : |
2422 | code == RSHIFT_EXPR ? ">>" : |
2423 | code == LROTATE_EXPR ? "<<<" : ">>>" ); |
2424 | pp_c_whitespace (pp); |
2425 | pp_c_additive_expression (pp, TREE_OPERAND (e, 1)); |
2426 | break; |
2427 | |
2428 | default: |
2429 | pp_c_additive_expression (pp, e); |
2430 | } |
2431 | } |
2432 | |
2433 | /* relational-expression: |
2434 | shift-expression |
2435 | relational-expression < shift-expression |
2436 | relational-expression > shift-expression |
2437 | relational-expression <= shift-expression |
2438 | relational-expression >= shift-expression */ |
2439 | |
2440 | static void |
2441 | pp_c_relational_expression (c_pretty_printer *pp, tree e) |
2442 | { |
2443 | enum tree_code code = TREE_CODE (e); |
2444 | switch (code) |
2445 | { |
2446 | case LT_EXPR: |
2447 | case GT_EXPR: |
2448 | case LE_EXPR: |
2449 | case GE_EXPR: |
2450 | pp_c_relational_expression (pp, TREE_OPERAND (e, 0)); |
2451 | pp_c_whitespace (pp); |
2452 | if (code == LT_EXPR) |
2453 | pp_less (pp); |
2454 | else if (code == GT_EXPR) |
2455 | pp_greater (pp); |
2456 | else if (code == LE_EXPR) |
2457 | pp_less_equal (pp); |
2458 | else if (code == GE_EXPR) |
2459 | pp_greater_equal (pp); |
2460 | pp_c_whitespace (pp); |
2461 | pp_c_shift_expression (pp, TREE_OPERAND (e, 1)); |
2462 | break; |
2463 | |
2464 | default: |
2465 | pp_c_shift_expression (pp, e); |
2466 | break; |
2467 | } |
2468 | } |
2469 | |
2470 | /* equality-expression: |
2471 | relational-expression |
2472 | equality-expression == relational-expression |
2473 | equality-equality != relational-expression */ |
2474 | |
2475 | static void |
2476 | pp_c_equality_expression (c_pretty_printer *pp, tree e) |
2477 | { |
2478 | enum tree_code code = TREE_CODE (e); |
2479 | switch (code) |
2480 | { |
2481 | case EQ_EXPR: |
2482 | case NE_EXPR: |
2483 | pp_c_equality_expression (pp, TREE_OPERAND (e, 0)); |
2484 | pp_c_whitespace (pp); |
2485 | pp_string (pp, code == EQ_EXPR ? "==" : "!=" ); |
2486 | pp_c_whitespace (pp); |
2487 | pp_c_relational_expression (pp, TREE_OPERAND (e, 1)); |
2488 | break; |
2489 | |
2490 | default: |
2491 | pp_c_relational_expression (pp, e); |
2492 | break; |
2493 | } |
2494 | } |
2495 | |
2496 | /* AND-expression: |
2497 | equality-expression |
2498 | AND-expression & equality-equality */ |
2499 | |
2500 | static void |
2501 | pp_c_and_expression (c_pretty_printer *pp, tree e) |
2502 | { |
2503 | if (TREE_CODE (e) == BIT_AND_EXPR) |
2504 | { |
2505 | pp_c_and_expression (pp, TREE_OPERAND (e, 0)); |
2506 | pp_c_whitespace (pp); |
2507 | pp_ampersand (pp); |
2508 | pp_c_whitespace (pp); |
2509 | pp_c_equality_expression (pp, TREE_OPERAND (e, 1)); |
2510 | } |
2511 | else |
2512 | pp_c_equality_expression (pp, e); |
2513 | } |
2514 | |
2515 | /* exclusive-OR-expression: |
2516 | AND-expression |
2517 | exclusive-OR-expression ^ AND-expression */ |
2518 | |
2519 | static void |
2520 | pp_c_exclusive_or_expression (c_pretty_printer *pp, tree e) |
2521 | { |
2522 | if (TREE_CODE (e) == BIT_XOR_EXPR |
2523 | || TREE_CODE (e) == TRUTH_XOR_EXPR) |
2524 | { |
2525 | pp_c_exclusive_or_expression (pp, TREE_OPERAND (e, 0)); |
2526 | if (TREE_CODE (e) == BIT_XOR_EXPR) |
2527 | pp_c_maybe_whitespace (pp); |
2528 | else |
2529 | pp_c_whitespace (pp); |
2530 | pp_carret (pp); |
2531 | pp_c_whitespace (pp); |
2532 | pp_c_and_expression (pp, TREE_OPERAND (e, 1)); |
2533 | } |
2534 | else |
2535 | pp_c_and_expression (pp, e); |
2536 | } |
2537 | |
2538 | /* inclusive-OR-expression: |
2539 | exclusive-OR-expression |
2540 | inclusive-OR-expression | exclusive-OR-expression */ |
2541 | |
2542 | static void |
2543 | pp_c_inclusive_or_expression (c_pretty_printer *pp, tree e) |
2544 | { |
2545 | if (TREE_CODE (e) == BIT_IOR_EXPR) |
2546 | { |
2547 | pp_c_exclusive_or_expression (pp, TREE_OPERAND (e, 0)); |
2548 | pp_c_whitespace (pp); |
2549 | pp_bar (pp); |
2550 | pp_c_whitespace (pp); |
2551 | pp_c_exclusive_or_expression (pp, TREE_OPERAND (e, 1)); |
2552 | } |
2553 | else |
2554 | pp_c_exclusive_or_expression (pp, e); |
2555 | } |
2556 | |
2557 | /* logical-AND-expression: |
2558 | inclusive-OR-expression |
2559 | logical-AND-expression && inclusive-OR-expression */ |
2560 | |
2561 | static void |
2562 | pp_c_logical_and_expression (c_pretty_printer *pp, tree e) |
2563 | { |
2564 | if (TREE_CODE (e) == TRUTH_ANDIF_EXPR |
2565 | || TREE_CODE (e) == TRUTH_AND_EXPR) |
2566 | { |
2567 | pp_c_logical_and_expression (pp, TREE_OPERAND (e, 0)); |
2568 | pp_c_whitespace (pp); |
2569 | pp_ampersand_ampersand (pp); |
2570 | pp_c_whitespace (pp); |
2571 | pp_c_inclusive_or_expression (pp, TREE_OPERAND (e, 1)); |
2572 | } |
2573 | else |
2574 | pp_c_inclusive_or_expression (pp, e); |
2575 | } |
2576 | |
2577 | /* logical-OR-expression: |
2578 | logical-AND-expression |
2579 | logical-OR-expression || logical-AND-expression */ |
2580 | |
2581 | void |
2582 | pp_c_logical_or_expression (c_pretty_printer *pp, tree e) |
2583 | { |
2584 | if (TREE_CODE (e) == TRUTH_ORIF_EXPR |
2585 | || TREE_CODE (e) == TRUTH_OR_EXPR) |
2586 | { |
2587 | pp_c_logical_or_expression (pp, TREE_OPERAND (e, 0)); |
2588 | pp_c_whitespace (pp); |
2589 | pp_bar_bar (pp); |
2590 | pp_c_whitespace (pp); |
2591 | pp_c_logical_and_expression (pp, TREE_OPERAND (e, 1)); |
2592 | } |
2593 | else |
2594 | pp_c_logical_and_expression (pp, e); |
2595 | } |
2596 | |
2597 | /* conditional-expression: |
2598 | logical-OR-expression |
2599 | logical-OR-expression ? expression : conditional-expression */ |
2600 | |
2601 | void |
2602 | c_pretty_printer::conditional_expression (tree e) |
2603 | { |
2604 | if (TREE_CODE (e) == COND_EXPR) |
2605 | { |
2606 | pp_c_logical_or_expression (pp: this, TREE_OPERAND (e, 0)); |
2607 | pp_c_whitespace (pp: this); |
2608 | pp_question (this); |
2609 | pp_c_whitespace (pp: this); |
2610 | expression (TREE_OPERAND (e, 1)); |
2611 | pp_c_whitespace (pp: this); |
2612 | pp_colon (this); |
2613 | pp_c_whitespace (pp: this); |
2614 | conditional_expression (TREE_OPERAND (e, 2)); |
2615 | } |
2616 | else |
2617 | pp_c_logical_or_expression (pp: this, e); |
2618 | } |
2619 | |
2620 | |
2621 | /* assignment-expression: |
2622 | conditional-expression |
2623 | unary-expression assignment-operator assignment-expression |
2624 | |
2625 | assignment-expression: one of |
2626 | = *= /= %= += -= >>= <<= &= ^= |= */ |
2627 | |
2628 | void |
2629 | c_pretty_printer::assignment_expression (tree e) |
2630 | { |
2631 | if (TREE_CODE (e) == MODIFY_EXPR |
2632 | || TREE_CODE (e) == INIT_EXPR) |
2633 | { |
2634 | unary_expression (TREE_OPERAND (e, 0)); |
2635 | pp_c_whitespace (pp: this); |
2636 | pp_equal (this); |
2637 | pp_space (this); |
2638 | expression (TREE_OPERAND (e, 1)); |
2639 | } |
2640 | else |
2641 | conditional_expression (e); |
2642 | } |
2643 | |
2644 | /* expression: |
2645 | assignment-expression |
2646 | expression , assignment-expression |
2647 | |
2648 | Implementation note: instead of going through the usual recursion |
2649 | chain, I take the liberty of dispatching nodes to the appropriate |
2650 | functions. This makes some redundancy, but it worths it. That also |
2651 | prevents a possible infinite recursion between primary_expression () |
2652 | and expression (). */ |
2653 | |
2654 | void |
2655 | c_pretty_printer::expression (tree e) |
2656 | { |
2657 | switch (TREE_CODE (e)) |
2658 | { |
2659 | case VOID_CST: |
2660 | pp_c_void_constant (pp: this); |
2661 | break; |
2662 | |
2663 | case INTEGER_CST: |
2664 | pp_c_integer_constant (pp: this, i: e); |
2665 | break; |
2666 | |
2667 | case REAL_CST: |
2668 | pp_c_floating_constant (pp: this, r: e); |
2669 | break; |
2670 | |
2671 | case FIXED_CST: |
2672 | pp_c_fixed_constant (pp: this, r: e); |
2673 | break; |
2674 | |
2675 | case STRING_CST: |
2676 | pp_c_string_literal (pp: this, s: e); |
2677 | break; |
2678 | |
2679 | case IDENTIFIER_NODE: |
2680 | case FUNCTION_DECL: |
2681 | case VAR_DECL: |
2682 | case CONST_DECL: |
2683 | case PARM_DECL: |
2684 | case RESULT_DECL: |
2685 | case FIELD_DECL: |
2686 | case LABEL_DECL: |
2687 | case ERROR_MARK: |
2688 | primary_expression (e); |
2689 | break; |
2690 | |
2691 | case SSA_NAME: |
2692 | if (SSA_NAME_VAR (e) |
2693 | && !DECL_ARTIFICIAL (SSA_NAME_VAR (e))) |
2694 | expression (SSA_NAME_VAR (e)); |
2695 | else |
2696 | translate_string (gmsgid: "<unknown>" ); |
2697 | break; |
2698 | |
2699 | case POSTINCREMENT_EXPR: |
2700 | case POSTDECREMENT_EXPR: |
2701 | case ARRAY_REF: |
2702 | case CALL_EXPR: |
2703 | case COMPONENT_REF: |
2704 | case BIT_FIELD_REF: |
2705 | case COMPLEX_CST: |
2706 | case COMPLEX_EXPR: |
2707 | case VECTOR_CST: |
2708 | case ORDERED_EXPR: |
2709 | case UNORDERED_EXPR: |
2710 | case LTGT_EXPR: |
2711 | case UNEQ_EXPR: |
2712 | case UNLE_EXPR: |
2713 | case UNLT_EXPR: |
2714 | case UNGE_EXPR: |
2715 | case UNGT_EXPR: |
2716 | case MAX_EXPR: |
2717 | case MIN_EXPR: |
2718 | case ABS_EXPR: |
2719 | case CONSTRUCTOR: |
2720 | case COMPOUND_LITERAL_EXPR: |
2721 | case VA_ARG_EXPR: |
2722 | postfix_expression (e); |
2723 | break; |
2724 | |
2725 | case CONJ_EXPR: |
2726 | case ADDR_EXPR: |
2727 | case INDIRECT_REF: |
2728 | case MEM_REF: |
2729 | case TARGET_MEM_REF: |
2730 | case NEGATE_EXPR: |
2731 | case BIT_NOT_EXPR: |
2732 | case TRUTH_NOT_EXPR: |
2733 | case PREINCREMENT_EXPR: |
2734 | case PREDECREMENT_EXPR: |
2735 | case REALPART_EXPR: |
2736 | case IMAGPART_EXPR: |
2737 | unary_expression (e); |
2738 | break; |
2739 | |
2740 | case FLOAT_EXPR: |
2741 | case FIX_TRUNC_EXPR: |
2742 | CASE_CONVERT: |
2743 | case VIEW_CONVERT_EXPR: |
2744 | pp_c_cast_expression (pp: this, e); |
2745 | break; |
2746 | |
2747 | case MULT_EXPR: |
2748 | case TRUNC_MOD_EXPR: |
2749 | case TRUNC_DIV_EXPR: |
2750 | case EXACT_DIV_EXPR: |
2751 | case RDIV_EXPR: |
2752 | multiplicative_expression (e); |
2753 | break; |
2754 | |
2755 | case LSHIFT_EXPR: |
2756 | case RSHIFT_EXPR: |
2757 | case LROTATE_EXPR: |
2758 | case RROTATE_EXPR: |
2759 | pp_c_shift_expression (pp: this, e); |
2760 | break; |
2761 | |
2762 | case LT_EXPR: |
2763 | case GT_EXPR: |
2764 | case LE_EXPR: |
2765 | case GE_EXPR: |
2766 | pp_c_relational_expression (pp: this, e); |
2767 | break; |
2768 | |
2769 | case BIT_AND_EXPR: |
2770 | pp_c_and_expression (pp: this, e); |
2771 | break; |
2772 | |
2773 | case BIT_XOR_EXPR: |
2774 | case TRUTH_XOR_EXPR: |
2775 | pp_c_exclusive_or_expression (pp: this, e); |
2776 | break; |
2777 | |
2778 | case BIT_IOR_EXPR: |
2779 | pp_c_inclusive_or_expression (pp: this, e); |
2780 | break; |
2781 | |
2782 | case TRUTH_ANDIF_EXPR: |
2783 | case TRUTH_AND_EXPR: |
2784 | pp_c_logical_and_expression (pp: this, e); |
2785 | break; |
2786 | |
2787 | case TRUTH_ORIF_EXPR: |
2788 | case TRUTH_OR_EXPR: |
2789 | pp_c_logical_or_expression (pp: this, e); |
2790 | break; |
2791 | |
2792 | case EQ_EXPR: |
2793 | case NE_EXPR: |
2794 | pp_c_equality_expression (pp: this, e); |
2795 | break; |
2796 | |
2797 | case COND_EXPR: |
2798 | conditional_expression (e); |
2799 | break; |
2800 | |
2801 | case POINTER_PLUS_EXPR: |
2802 | case PLUS_EXPR: |
2803 | case POINTER_DIFF_EXPR: |
2804 | case MINUS_EXPR: |
2805 | pp_c_additive_expression (pp: this, e); |
2806 | break; |
2807 | |
2808 | case MODIFY_EXPR: |
2809 | case INIT_EXPR: |
2810 | assignment_expression (e); |
2811 | break; |
2812 | |
2813 | case COMPOUND_EXPR: |
2814 | pp_c_left_paren (pp: this); |
2815 | expression (TREE_OPERAND (e, 0)); |
2816 | pp_separate_with (this, ','); |
2817 | assignment_expression (TREE_OPERAND (e, 1)); |
2818 | pp_c_right_paren (pp: this); |
2819 | break; |
2820 | |
2821 | case NON_LVALUE_EXPR: |
2822 | case SAVE_EXPR: |
2823 | expression (TREE_OPERAND (e, 0)); |
2824 | break; |
2825 | |
2826 | case TARGET_EXPR: |
2827 | postfix_expression (TREE_OPERAND (e, 1)); |
2828 | break; |
2829 | |
2830 | case BIND_EXPR: |
2831 | case GOTO_EXPR: |
2832 | /* We don't yet have a way of dumping statements in a |
2833 | human-readable format. */ |
2834 | pp_string (this, "({...})" ); |
2835 | break; |
2836 | |
2837 | case C_MAYBE_CONST_EXPR: |
2838 | expression (C_MAYBE_CONST_EXPR_EXPR (e)); |
2839 | break; |
2840 | |
2841 | default: |
2842 | pp_unsupported_tree (this, e); |
2843 | break; |
2844 | } |
2845 | } |
2846 | |
2847 | |
2848 | |
2849 | /* Statements. */ |
2850 | |
2851 | void |
2852 | c_pretty_printer::statement (tree t) |
2853 | { |
2854 | if (t == NULL) |
2855 | return; |
2856 | |
2857 | switch (TREE_CODE (t)) |
2858 | { |
2859 | |
2860 | case SWITCH_STMT: |
2861 | pp_c_ws_string (pp: this, str: "switch" ); |
2862 | pp_space (this); |
2863 | pp_c_left_paren (pp: this); |
2864 | expression (SWITCH_STMT_COND (t)); |
2865 | pp_c_right_paren (pp: this); |
2866 | pp_indentation (this) += 3; |
2867 | pp_needs_newline (this) = true; |
2868 | statement (SWITCH_STMT_BODY (t)); |
2869 | pp_newline_and_indent (this, -3); |
2870 | break; |
2871 | |
2872 | /* iteration-statement: |
2873 | while ( expression ) statement |
2874 | do statement while ( expression ) ; |
2875 | for ( expression(opt) ; expression(opt) ; expression(opt) ) statement |
2876 | for ( declaration expression(opt) ; expression(opt) ) statement */ |
2877 | case WHILE_STMT: |
2878 | pp_c_ws_string (pp: this, str: "while" ); |
2879 | pp_space (this); |
2880 | pp_c_left_paren (pp: this); |
2881 | expression (WHILE_COND (t)); |
2882 | pp_c_right_paren (pp: this); |
2883 | pp_newline_and_indent (this, 3); |
2884 | statement (WHILE_BODY (t)); |
2885 | pp_indentation (this) -= 3; |
2886 | pp_needs_newline (this) = true; |
2887 | break; |
2888 | |
2889 | case DO_STMT: |
2890 | pp_c_ws_string (pp: this, str: "do" ); |
2891 | pp_newline_and_indent (this, 3); |
2892 | statement (DO_BODY (t)); |
2893 | pp_newline_and_indent (this, -3); |
2894 | pp_c_ws_string (pp: this, str: "while" ); |
2895 | pp_space (this); |
2896 | pp_c_left_paren (pp: this); |
2897 | expression (DO_COND (t)); |
2898 | pp_c_right_paren (pp: this); |
2899 | pp_c_semicolon (pp: this); |
2900 | pp_needs_newline (this) = true; |
2901 | break; |
2902 | |
2903 | case FOR_STMT: |
2904 | pp_c_ws_string (pp: this, str: "for" ); |
2905 | pp_space (this); |
2906 | pp_c_left_paren (pp: this); |
2907 | if (FOR_INIT_STMT (t)) |
2908 | statement (FOR_INIT_STMT (t)); |
2909 | else |
2910 | pp_c_semicolon (pp: this); |
2911 | pp_needs_newline (this) = false; |
2912 | pp_c_whitespace (pp: this); |
2913 | if (FOR_COND (t)) |
2914 | expression (FOR_COND (t)); |
2915 | pp_c_semicolon (pp: this); |
2916 | pp_needs_newline (this) = false; |
2917 | pp_c_whitespace (pp: this); |
2918 | if (FOR_EXPR (t)) |
2919 | expression (FOR_EXPR (t)); |
2920 | pp_c_right_paren (pp: this); |
2921 | pp_newline_and_indent (this, 3); |
2922 | statement (FOR_BODY (t)); |
2923 | pp_indentation (this) -= 3; |
2924 | pp_needs_newline (this) = true; |
2925 | break; |
2926 | |
2927 | /* jump-statement: |
2928 | goto identifier; |
2929 | continue ; |
2930 | return expression(opt) ; */ |
2931 | case BREAK_STMT: |
2932 | case CONTINUE_STMT: |
2933 | pp_string (this, TREE_CODE (t) == BREAK_STMT ? "break" : "continue" ); |
2934 | pp_c_semicolon (pp: this); |
2935 | pp_needs_newline (this) = true; |
2936 | break; |
2937 | |
2938 | default: |
2939 | if (pp_needs_newline (this)) |
2940 | pp_newline_and_indent (this, 0); |
2941 | dump_generic_node (this, t, pp_indentation (this), TDF_NONE, true); |
2942 | } |
2943 | } |
2944 | |
2945 | |
2946 | /* Initialize the PRETTY-PRINTER for handling C codes. */ |
2947 | |
2948 | c_pretty_printer::c_pretty_printer () |
2949 | : pretty_printer (), |
2950 | offset_list (), |
2951 | flags () |
2952 | { |
2953 | type_specifier_seq = pp_c_specifier_qualifier_list; |
2954 | ptr_operator = pp_c_pointer; |
2955 | parameter_list = pp_c_parameter_type_list; |
2956 | } |
2957 | |
2958 | /* c_pretty_printer's implementation of pretty_printer::clone vfunc. */ |
2959 | |
2960 | pretty_printer * |
2961 | c_pretty_printer::clone () const |
2962 | { |
2963 | return new c_pretty_printer (*this); |
2964 | } |
2965 | |
2966 | /* Print the tree T in full, on file FILE. */ |
2967 | |
2968 | void |
2969 | print_c_tree (FILE *file, tree t) |
2970 | { |
2971 | c_pretty_printer pp; |
2972 | |
2973 | pp_needs_newline (&pp) = true; |
2974 | pp.buffer->stream = file; |
2975 | pp.statement (t); |
2976 | pp_newline_and_flush (&pp); |
2977 | } |
2978 | |
2979 | /* Print the tree T in full, on stderr. */ |
2980 | |
2981 | DEBUG_FUNCTION void |
2982 | debug_c_tree (tree t) |
2983 | { |
2984 | print_c_tree (stderr, t); |
2985 | fputc (c: '\n', stderr); |
2986 | } |
2987 | |
2988 | /* Output the DECL_NAME of T. If T has no DECL_NAME, output a string made |
2989 | up of T's memory address. */ |
2990 | |
2991 | void |
2992 | pp_c_tree_decl_identifier (c_pretty_printer *pp, tree t) |
2993 | { |
2994 | const char *name; |
2995 | |
2996 | gcc_assert (DECL_P (t)); |
2997 | |
2998 | if (DECL_NAME (t)) |
2999 | name = IDENTIFIER_POINTER (DECL_NAME (t)); |
3000 | else |
3001 | { |
3002 | static char xname[8]; |
3003 | sprintf (s: xname, format: "<U%4hx>" , ((unsigned short) ((uintptr_t) (t) |
3004 | & 0xffff))); |
3005 | name = xname; |
3006 | } |
3007 | |
3008 | pp_c_identifier (pp, id: name); |
3009 | } |
3010 | |
3011 | #if CHECKING_P |
3012 | |
3013 | namespace selftest { |
3014 | |
3015 | /* Selftests for pretty-printing trees. */ |
3016 | |
3017 | /* Verify that EXPR printed by c_pretty_printer is EXPECTED, using |
3018 | LOC as the effective location for any failures. */ |
3019 | |
3020 | static void |
3021 | assert_c_pretty_printer_output (const location &loc, const char *expected, |
3022 | tree expr) |
3023 | { |
3024 | c_pretty_printer pp; |
3025 | pp.expression (e: expr); |
3026 | ASSERT_STREQ_AT (loc, expected, pp_formatted_text (&pp)); |
3027 | } |
3028 | |
3029 | /* Helper function for calling assert_c_pretty_printer_output. |
3030 | This is to avoid having to write SELFTEST_LOCATION. */ |
3031 | |
3032 | #define ASSERT_C_PRETTY_PRINTER_OUTPUT(EXPECTED, EXPR) \ |
3033 | SELFTEST_BEGIN_STMT \ |
3034 | assert_c_pretty_printer_output ((SELFTEST_LOCATION), \ |
3035 | (EXPECTED), \ |
3036 | (EXPR)); \ |
3037 | SELFTEST_END_STMT |
3038 | |
3039 | /* Verify that location wrappers don't show up in pretty-printed output. */ |
3040 | |
3041 | static void |
3042 | test_location_wrappers () |
3043 | { |
3044 | /* VAR_DECL. */ |
3045 | tree id = get_identifier ("foo" ); |
3046 | tree decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, id, |
3047 | integer_type_node); |
3048 | tree wrapped_decl = maybe_wrap_with_location (decl, BUILTINS_LOCATION); |
3049 | ASSERT_NE (wrapped_decl, decl); |
3050 | ASSERT_C_PRETTY_PRINTER_OUTPUT ("foo" , decl); |
3051 | ASSERT_C_PRETTY_PRINTER_OUTPUT ("foo" , wrapped_decl); |
3052 | |
3053 | /* INTEGER_CST. */ |
3054 | tree int_cst = build_int_cst (integer_type_node, 42); |
3055 | tree wrapped_cst = maybe_wrap_with_location (int_cst, BUILTINS_LOCATION); |
3056 | ASSERT_NE (wrapped_cst, int_cst); |
3057 | ASSERT_C_PRETTY_PRINTER_OUTPUT ("42" , int_cst); |
3058 | ASSERT_C_PRETTY_PRINTER_OUTPUT ("42" , wrapped_cst); |
3059 | } |
3060 | |
3061 | /* Run all of the selftests within this file. */ |
3062 | |
3063 | void |
3064 | c_pretty_print_cc_tests () |
3065 | { |
3066 | test_location_wrappers (); |
3067 | } |
3068 | |
3069 | } // namespace selftest |
3070 | |
3071 | #endif /* CHECKING_P */ |
3072 | |