* c-ada-spec.c (dump_ada_node) <POINTER_TYPE>: Do not use generic
[official-gcc.git] / gcc / c-family / c-ada-spec.c
blob588dc5d228916ef6ddd905ec4941cd3551667791
1 /* Print GENERIC declaration (functions, variables, types) trees coming from
2 the C and C++ front-ends as well as macros in Ada syntax.
3 Copyright (C) 2010-2018 Free Software Foundation, Inc.
4 Adapted from tree-pretty-print.c by Arnaud Charlet <charlet@adacore.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "tree.h"
27 #include "c-ada-spec.h"
28 #include "fold-const.h"
29 #include "c-pragma.h"
30 #include "cpp-id-data.h"
31 #include "stringpool.h"
32 #include "attribs.h"
34 /* Local functions, macros and variables. */
35 static int dump_ada_node (pretty_printer *, tree, tree, int, bool, bool);
36 static int dump_ada_declaration (pretty_printer *, tree, tree, int);
37 static void dump_ada_structure (pretty_printer *, tree, tree, int, bool);
38 static char *to_ada_name (const char *, unsigned int, bool *);
40 #define INDENT(SPACE) \
41 do { int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
43 #define INDENT_INCR 3
45 /* Global hook used to perform C++ queries on nodes. */
46 static int (*cpp_check) (tree, cpp_operation) = NULL;
48 /* Global variables used in macro-related callbacks. */
49 static int max_ada_macros;
50 static int store_ada_macro_index;
51 static const char *macro_source_file;
53 /* Given a cpp MACRO, compute the max length BUFFER_LEN of the macro, as well
54 as max length PARAM_LEN of arguments for fun_like macros, and also set
55 SUPPORTED to 0 if the macro cannot be mapped to an Ada construct. */
57 static void
58 macro_length (const cpp_macro *macro, int *supported, int *buffer_len,
59 int *param_len)
61 int i;
62 unsigned j;
64 *supported = 1;
65 *buffer_len = 0;
66 *param_len = 0;
68 if (macro->fun_like)
70 (*param_len)++;
71 for (i = 0; i < macro->paramc; i++)
73 cpp_hashnode *param = macro->params[i];
75 *param_len += NODE_LEN (param);
77 if (i + 1 < macro->paramc)
79 *param_len += 2; /* ", " */
81 else if (macro->variadic)
83 *supported = 0;
84 return;
87 *param_len += 2; /* ")\0" */
90 for (j = 0; j < macro->count; j++)
92 cpp_token *token = &macro->exp.tokens[j];
94 if (token->flags & PREV_WHITE)
95 (*buffer_len)++;
97 if (token->flags & STRINGIFY_ARG || token->flags & PASTE_LEFT)
99 *supported = 0;
100 return;
103 if (token->type == CPP_MACRO_ARG)
104 *buffer_len +=
105 NODE_LEN (macro->params[token->val.macro_arg.arg_no - 1]);
106 else
107 /* Include enough extra space to handle e.g. special characters. */
108 *buffer_len += (cpp_token_len (token) + 1) * 8;
111 (*buffer_len)++;
114 /* Dump all digits/hex chars from NUMBER to BUFFER and return a pointer
115 to the character after the last character written. If FLOAT_P is true,
116 this is a floating-point number. */
118 static unsigned char *
119 dump_number (unsigned char *number, unsigned char *buffer, bool float_p)
121 while (*number != '\0'
122 && *number != (float_p ? 'F' : 'U')
123 && *number != (float_p ? 'f' : 'u')
124 && *number != 'l'
125 && *number != 'L')
126 *buffer++ = *number++;
128 return buffer;
131 /* Handle escape character C and convert to an Ada character into BUFFER.
132 Return a pointer to the character after the last character written, or
133 NULL if the escape character is not supported. */
135 static unsigned char *
136 handle_escape_character (unsigned char *buffer, char c)
138 switch (c)
140 case '"':
141 *buffer++ = '"';
142 *buffer++ = '"';
143 break;
145 case 'n':
146 strcpy ((char *) buffer, "\" & ASCII.LF & \"");
147 buffer += 16;
148 break;
150 case 'r':
151 strcpy ((char *) buffer, "\" & ASCII.CR & \"");
152 buffer += 16;
153 break;
155 case 't':
156 strcpy ((char *) buffer, "\" & ASCII.HT & \"");
157 buffer += 16;
158 break;
160 default:
161 return NULL;
164 return buffer;
167 /* Callback used to count the number of macros from cpp_forall_identifiers.
168 PFILE and V are not used. NODE is the current macro to consider. */
170 static int
171 count_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *node,
172 void *v ATTRIBUTE_UNUSED)
174 const cpp_macro *macro = node->value.macro;
176 if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)
177 && macro->count
178 && *NODE_NAME (node) != '_'
179 && LOCATION_FILE (macro->line) == macro_source_file)
180 max_ada_macros++;
182 return 1;
185 /* Callback used to store relevant macros from cpp_forall_identifiers.
186 PFILE is not used. NODE is the current macro to store if relevant.
187 MACROS is an array of cpp_hashnode* used to store NODE. */
189 static int
190 store_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED,
191 cpp_hashnode *node, void *macros)
193 const cpp_macro *macro = node->value.macro;
195 if (node->type == NT_MACRO
196 && !(node->flags & NODE_BUILTIN)
197 && macro->count
198 && *NODE_NAME (node) != '_'
199 && LOCATION_FILE (macro->line) == macro_source_file)
200 ((cpp_hashnode **) macros)[store_ada_macro_index++] = node;
202 return 1;
205 /* Callback used to compare (during qsort) macros. NODE1 and NODE2 are the
206 two macro nodes to compare. */
208 static int
209 compare_macro (const void *node1, const void *node2)
211 typedef const cpp_hashnode *const_hnode;
213 const_hnode n1 = *(const const_hnode *) node1;
214 const_hnode n2 = *(const const_hnode *) node2;
216 return n1->value.macro->line - n2->value.macro->line;
219 /* Dump in PP all relevant macros appearing in FILE. */
221 static void
222 dump_ada_macros (pretty_printer *pp, const char* file)
224 int num_macros = 0, prev_line = -1;
225 cpp_hashnode **macros;
227 /* Initialize file-scope variables. */
228 max_ada_macros = 0;
229 store_ada_macro_index = 0;
230 macro_source_file = file;
232 /* Count all potentially relevant macros, and then sort them by sloc. */
233 cpp_forall_identifiers (parse_in, count_ada_macro, NULL);
234 macros = XALLOCAVEC (cpp_hashnode *, max_ada_macros);
235 cpp_forall_identifiers (parse_in, store_ada_macro, macros);
236 qsort (macros, max_ada_macros, sizeof (cpp_hashnode *), compare_macro);
238 for (int j = 0; j < max_ada_macros; j++)
240 cpp_hashnode *node = macros[j];
241 const cpp_macro *macro = node->value.macro;
242 unsigned i;
243 int supported = 1, prev_is_one = 0, buffer_len, param_len;
244 int is_string = 0, is_char = 0;
245 char *ada_name;
246 unsigned char *s, *params, *buffer, *buf_param, *char_one = NULL, *tmp;
248 macro_length (macro, &supported, &buffer_len, &param_len);
249 s = buffer = XALLOCAVEC (unsigned char, buffer_len);
250 params = buf_param = XALLOCAVEC (unsigned char, param_len);
252 if (supported)
254 if (macro->fun_like)
256 *buf_param++ = '(';
257 for (i = 0; i < macro->paramc; i++)
259 cpp_hashnode *param = macro->params[i];
261 memcpy (buf_param, NODE_NAME (param), NODE_LEN (param));
262 buf_param += NODE_LEN (param);
264 if (i + 1 < macro->paramc)
266 *buf_param++ = ',';
267 *buf_param++ = ' ';
269 else if (macro->variadic)
271 supported = 0;
272 break;
275 *buf_param++ = ')';
276 *buf_param = '\0';
279 for (i = 0; supported && i < macro->count; i++)
281 cpp_token *token = &macro->exp.tokens[i];
282 int is_one = 0;
284 if (token->flags & PREV_WHITE)
285 *buffer++ = ' ';
287 if (token->flags & STRINGIFY_ARG || token->flags & PASTE_LEFT)
289 supported = 0;
290 break;
293 switch (token->type)
295 case CPP_MACRO_ARG:
297 cpp_hashnode *param =
298 macro->params[token->val.macro_arg.arg_no - 1];
299 memcpy (buffer, NODE_NAME (param), NODE_LEN (param));
300 buffer += NODE_LEN (param);
302 break;
304 case CPP_EQ_EQ: *buffer++ = '='; break;
305 case CPP_GREATER: *buffer++ = '>'; break;
306 case CPP_LESS: *buffer++ = '<'; break;
307 case CPP_PLUS: *buffer++ = '+'; break;
308 case CPP_MINUS: *buffer++ = '-'; break;
309 case CPP_MULT: *buffer++ = '*'; break;
310 case CPP_DIV: *buffer++ = '/'; break;
311 case CPP_COMMA: *buffer++ = ','; break;
312 case CPP_OPEN_SQUARE:
313 case CPP_OPEN_PAREN: *buffer++ = '('; break;
314 case CPP_CLOSE_SQUARE: /* fallthrough */
315 case CPP_CLOSE_PAREN: *buffer++ = ')'; break;
316 case CPP_DEREF: /* fallthrough */
317 case CPP_SCOPE: /* fallthrough */
318 case CPP_DOT: *buffer++ = '.'; break;
320 case CPP_EQ: *buffer++ = ':'; *buffer++ = '='; break;
321 case CPP_NOT_EQ: *buffer++ = '/'; *buffer++ = '='; break;
322 case CPP_GREATER_EQ: *buffer++ = '>'; *buffer++ = '='; break;
323 case CPP_LESS_EQ: *buffer++ = '<'; *buffer++ = '='; break;
325 case CPP_NOT:
326 *buffer++ = 'n'; *buffer++ = 'o'; *buffer++ = 't'; break;
327 case CPP_MOD:
328 *buffer++ = 'm'; *buffer++ = 'o'; *buffer++ = 'd'; break;
329 case CPP_AND:
330 *buffer++ = 'a'; *buffer++ = 'n'; *buffer++ = 'd'; break;
331 case CPP_OR:
332 *buffer++ = 'o'; *buffer++ = 'r'; break;
333 case CPP_XOR:
334 *buffer++ = 'x'; *buffer++ = 'o'; *buffer++ = 'r'; break;
335 case CPP_AND_AND:
336 strcpy ((char *) buffer, " and then ");
337 buffer += 10;
338 break;
339 case CPP_OR_OR:
340 strcpy ((char *) buffer, " or else ");
341 buffer += 9;
342 break;
344 case CPP_PADDING:
345 *buffer++ = ' ';
346 is_one = prev_is_one;
347 break;
349 case CPP_COMMENT:
350 break;
352 case CPP_WSTRING:
353 case CPP_STRING16:
354 case CPP_STRING32:
355 case CPP_UTF8STRING:
356 case CPP_WCHAR:
357 case CPP_CHAR16:
358 case CPP_CHAR32:
359 case CPP_UTF8CHAR:
360 case CPP_NAME:
361 if (!macro->fun_like)
362 supported = 0;
363 else
364 buffer
365 = cpp_spell_token (parse_in, token, buffer, false);
366 break;
368 case CPP_STRING:
369 if (is_string)
371 *buffer++ = '&';
372 *buffer++ = ' ';
374 else
375 is_string = 1;
377 const unsigned char *s = token->val.str.text;
379 for (; *s; s++)
380 if (*s == '\\')
382 s++;
383 buffer = handle_escape_character (buffer, *s);
384 if (buffer == NULL)
386 supported = 0;
387 break;
390 else
391 *buffer++ = *s;
393 break;
395 case CPP_CHAR:
396 is_char = 1;
398 unsigned chars_seen;
399 int ignored;
400 cppchar_t c;
402 c = cpp_interpret_charconst (parse_in, token,
403 &chars_seen, &ignored);
404 if (c >= 32 && c <= 126)
406 *buffer++ = '\'';
407 *buffer++ = (char) c;
408 *buffer++ = '\'';
410 else
412 chars_seen = sprintf
413 ((char *) buffer, "Character'Val (%d)", (int) c);
414 buffer += chars_seen;
417 break;
419 case CPP_NUMBER:
420 tmp = cpp_token_as_text (parse_in, token);
422 switch (*tmp)
424 case '0':
425 switch (tmp[1])
427 case '\0':
428 case 'l':
429 case 'L':
430 case 'u':
431 case 'U':
432 *buffer++ = '0';
433 break;
435 case 'x':
436 case 'X':
437 *buffer++ = '1';
438 *buffer++ = '6';
439 *buffer++ = '#';
440 buffer = dump_number (tmp + 2, buffer, false);
441 *buffer++ = '#';
442 break;
444 case 'b':
445 case 'B':
446 *buffer++ = '2';
447 *buffer++ = '#';
448 buffer = dump_number (tmp + 2, buffer, false);
449 *buffer++ = '#';
450 break;
452 default:
453 /* Dump floating-point constant unmodified. */
454 if (strchr ((const char *)tmp, '.'))
455 buffer = dump_number (tmp, buffer, true);
456 else
458 *buffer++ = '8';
459 *buffer++ = '#';
460 buffer
461 = dump_number (tmp + 1, buffer, false);
462 *buffer++ = '#';
464 break;
466 break;
468 case '1':
469 if (tmp[1] == '\0'
470 || tmp[1] == 'u'
471 || tmp[1] == 'U'
472 || tmp[1] == 'l'
473 || tmp[1] == 'L')
475 is_one = 1;
476 char_one = buffer;
477 *buffer++ = '1';
478 break;
480 /* fallthrough */
482 default:
483 buffer
484 = dump_number (tmp, buffer,
485 strchr ((const char *)tmp, '.'));
486 break;
488 break;
490 case CPP_LSHIFT:
491 if (prev_is_one)
493 /* Replace "1 << N" by "2 ** N" */
494 *char_one = '2';
495 *buffer++ = '*';
496 *buffer++ = '*';
497 break;
499 /* fallthrough */
501 case CPP_RSHIFT:
502 case CPP_COMPL:
503 case CPP_QUERY:
504 case CPP_EOF:
505 case CPP_PLUS_EQ:
506 case CPP_MINUS_EQ:
507 case CPP_MULT_EQ:
508 case CPP_DIV_EQ:
509 case CPP_MOD_EQ:
510 case CPP_AND_EQ:
511 case CPP_OR_EQ:
512 case CPP_XOR_EQ:
513 case CPP_RSHIFT_EQ:
514 case CPP_LSHIFT_EQ:
515 case CPP_PRAGMA:
516 case CPP_PRAGMA_EOL:
517 case CPP_HASH:
518 case CPP_PASTE:
519 case CPP_OPEN_BRACE:
520 case CPP_CLOSE_BRACE:
521 case CPP_SEMICOLON:
522 case CPP_ELLIPSIS:
523 case CPP_PLUS_PLUS:
524 case CPP_MINUS_MINUS:
525 case CPP_DEREF_STAR:
526 case CPP_DOT_STAR:
527 case CPP_ATSIGN:
528 case CPP_HEADER_NAME:
529 case CPP_AT_NAME:
530 case CPP_OTHER:
531 case CPP_OBJC_STRING:
532 default:
533 if (!macro->fun_like)
534 supported = 0;
535 else
536 buffer = cpp_spell_token (parse_in, token, buffer, false);
537 break;
540 prev_is_one = is_one;
543 if (supported)
544 *buffer = '\0';
547 if (macro->fun_like && supported)
549 char *start = (char *) s;
550 int is_function = 0;
552 pp_string (pp, " -- arg-macro: ");
554 if (*start == '(' && buffer[-1] == ')')
556 start++;
557 buffer[-1] = '\0';
558 is_function = 1;
559 pp_string (pp, "function ");
561 else
563 pp_string (pp, "procedure ");
566 pp_string (pp, (const char *) NODE_NAME (node));
567 pp_space (pp);
568 pp_string (pp, (char *) params);
569 pp_newline (pp);
570 pp_string (pp, " -- ");
572 if (is_function)
574 pp_string (pp, "return ");
575 pp_string (pp, start);
576 pp_semicolon (pp);
578 else
579 pp_string (pp, start);
581 pp_newline (pp);
583 else if (supported)
585 expanded_location sloc = expand_location (macro->line);
587 if (sloc.line != prev_line + 1 && prev_line > 0)
588 pp_newline (pp);
590 num_macros++;
591 prev_line = sloc.line;
593 pp_string (pp, " ");
594 ada_name = to_ada_name ((const char *) NODE_NAME (node), 0, NULL);
595 pp_string (pp, ada_name);
596 free (ada_name);
597 pp_string (pp, " : ");
599 if (is_string)
600 pp_string (pp, "aliased constant String");
601 else if (is_char)
602 pp_string (pp, "aliased constant Character");
603 else
604 pp_string (pp, "constant");
606 pp_string (pp, " := ");
607 pp_string (pp, (char *) s);
609 if (is_string)
610 pp_string (pp, " & ASCII.NUL");
612 pp_string (pp, "; -- ");
613 pp_string (pp, sloc.file);
614 pp_colon (pp);
615 pp_scalar (pp, "%d", sloc.line);
616 pp_newline (pp);
618 else
620 pp_string (pp, " -- unsupported macro: ");
621 pp_string (pp, (const char *) cpp_macro_definition (parse_in, node));
622 pp_newline (pp);
626 if (num_macros > 0)
627 pp_newline (pp);
630 /* Current source file being handled. */
631 static const char *current_source_file;
633 /* Return sloc of DECL, using sloc of last field if LAST is true. */
635 location_t
636 decl_sloc (const_tree decl, bool last)
638 tree field;
640 /* Compare the declaration of struct-like types based on the sloc of their
641 last field (if LAST is true), so that more nested types collate before
642 less nested ones. */
643 if (TREE_CODE (decl) == TYPE_DECL
644 && !DECL_ORIGINAL_TYPE (decl)
645 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
646 && (field = TYPE_FIELDS (TREE_TYPE (decl))))
648 if (last)
649 while (DECL_CHAIN (field))
650 field = DECL_CHAIN (field);
651 return DECL_SOURCE_LOCATION (field);
654 return DECL_SOURCE_LOCATION (decl);
657 /* Compare two locations LHS and RHS. */
659 static int
660 compare_location (location_t lhs, location_t rhs)
662 expanded_location xlhs = expand_location (lhs);
663 expanded_location xrhs = expand_location (rhs);
665 if (xlhs.file != xrhs.file)
666 return filename_cmp (xlhs.file, xrhs.file);
668 if (xlhs.line != xrhs.line)
669 return xlhs.line - xrhs.line;
671 if (xlhs.column != xrhs.column)
672 return xlhs.column - xrhs.column;
674 return 0;
677 /* Compare two declarations (LP and RP) by their source location. */
679 static int
680 compare_node (const void *lp, const void *rp)
682 const_tree lhs = *((const tree *) lp);
683 const_tree rhs = *((const tree *) rp);
685 return compare_location (decl_sloc (lhs, true), decl_sloc (rhs, true));
688 /* Compare two comments (LP and RP) by their source location. */
690 static int
691 compare_comment (const void *lp, const void *rp)
693 const cpp_comment *lhs = (const cpp_comment *) lp;
694 const cpp_comment *rhs = (const cpp_comment *) rp;
696 return compare_location (lhs->sloc, rhs->sloc);
699 static tree *to_dump = NULL;
700 static int to_dump_count = 0;
702 /* Collect a list of declarations from T relevant to SOURCE_FILE to be dumped
703 by a subsequent call to dump_ada_nodes. */
705 void
706 collect_ada_nodes (tree t, const char *source_file)
708 tree n;
709 int i = to_dump_count;
711 /* Count the likely relevant nodes: do not dump builtins (they are irrelevant
712 in the context of bindings) and namespaces (we do not handle them properly
713 yet). */
714 for (n = t; n; n = TREE_CHAIN (n))
715 if (!DECL_IS_BUILTIN (n)
716 && TREE_CODE (n) != NAMESPACE_DECL
717 && LOCATION_FILE (decl_sloc (n, false)) == source_file)
718 to_dump_count++;
720 /* Allocate sufficient storage for all nodes. */
721 to_dump = XRESIZEVEC (tree, to_dump, to_dump_count);
723 /* Store the relevant nodes. */
724 for (n = t; n; n = TREE_CHAIN (n))
725 if (!DECL_IS_BUILTIN (n)
726 && TREE_CODE (n) != NAMESPACE_DECL
727 && LOCATION_FILE (decl_sloc (n, false)) == source_file)
728 to_dump[i++] = n;
731 /* Call back for walk_tree to clear the TREE_VISITED flag of TP. */
733 static tree
734 unmark_visited_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
735 void *data ATTRIBUTE_UNUSED)
737 if (TREE_VISITED (*tp))
738 TREE_VISITED (*tp) = 0;
739 else
740 *walk_subtrees = 0;
742 return NULL_TREE;
745 /* Print a COMMENT to the output stream PP. */
747 static void
748 print_comment (pretty_printer *pp, const char *comment)
750 int len = strlen (comment);
751 char *str = XALLOCAVEC (char, len + 1);
752 char *tok;
753 bool extra_newline = false;
755 memcpy (str, comment, len + 1);
757 /* Trim C/C++ comment indicators. */
758 if (str[len - 2] == '*' && str[len - 1] == '/')
760 str[len - 2] = ' ';
761 str[len - 1] = '\0';
763 str += 2;
765 tok = strtok (str, "\n");
766 while (tok) {
767 pp_string (pp, " --");
768 pp_string (pp, tok);
769 pp_newline (pp);
770 tok = strtok (NULL, "\n");
772 /* Leave a blank line after multi-line comments. */
773 if (tok)
774 extra_newline = true;
777 if (extra_newline)
778 pp_newline (pp);
781 /* Dump nodes into PP relevant to SOURCE_FILE, as collected by previous calls
782 to collect_ada_nodes. */
784 static void
785 dump_ada_nodes (pretty_printer *pp, const char *source_file)
787 int i, j;
788 cpp_comment_table *comments;
790 /* Sort the table of declarations to dump by sloc. */
791 qsort (to_dump, to_dump_count, sizeof (tree), compare_node);
793 /* Fetch the table of comments. */
794 comments = cpp_get_comments (parse_in);
796 /* Sort the comments table by sloc. */
797 if (comments->count > 1)
798 qsort (comments->entries, comments->count, sizeof (cpp_comment),
799 compare_comment);
801 /* Interleave comments and declarations in line number order. */
802 i = j = 0;
805 /* Advance j until comment j is in this file. */
806 while (j != comments->count
807 && LOCATION_FILE (comments->entries[j].sloc) != source_file)
808 j++;
810 /* Advance j until comment j is not a duplicate. */
811 while (j < comments->count - 1
812 && !compare_comment (&comments->entries[j],
813 &comments->entries[j + 1]))
814 j++;
816 /* Write decls until decl i collates after comment j. */
817 while (i != to_dump_count)
819 if (j == comments->count
820 || LOCATION_LINE (decl_sloc (to_dump[i], false))
821 < LOCATION_LINE (comments->entries[j].sloc))
823 current_source_file = source_file;
825 if (dump_ada_declaration (pp, to_dump[i++], NULL_TREE,
826 INDENT_INCR))
828 pp_newline (pp);
829 pp_newline (pp);
832 else
833 break;
836 /* Write comment j, if there is one. */
837 if (j != comments->count)
838 print_comment (pp, comments->entries[j++].comment);
840 } while (i != to_dump_count || j != comments->count);
842 /* Clear the TREE_VISITED flag over each subtree we've dumped. */
843 for (i = 0; i < to_dump_count; i++)
844 walk_tree (&to_dump[i], unmark_visited_r, NULL, NULL);
846 /* Finalize the to_dump table. */
847 if (to_dump)
849 free (to_dump);
850 to_dump = NULL;
851 to_dump_count = 0;
855 /* Dump a newline and indent BUFFER by SPC chars. */
857 static void
858 newline_and_indent (pretty_printer *buffer, int spc)
860 pp_newline (buffer);
861 INDENT (spc);
864 struct with { char *s; const char *in_file; bool limited; };
865 static struct with *withs = NULL;
866 static int withs_max = 4096;
867 static int with_len = 0;
869 /* Record a "with" clause on package S (a limited with if LIMITED_ACCESS is
870 true), if not already done. */
872 static void
873 append_withs (const char *s, bool limited_access)
875 int i;
877 if (withs == NULL)
878 withs = XNEWVEC (struct with, withs_max);
880 if (with_len == withs_max)
882 withs_max *= 2;
883 withs = XRESIZEVEC (struct with, withs, withs_max);
886 for (i = 0; i < with_len; i++)
887 if (!strcmp (s, withs[i].s)
888 && current_source_file == withs[i].in_file)
890 withs[i].limited &= limited_access;
891 return;
894 withs[with_len].s = xstrdup (s);
895 withs[with_len].in_file = current_source_file;
896 withs[with_len].limited = limited_access;
897 with_len++;
900 /* Reset "with" clauses. */
902 static void
903 reset_ada_withs (void)
905 int i;
907 if (!withs)
908 return;
910 for (i = 0; i < with_len; i++)
911 free (withs[i].s);
912 free (withs);
913 withs = NULL;
914 withs_max = 4096;
915 with_len = 0;
918 /* Dump "with" clauses in F. */
920 static void
921 dump_ada_withs (FILE *f)
923 int i;
925 fprintf (f, "with Interfaces.C; use Interfaces.C;\n");
927 for (i = 0; i < with_len; i++)
928 fprintf
929 (f, "%swith %s;\n", withs[i].limited ? "limited " : "", withs[i].s);
932 /* Return suitable Ada package name from FILE. */
934 static char *
935 get_ada_package (const char *file)
937 const char *base;
938 char *res;
939 const char *s;
940 int i;
941 size_t plen;
943 s = strstr (file, "/include/");
944 if (s)
945 base = s + 9;
946 else
947 base = lbasename (file);
949 if (ada_specs_parent == NULL)
950 plen = 0;
951 else
952 plen = strlen (ada_specs_parent) + 1;
954 res = XNEWVEC (char, plen + strlen (base) + 1);
955 if (ada_specs_parent != NULL) {
956 strcpy (res, ada_specs_parent);
957 res[plen - 1] = '.';
960 for (i = plen; *base; base++, i++)
961 switch (*base)
963 case '+':
964 res[i] = 'p';
965 break;
967 case '.':
968 case '-':
969 case '_':
970 case '/':
971 case '\\':
972 res[i] = (i == 0 || res[i - 1] == '.' || res[i - 1] == '_') ? 'u' : '_';
973 break;
975 default:
976 res[i] = *base;
977 break;
979 res[i] = '\0';
981 return res;
984 static const char *ada_reserved[] = {
985 "abort", "abs", "abstract", "accept", "access", "aliased", "all", "and",
986 "array", "at", "begin", "body", "case", "constant", "declare", "delay",
987 "delta", "digits", "do", "else", "elsif", "end", "entry", "exception",
988 "exit", "for", "function", "generic", "goto", "if", "in", "interface", "is",
989 "limited", "loop", "mod", "new", "not", "null", "others", "out", "of", "or",
990 "overriding", "package", "pragma", "private", "procedure", "protected",
991 "raise", "range", "record", "rem", "renames", "requeue", "return", "reverse",
992 "select", "separate", "subtype", "synchronized", "tagged", "task",
993 "terminate", "then", "type", "until", "use", "when", "while", "with", "xor",
994 NULL};
996 /* ??? would be nice to specify this list via a config file, so that users
997 can create their own dictionary of conflicts. */
998 static const char *c_duplicates[] = {
999 /* system will cause troubles with System.Address. */
1000 "system",
1002 /* The following values have other definitions with same name/other
1003 casing. */
1004 "funmap",
1005 "rl_vi_fWord",
1006 "rl_vi_bWord",
1007 "rl_vi_eWord",
1008 "rl_readline_version",
1009 "_Vx_ushort",
1010 "USHORT",
1011 "XLookupKeysym",
1012 NULL};
1014 /* Return a declaration tree corresponding to TYPE. */
1016 static tree
1017 get_underlying_decl (tree type)
1019 if (!type)
1020 return NULL_TREE;
1022 /* type is a declaration. */
1023 if (DECL_P (type))
1024 return type;
1026 /* type is a typedef. */
1027 if (TYPE_P (type) && TYPE_NAME (type) && DECL_P (TYPE_NAME (type)))
1028 return TYPE_NAME (type);
1030 /* TYPE_STUB_DECL has been set for type. */
1031 if (TYPE_P (type) && TYPE_STUB_DECL (type))
1032 return TYPE_STUB_DECL (type);
1034 return NULL_TREE;
1037 /* Return whether TYPE has static fields. */
1039 static bool
1040 has_static_fields (const_tree type)
1042 if (!type || !RECORD_OR_UNION_TYPE_P (type))
1043 return false;
1045 for (tree fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
1046 if (TREE_CODE (fld) == VAR_DECL && DECL_NAME (fld))
1047 return true;
1049 return false;
1052 /* Return whether TYPE corresponds to an Ada tagged type (has a dispatch
1053 table). */
1055 static bool
1056 is_tagged_type (const_tree type)
1058 if (!type || !RECORD_OR_UNION_TYPE_P (type))
1059 return false;
1061 for (tree fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
1062 if (TREE_CODE (fld) == FUNCTION_DECL && DECL_VINDEX (fld))
1063 return true;
1065 return false;
1068 /* Return whether TYPE has non-trivial methods, i.e. methods that do something
1069 for the objects of TYPE. In C++, all classes have implicit special methods,
1070 e.g. constructors and destructors, but they can be trivial if the type is
1071 sufficiently simple. */
1073 static bool
1074 has_nontrivial_methods (tree type)
1076 if (!type || !RECORD_OR_UNION_TYPE_P (type))
1077 return false;
1079 /* Only C++ types can have methods. */
1080 if (!cpp_check)
1081 return false;
1083 /* A non-trivial type has non-trivial special methods. */
1084 if (!cpp_check (type, IS_TRIVIAL))
1085 return true;
1087 /* If there are user-defined methods, they are deemed non-trivial. */
1088 for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
1089 if (TREE_CODE (fld) == FUNCTION_DECL && !DECL_ARTIFICIAL (fld))
1090 return true;
1092 return false;
1095 #define INDEX_LENGTH 8
1097 /* Generate a legal Ada name from a C/C++ NAME and return a malloc'ed string.
1098 INDEX, if non-zero, is used to disambiguate overloaded names. SPACE_FOUND,
1099 if not NULL, is used to indicate whether a space was found in NAME. */
1101 static char *
1102 to_ada_name (const char *name, unsigned int index, bool *space_found)
1104 const char **names;
1105 const int len = strlen (name);
1106 int j, len2 = 0;
1107 bool found = false;
1108 char *s = XNEWVEC (char, len * 2 + 5 + (index ? INDEX_LENGTH : 0));
1109 char c;
1111 if (space_found)
1112 *space_found = false;
1114 /* Add "c_" prefix if name is an Ada reserved word. */
1115 for (names = ada_reserved; *names; names++)
1116 if (!strcasecmp (name, *names))
1118 s[len2++] = 'c';
1119 s[len2++] = '_';
1120 found = true;
1121 break;
1124 if (!found)
1125 /* Add "c_" prefix if name is a potential case sensitive duplicate. */
1126 for (names = c_duplicates; *names; names++)
1127 if (!strcmp (name, *names))
1129 s[len2++] = 'c';
1130 s[len2++] = '_';
1131 found = true;
1132 break;
1135 for (j = 0; name[j] == '_'; j++)
1136 s[len2++] = 'u';
1138 if (j > 0)
1139 s[len2++] = '_';
1140 else if (*name == '.' || *name == '$')
1142 s[0] = 'a';
1143 s[1] = 'n';
1144 s[2] = 'o';
1145 s[3] = 'n';
1146 len2 = 4;
1147 j++;
1150 /* Replace unsuitable characters for Ada identifiers. */
1151 for (; j < len; j++)
1152 switch (name[j])
1154 case ' ':
1155 if (space_found)
1156 *space_found = true;
1157 s[len2++] = '_';
1158 break;
1160 /* ??? missing some C++ operators. */
1161 case '=':
1162 s[len2++] = '_';
1164 if (name[j + 1] == '=')
1166 j++;
1167 s[len2++] = 'e';
1168 s[len2++] = 'q';
1170 else
1172 s[len2++] = 'a';
1173 s[len2++] = 's';
1175 break;
1177 case '!':
1178 s[len2++] = '_';
1179 if (name[j + 1] == '=')
1181 j++;
1182 s[len2++] = 'n';
1183 s[len2++] = 'e';
1185 break;
1187 case '~':
1188 s[len2++] = '_';
1189 s[len2++] = 't';
1190 s[len2++] = 'i';
1191 break;
1193 case '&':
1194 case '|':
1195 case '^':
1196 s[len2++] = '_';
1197 s[len2++] = name[j] == '&' ? 'a' : name[j] == '|' ? 'o' : 'x';
1199 if (name[j + 1] == '=')
1201 j++;
1202 s[len2++] = 'e';
1204 break;
1206 case '+':
1207 case '-':
1208 case '*':
1209 case '/':
1210 case '(':
1211 case '[':
1212 if (s[len2 - 1] != '_')
1213 s[len2++] = '_';
1215 switch (name[j + 1]) {
1216 case '\0':
1217 j++;
1218 switch (name[j - 1]) {
1219 case '+': s[len2++] = 'p'; break; /* + */
1220 case '-': s[len2++] = 'm'; break; /* - */
1221 case '*': s[len2++] = 't'; break; /* * */
1222 case '/': s[len2++] = 'd'; break; /* / */
1224 break;
1226 case '=':
1227 j++;
1228 switch (name[j - 1]) {
1229 case '+': s[len2++] = 'p'; break; /* += */
1230 case '-': s[len2++] = 'm'; break; /* -= */
1231 case '*': s[len2++] = 't'; break; /* *= */
1232 case '/': s[len2++] = 'd'; break; /* /= */
1234 s[len2++] = 'a';
1235 break;
1237 case '-': /* -- */
1238 j++;
1239 s[len2++] = 'm';
1240 s[len2++] = 'm';
1241 break;
1243 case '+': /* ++ */
1244 j++;
1245 s[len2++] = 'p';
1246 s[len2++] = 'p';
1247 break;
1249 case ')': /* () */
1250 j++;
1251 s[len2++] = 'o';
1252 s[len2++] = 'p';
1253 break;
1255 case ']': /* [] */
1256 j++;
1257 s[len2++] = 'o';
1258 s[len2++] = 'b';
1259 break;
1262 break;
1264 case '<':
1265 case '>':
1266 c = name[j] == '<' ? 'l' : 'g';
1267 s[len2++] = '_';
1269 switch (name[j + 1]) {
1270 case '\0':
1271 s[len2++] = c;
1272 s[len2++] = 't';
1273 break;
1274 case '=':
1275 j++;
1276 s[len2++] = c;
1277 s[len2++] = 'e';
1278 break;
1279 case '>':
1280 j++;
1281 s[len2++] = 's';
1282 s[len2++] = 'r';
1283 break;
1284 case '<':
1285 j++;
1286 s[len2++] = 's';
1287 s[len2++] = 'l';
1288 break;
1289 default:
1290 break;
1292 break;
1294 case '_':
1295 if (len2 && s[len2 - 1] == '_')
1296 s[len2++] = 'u';
1297 /* fall through */
1299 default:
1300 s[len2++] = name[j];
1303 if (s[len2 - 1] == '_')
1304 s[len2++] = 'u';
1306 if (index)
1307 snprintf (&s[len2], INDEX_LENGTH, "_u_%d", index + 1);
1308 else
1309 s[len2] = '\0';
1311 return s;
1314 /* Return true if DECL refers to a C++ class type for which a
1315 separate enclosing package has been or should be generated. */
1317 static bool
1318 separate_class_package (tree decl)
1320 tree type = TREE_TYPE (decl);
1321 return has_nontrivial_methods (type) || has_static_fields (type);
1324 static bool package_prefix = true;
1326 /* Dump in BUFFER the name of an identifier NODE of type TYPE, following Ada
1327 syntax. INDEX, if non-zero, is used to disambiguate overloaded names.
1328 LIMITED_ACCESS indicates whether NODE can be accessed via a limited
1329 'with' clause rather than a regular 'with' clause. */
1331 static void
1332 pp_ada_tree_identifier (pretty_printer *buffer, tree node, tree type,
1333 unsigned int index, bool limited_access)
1335 const char *name = IDENTIFIER_POINTER (node);
1336 bool space_found = false;
1337 char *s = to_ada_name (name, index, &space_found);
1338 tree decl = get_underlying_decl (type);
1340 /* If the entity comes from another file, generate a package prefix. */
1341 if (decl)
1343 expanded_location xloc = expand_location (decl_sloc (decl, false));
1345 if (xloc.file && xloc.line)
1347 if (xloc.file != current_source_file)
1349 switch (TREE_CODE (type))
1351 case ENUMERAL_TYPE:
1352 case INTEGER_TYPE:
1353 case REAL_TYPE:
1354 case FIXED_POINT_TYPE:
1355 case BOOLEAN_TYPE:
1356 case REFERENCE_TYPE:
1357 case POINTER_TYPE:
1358 case ARRAY_TYPE:
1359 case RECORD_TYPE:
1360 case UNION_TYPE:
1361 case TYPE_DECL:
1362 if (package_prefix)
1364 char *s1 = get_ada_package (xloc.file);
1365 append_withs (s1, limited_access);
1366 pp_string (buffer, s1);
1367 pp_dot (buffer);
1368 free (s1);
1370 break;
1371 default:
1372 break;
1375 /* Generate the additional package prefix for C++ classes. */
1376 if (separate_class_package (decl))
1378 pp_string (buffer, "Class_");
1379 pp_string (buffer, s);
1380 pp_dot (buffer);
1386 if (space_found)
1387 if (!strcmp (s, "short_int"))
1388 pp_string (buffer, "short");
1389 else if (!strcmp (s, "short_unsigned_int"))
1390 pp_string (buffer, "unsigned_short");
1391 else if (!strcmp (s, "unsigned_int"))
1392 pp_string (buffer, "unsigned");
1393 else if (!strcmp (s, "long_int"))
1394 pp_string (buffer, "long");
1395 else if (!strcmp (s, "long_unsigned_int"))
1396 pp_string (buffer, "unsigned_long");
1397 else if (!strcmp (s, "long_long_int"))
1398 pp_string (buffer, "Long_Long_Integer");
1399 else if (!strcmp (s, "long_long_unsigned_int"))
1401 if (package_prefix)
1403 append_withs ("Interfaces.C.Extensions", false);
1404 pp_string (buffer, "Extensions.unsigned_long_long");
1406 else
1407 pp_string (buffer, "unsigned_long_long");
1409 else
1410 pp_string(buffer, s);
1411 else
1412 if (!strcmp (s, "bool"))
1414 if (package_prefix)
1416 append_withs ("Interfaces.C.Extensions", false);
1417 pp_string (buffer, "Extensions.bool");
1419 else
1420 pp_string (buffer, "bool");
1422 else
1423 pp_string(buffer, s);
1425 free (s);
1428 /* Dump in BUFFER the assembly name of T. */
1430 static void
1431 pp_asm_name (pretty_printer *buffer, tree t)
1433 tree name = DECL_ASSEMBLER_NAME (t);
1434 char *ada_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (name) + 1), *s;
1435 const char *ident = IDENTIFIER_POINTER (name);
1437 for (s = ada_name; *ident; ident++)
1439 if (*ident == ' ')
1440 break;
1441 else if (*ident != '*')
1442 *s++ = *ident;
1445 *s = '\0';
1446 pp_string (buffer, ada_name);
1449 /* Hash table of overloaded names associating identifier nodes with DECL_UIDs.
1450 It is needed in Ada 2005 because we can have at most one import directive
1451 per subprogram name in a given scope, so we have to mangle the subprogram
1452 names on the Ada side to import overloaded subprograms from C++. */
1454 struct overloaded_name_hash {
1455 hashval_t hash;
1456 tree name;
1457 tree context;
1458 vec<unsigned int> homonyms;
1461 struct overloaded_name_hasher : delete_ptr_hash<overloaded_name_hash>
1463 static inline hashval_t hash (overloaded_name_hash *t)
1464 { return t->hash; }
1465 static inline bool equal (overloaded_name_hash *a, overloaded_name_hash *b)
1466 { return a->name == b->name && a->context == b->context; }
1469 static hash_table<overloaded_name_hasher> *overloaded_names;
1471 /* Compute the overloading index of function DECL in its context. */
1473 static unsigned int
1474 compute_overloading_index (tree decl)
1476 const hashval_t hashcode
1477 = iterative_hash_hashval_t (htab_hash_pointer (DECL_NAME (decl)),
1478 htab_hash_pointer (DECL_CONTEXT (decl)));
1479 struct overloaded_name_hash in, *h, **slot;
1480 unsigned int index, *iter;
1482 if (!overloaded_names)
1483 overloaded_names = new hash_table<overloaded_name_hasher> (512);
1485 /* Look up the list of homonyms in the table. */
1486 in.hash = hashcode;
1487 in.name = DECL_NAME (decl);
1488 in.context = DECL_CONTEXT (decl);
1489 slot = overloaded_names->find_slot_with_hash (&in, hashcode, INSERT);
1490 if (*slot)
1491 h = *slot;
1492 else
1494 h = new overloaded_name_hash;
1495 h->hash = hashcode;
1496 h->name = DECL_NAME (decl);
1497 h->context = DECL_CONTEXT (decl);
1498 h->homonyms.create (0);
1499 *slot = h;
1502 /* Look up the function in the list of homonyms. */
1503 FOR_EACH_VEC_ELT (h->homonyms, index, iter)
1504 if (*iter == DECL_UID (decl))
1505 break;
1507 /* If it is not present, push it onto the list. */
1508 if (!iter)
1509 h->homonyms.safe_push (DECL_UID (decl));
1511 return index;
1514 /* Dump in BUFFER the name of a DECL node if set, following Ada syntax.
1515 LIMITED_ACCESS indicates whether NODE can be accessed via a limited
1516 'with' clause rather than a regular 'with' clause. */
1518 static void
1519 dump_ada_decl_name (pretty_printer *buffer, tree decl, bool limited_access)
1521 if (DECL_NAME (decl))
1523 const unsigned int index
1524 = (TREE_CODE (decl) == FUNCTION_DECL && cpp_check)
1525 ? compute_overloading_index (decl) : 0;
1526 pp_ada_tree_identifier (buffer, DECL_NAME (decl), decl, index,
1527 limited_access);
1529 else
1531 tree type_name = TYPE_NAME (TREE_TYPE (decl));
1533 if (!type_name)
1535 pp_string (buffer, "anon");
1536 if (TREE_CODE (decl) == FIELD_DECL)
1537 pp_scalar (buffer, "%d", DECL_UID (decl));
1538 else
1539 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (decl)));
1541 else if (TREE_CODE (type_name) == IDENTIFIER_NODE)
1542 pp_ada_tree_identifier (buffer, type_name, decl, 0, limited_access);
1546 /* Dump in BUFFER a name based on both T1 and T2 followed by a suffix. */
1548 static void
1549 dump_ada_double_name (pretty_printer *buffer, tree t1, tree t2)
1551 if (DECL_NAME (t1))
1552 pp_ada_tree_identifier (buffer, DECL_NAME (t1), t1, 0, false);
1553 else
1555 pp_string (buffer, "anon");
1556 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t1)));
1559 pp_underscore (buffer);
1561 if (DECL_NAME (t2))
1562 pp_ada_tree_identifier (buffer, DECL_NAME (t2), t2, 0, false);
1563 else
1565 pp_string (buffer, "anon");
1566 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t2)));
1569 switch (TREE_CODE (TREE_TYPE (t2)))
1571 case ARRAY_TYPE:
1572 pp_string (buffer, "_array");
1573 break;
1574 case RECORD_TYPE:
1575 pp_string (buffer, "_struct");
1576 break;
1577 case UNION_TYPE:
1578 pp_string (buffer, "_union");
1579 break;
1580 default:
1581 pp_string (buffer, "_unknown");
1582 break;
1586 /* Dump in BUFFER pragma Import C/CPP on a given node T. */
1588 static void
1589 dump_ada_import (pretty_printer *buffer, tree t)
1591 const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t));
1592 const bool is_stdcall
1593 = TREE_CODE (t) == FUNCTION_DECL
1594 && lookup_attribute ("stdcall", TYPE_ATTRIBUTES (TREE_TYPE (t)));
1596 if (is_stdcall)
1597 pp_string (buffer, "pragma Import (Stdcall, ");
1598 else if (name[0] == '_' && name[1] == 'Z')
1599 pp_string (buffer, "pragma Import (CPP, ");
1600 else
1601 pp_string (buffer, "pragma Import (C, ");
1603 dump_ada_decl_name (buffer, t, false);
1604 pp_string (buffer, ", \"");
1606 if (is_stdcall)
1607 pp_string (buffer, IDENTIFIER_POINTER (DECL_NAME (t)));
1608 else
1609 pp_asm_name (buffer, t);
1611 pp_string (buffer, "\");");
1614 /* Check whether T and its type have different names, and append "the_"
1615 otherwise in BUFFER. */
1617 static void
1618 check_name (pretty_printer *buffer, tree t)
1620 const char *s;
1621 tree tmp = TREE_TYPE (t);
1623 while (TREE_CODE (tmp) == POINTER_TYPE && !TYPE_NAME (tmp))
1624 tmp = TREE_TYPE (tmp);
1626 if (TREE_CODE (tmp) != FUNCTION_TYPE)
1628 if (TREE_CODE (tmp) == IDENTIFIER_NODE)
1629 s = IDENTIFIER_POINTER (tmp);
1630 else if (!TYPE_NAME (tmp))
1631 s = "";
1632 else if (TREE_CODE (TYPE_NAME (tmp)) == IDENTIFIER_NODE)
1633 s = IDENTIFIER_POINTER (TYPE_NAME (tmp));
1634 else
1635 s = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (tmp)));
1637 if (!strcasecmp (IDENTIFIER_POINTER (DECL_NAME (t)), s))
1638 pp_string (buffer, "the_");
1642 /* Dump in BUFFER a function declaration FUNC with Ada syntax.
1643 IS_METHOD indicates whether FUNC is a C++ method.
1644 IS_CONSTRUCTOR whether FUNC is a C++ constructor.
1645 IS_DESTRUCTOR whether FUNC is a C++ destructor.
1646 SPC is the current indentation level. */
1648 static void
1649 dump_ada_function_declaration (pretty_printer *buffer, tree func,
1650 bool is_method, bool is_constructor,
1651 bool is_destructor, int spc)
1653 tree arg;
1654 const tree node = TREE_TYPE (func);
1655 char buf[17];
1656 int num = 0, num_args = 0, have_args = true, have_ellipsis = false;
1658 /* Compute number of arguments. */
1659 arg = TYPE_ARG_TYPES (node);
1661 if (arg)
1663 while (TREE_CHAIN (arg) && arg != error_mark_node)
1665 num_args++;
1666 arg = TREE_CHAIN (arg);
1669 if (TREE_CODE (TREE_VALUE (arg)) != VOID_TYPE)
1671 num_args++;
1672 have_ellipsis = true;
1676 if (is_constructor)
1677 num_args--;
1679 if (is_destructor)
1680 num_args = 1;
1682 if (num_args > 2)
1683 newline_and_indent (buffer, spc + 1);
1685 if (num_args > 0)
1687 pp_space (buffer);
1688 pp_left_paren (buffer);
1691 if (TREE_CODE (func) == FUNCTION_DECL)
1692 arg = DECL_ARGUMENTS (func);
1693 else
1694 arg = NULL_TREE;
1696 if (arg == NULL_TREE)
1698 have_args = false;
1699 arg = TYPE_ARG_TYPES (node);
1701 if (arg && TREE_CODE (TREE_VALUE (arg)) == VOID_TYPE)
1702 arg = NULL_TREE;
1705 if (is_constructor)
1706 arg = TREE_CHAIN (arg);
1708 /* Print the argument names (if available) & types. */
1710 for (num = 1; num <= num_args; num++)
1712 if (have_args)
1714 if (DECL_NAME (arg))
1716 check_name (buffer, arg);
1717 pp_ada_tree_identifier (buffer, DECL_NAME (arg), NULL_TREE, 0,
1718 false);
1719 pp_string (buffer, " : ");
1721 else
1723 sprintf (buf, "arg%d : ", num);
1724 pp_string (buffer, buf);
1727 dump_ada_node (buffer, TREE_TYPE (arg), node, spc, false, true);
1729 else
1731 sprintf (buf, "arg%d : ", num);
1732 pp_string (buffer, buf);
1733 dump_ada_node (buffer, TREE_VALUE (arg), node, spc, false, true);
1736 /* If the type is a pointer to a tagged type, we need to differentiate
1737 virtual methods from the rest (non-virtual methods, static member
1738 or regular functions) and import only them as primitive operations,
1739 because they make up the virtual table which is mirrored on the Ada
1740 side by the dispatch table. So we add 'Class to the type of every
1741 parameter that is not the first one of a method which either has a
1742 slot in the virtual table or is a constructor. */
1743 if (TREE_TYPE (arg)
1744 && POINTER_TYPE_P (TREE_TYPE (arg))
1745 && is_tagged_type (TREE_TYPE (TREE_TYPE (arg)))
1746 && !(num == 1 && is_method && (DECL_VINDEX (func) || is_constructor)))
1747 pp_string (buffer, "'Class");
1749 arg = TREE_CHAIN (arg);
1751 if (num < num_args)
1753 pp_semicolon (buffer);
1755 if (num_args > 2)
1756 newline_and_indent (buffer, spc + INDENT_INCR);
1757 else
1758 pp_space (buffer);
1762 if (have_ellipsis)
1764 pp_string (buffer, " -- , ...");
1765 newline_and_indent (buffer, spc + INDENT_INCR);
1768 if (num_args > 0)
1769 pp_right_paren (buffer);
1771 if (is_constructor || !VOID_TYPE_P (TREE_TYPE (node)))
1773 pp_string (buffer, " return ");
1774 tree type = is_constructor ? DECL_CONTEXT (func) : TREE_TYPE (node);
1775 dump_ada_node (buffer, type, type, spc, false, true);
1779 /* Dump in BUFFER all the domains associated with an array NODE,
1780 using Ada syntax. SPC is the current indentation level. */
1782 static void
1783 dump_ada_array_domains (pretty_printer *buffer, tree node, int spc)
1785 int first = 1;
1786 pp_left_paren (buffer);
1788 for (; TREE_CODE (node) == ARRAY_TYPE; node = TREE_TYPE (node))
1790 tree domain = TYPE_DOMAIN (node);
1792 if (domain)
1794 tree min = TYPE_MIN_VALUE (domain);
1795 tree max = TYPE_MAX_VALUE (domain);
1797 if (!first)
1798 pp_string (buffer, ", ");
1799 first = 0;
1801 if (min)
1802 dump_ada_node (buffer, min, NULL_TREE, spc, false, true);
1803 pp_string (buffer, " .. ");
1805 /* If the upper bound is zero, gcc may generate a NULL_TREE
1806 for TYPE_MAX_VALUE rather than an integer_cst. */
1807 if (max)
1808 dump_ada_node (buffer, max, NULL_TREE, spc, false, true);
1809 else
1810 pp_string (buffer, "0");
1812 else
1813 pp_string (buffer, "size_t");
1815 pp_right_paren (buffer);
1818 /* Dump in BUFFER file:line information related to NODE. */
1820 static void
1821 dump_sloc (pretty_printer *buffer, tree node)
1823 expanded_location xloc;
1825 xloc.file = NULL;
1827 if (DECL_P (node))
1828 xloc = expand_location (DECL_SOURCE_LOCATION (node));
1829 else if (EXPR_HAS_LOCATION (node))
1830 xloc = expand_location (EXPR_LOCATION (node));
1832 if (xloc.file)
1834 pp_string (buffer, xloc.file);
1835 pp_colon (buffer);
1836 pp_decimal_int (buffer, xloc.line);
1840 /* Return true if T designates a one dimension array of "char". */
1842 static bool
1843 is_char_array (tree t)
1845 tree tmp;
1846 int num_dim = 0;
1848 /* Retrieve array's type. */
1849 tmp = t;
1850 while (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
1852 num_dim++;
1853 tmp = TREE_TYPE (tmp);
1856 tmp = TREE_TYPE (tmp);
1857 return num_dim == 1
1858 && TREE_CODE (tmp) == INTEGER_TYPE
1859 && id_equal (DECL_NAME (TYPE_NAME (tmp)), "char");
1862 /* Dump in BUFFER an array type T in Ada syntax. Assume that the "type"
1863 keyword and name have already been printed. PARENT is the parent node of T.
1864 SPC is the indentation level. */
1866 static void
1867 dump_ada_array_type (pretty_printer *buffer, tree t, tree parent, int spc)
1869 const bool char_array = is_char_array (t);
1870 tree tmp;
1872 /* Special case char arrays. */
1873 if (char_array)
1875 pp_string (buffer, "Interfaces.C.char_array ");
1877 else
1878 pp_string (buffer, "array ");
1880 /* Print the dimensions. */
1881 dump_ada_array_domains (buffer, TREE_TYPE (t), spc);
1883 /* Retrieve the element type. */
1884 tmp = TREE_TYPE (t);
1885 while (TREE_CODE (tmp) == ARRAY_TYPE)
1886 tmp = TREE_TYPE (tmp);
1888 /* Print array's type. */
1889 if (!char_array)
1891 pp_string (buffer, " of ");
1893 if (TREE_CODE (tmp) != POINTER_TYPE)
1894 pp_string (buffer, "aliased ");
1896 if (TYPE_NAME (tmp) || !RECORD_OR_UNION_TYPE_P (tmp))
1897 dump_ada_node (buffer, tmp, TREE_TYPE (t), spc, false, true);
1898 else
1899 dump_ada_double_name (buffer, parent, get_underlying_decl (tmp));
1903 /* Dump in BUFFER type names associated with a template, each prepended with
1904 '_'. TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS. SPC is
1905 the indentation level. */
1907 static void
1908 dump_template_types (pretty_printer *buffer, tree types, int spc)
1910 for (int i = 0; i < TREE_VEC_LENGTH (types); i++)
1912 tree elem = TREE_VEC_ELT (types, i);
1913 pp_underscore (buffer);
1915 if (!dump_ada_node (buffer, elem, NULL_TREE, spc, false, true))
1917 pp_string (buffer, "unknown");
1918 pp_scalar (buffer, "%lu", (unsigned long) TREE_HASH (elem));
1923 /* Dump in BUFFER the contents of all class instantiations associated with
1924 a given template T. SPC is the indentation level. */
1926 static int
1927 dump_ada_template (pretty_printer *buffer, tree t, int spc)
1929 /* DECL_SIZE_UNIT is DECL_TEMPLATE_INSTANTIATIONS in this context. */
1930 tree inst = DECL_SIZE_UNIT (t);
1931 /* This emulates DECL_TEMPLATE_RESULT in this context. */
1932 struct tree_template_decl {
1933 struct tree_decl_common common;
1934 tree arguments;
1935 tree result;
1937 tree result = ((struct tree_template_decl *) t)->result;
1938 int num_inst = 0;
1940 /* Don't look at template declarations declaring something coming from
1941 another file. This can occur for template friend declarations. */
1942 if (LOCATION_FILE (decl_sloc (result, false))
1943 != LOCATION_FILE (decl_sloc (t, false)))
1944 return 0;
1946 for (; inst && inst != error_mark_node; inst = TREE_CHAIN (inst))
1948 tree types = TREE_PURPOSE (inst);
1949 tree instance = TREE_VALUE (inst);
1951 if (TREE_VEC_LENGTH (types) == 0)
1952 break;
1954 if (!RECORD_OR_UNION_TYPE_P (instance))
1955 break;
1957 /* We are interested in concrete template instantiations only: skip
1958 partially specialized nodes. */
1959 if (RECORD_OR_UNION_TYPE_P (instance)
1960 && cpp_check
1961 && cpp_check (instance, HAS_DEPENDENT_TEMPLATE_ARGS))
1962 continue;
1964 num_inst++;
1965 INDENT (spc);
1966 pp_string (buffer, "package ");
1967 package_prefix = false;
1968 dump_ada_node (buffer, instance, t, spc, false, true);
1969 dump_template_types (buffer, types, spc);
1970 pp_string (buffer, " is");
1971 spc += INDENT_INCR;
1972 newline_and_indent (buffer, spc);
1974 TREE_VISITED (get_underlying_decl (instance)) = 1;
1975 pp_string (buffer, "type ");
1976 dump_ada_node (buffer, instance, t, spc, false, true);
1977 package_prefix = true;
1979 if (is_tagged_type (instance))
1980 pp_string (buffer, " is tagged limited ");
1981 else
1982 pp_string (buffer, " is limited ");
1984 dump_ada_node (buffer, instance, t, spc, false, false);
1985 pp_newline (buffer);
1986 spc -= INDENT_INCR;
1987 newline_and_indent (buffer, spc);
1989 pp_string (buffer, "end;");
1990 newline_and_indent (buffer, spc);
1991 pp_string (buffer, "use ");
1992 package_prefix = false;
1993 dump_ada_node (buffer, instance, t, spc, false, true);
1994 dump_template_types (buffer, types, spc);
1995 package_prefix = true;
1996 pp_semicolon (buffer);
1997 pp_newline (buffer);
1998 pp_newline (buffer);
2001 return num_inst > 0;
2004 /* Return true if NODE is a simple enum types, that can be mapped to an
2005 Ada enum type directly. */
2007 static bool
2008 is_simple_enum (tree node)
2010 HOST_WIDE_INT count = 0;
2011 tree value;
2013 for (value = TYPE_VALUES (node); value; value = TREE_CHAIN (value))
2015 tree int_val = TREE_VALUE (value);
2017 if (TREE_CODE (int_val) != INTEGER_CST)
2018 int_val = DECL_INITIAL (int_val);
2020 if (!tree_fits_shwi_p (int_val))
2021 return false;
2022 else if (tree_to_shwi (int_val) != count)
2023 return false;
2025 count++;
2028 return true;
2031 static bool bitfield_used = false;
2033 /* Recursively dump in BUFFER Ada declarations corresponding to NODE of type
2034 TYPE. SPC is the indentation level. LIMITED_ACCESS indicates whether NODE
2035 can be referenced via a "limited with" clause. NAME_ONLY indicates whether
2036 we should only dump the name of NODE, instead of its full declaration. */
2038 static int
2039 dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
2040 bool limited_access, bool name_only)
2042 if (node == NULL_TREE)
2043 return 0;
2045 switch (TREE_CODE (node))
2047 case ERROR_MARK:
2048 pp_string (buffer, "<<< error >>>");
2049 return 0;
2051 case IDENTIFIER_NODE:
2052 pp_ada_tree_identifier (buffer, node, type, 0, limited_access);
2053 break;
2055 case TREE_LIST:
2056 pp_string (buffer, "--- unexpected node: TREE_LIST");
2057 return 0;
2059 case TREE_BINFO:
2060 dump_ada_node (buffer, BINFO_TYPE (node), type, spc, limited_access,
2061 name_only);
2062 return 0;
2064 case TREE_VEC:
2065 pp_string (buffer, "--- unexpected node: TREE_VEC");
2066 return 0;
2068 case VOID_TYPE:
2069 if (package_prefix)
2071 append_withs ("System", false);
2072 pp_string (buffer, "System.Address");
2074 else
2075 pp_string (buffer, "address");
2076 break;
2078 case VECTOR_TYPE:
2079 pp_string (buffer, "<vector>");
2080 break;
2082 case COMPLEX_TYPE:
2083 pp_string (buffer, "<complex>");
2084 break;
2086 case ENUMERAL_TYPE:
2087 if (name_only)
2088 dump_ada_node (buffer, TYPE_NAME (node), node, spc, false, true);
2089 else
2091 tree value = TYPE_VALUES (node);
2093 if (is_simple_enum (node))
2095 bool first = true;
2096 spc += INDENT_INCR;
2097 newline_and_indent (buffer, spc - 1);
2098 pp_left_paren (buffer);
2099 for (; value; value = TREE_CHAIN (value))
2101 if (first)
2102 first = false;
2103 else
2105 pp_comma (buffer);
2106 newline_and_indent (buffer, spc);
2109 pp_ada_tree_identifier (buffer, TREE_PURPOSE (value), node,
2110 0, false);
2112 pp_string (buffer, ");");
2113 spc -= INDENT_INCR;
2114 newline_and_indent (buffer, spc);
2115 pp_string (buffer, "pragma Convention (C, ");
2116 dump_ada_node (buffer,
2117 DECL_NAME (type) ? type : TYPE_NAME (node),
2118 type, spc, false, true);
2119 pp_right_paren (buffer);
2121 else
2123 if (TYPE_UNSIGNED (node))
2124 pp_string (buffer, "unsigned");
2125 else
2126 pp_string (buffer, "int");
2127 for (; value; value = TREE_CHAIN (value))
2129 pp_semicolon (buffer);
2130 newline_and_indent (buffer, spc);
2132 pp_ada_tree_identifier (buffer, TREE_PURPOSE (value), node,
2133 0, false);
2134 pp_string (buffer, " : constant ");
2136 dump_ada_node (buffer,
2137 DECL_NAME (type) ? type : TYPE_NAME (node),
2138 type, spc, false, true);
2140 pp_string (buffer, " := ");
2141 dump_ada_node (buffer,
2142 TREE_CODE (TREE_VALUE (value)) == INTEGER_CST
2143 ? TREE_VALUE (value)
2144 : DECL_INITIAL (TREE_VALUE (value)),
2145 node, spc, false, true);
2149 break;
2151 case INTEGER_TYPE:
2152 case REAL_TYPE:
2153 case FIXED_POINT_TYPE:
2154 case BOOLEAN_TYPE:
2156 enum tree_code_class tclass;
2158 tclass = TREE_CODE_CLASS (TREE_CODE (node));
2160 if (tclass == tcc_declaration)
2162 if (DECL_NAME (node))
2163 pp_ada_tree_identifier (buffer, DECL_NAME (node), NULL_TREE, 0,
2164 limited_access);
2165 else
2166 pp_string (buffer, "<unnamed type decl>");
2168 else if (tclass == tcc_type)
2170 if (TYPE_NAME (node))
2172 if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
2173 pp_ada_tree_identifier (buffer, TYPE_NAME (node), node, 0,
2174 limited_access);
2175 else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
2176 && DECL_NAME (TYPE_NAME (node)))
2177 dump_ada_decl_name (buffer, TYPE_NAME (node), limited_access);
2178 else
2179 pp_string (buffer, "<unnamed type>");
2181 else if (TREE_CODE (node) == INTEGER_TYPE)
2183 append_withs ("Interfaces.C.Extensions", false);
2184 bitfield_used = true;
2186 if (TYPE_PRECISION (node) == 1)
2187 pp_string (buffer, "Extensions.Unsigned_1");
2188 else
2190 pp_string (buffer, (TYPE_UNSIGNED (node)
2191 ? "Extensions.Unsigned_"
2192 : "Extensions.Signed_"));
2193 pp_decimal_int (buffer, TYPE_PRECISION (node));
2196 else
2197 pp_string (buffer, "<unnamed type>");
2199 break;
2202 case POINTER_TYPE:
2203 case REFERENCE_TYPE:
2204 if (name_only && TYPE_NAME (node))
2205 dump_ada_node (buffer, TYPE_NAME (node), node, spc, limited_access,
2206 true);
2208 else if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
2210 if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (node))))
2211 pp_string (buffer, "access procedure");
2212 else
2213 pp_string (buffer, "access function");
2215 dump_ada_function_declaration
2216 (buffer, node, false, false, false, spc + INDENT_INCR);
2218 /* If we are dumping the full type, it means we are part of a
2219 type definition and need also a Convention C pragma. */
2220 if (!name_only)
2222 pp_semicolon (buffer);
2223 newline_and_indent (buffer, spc);
2224 pp_string (buffer, "pragma Convention (C, ");
2225 dump_ada_node (buffer, type, NULL_TREE, spc, false, true);
2226 pp_right_paren (buffer);
2229 else
2231 bool is_access = false;
2232 unsigned int quals = TYPE_QUALS (TREE_TYPE (node));
2234 if (VOID_TYPE_P (TREE_TYPE (node)))
2236 if (!name_only)
2237 pp_string (buffer, "new ");
2238 if (package_prefix)
2240 append_withs ("System", false);
2241 pp_string (buffer, "System.Address");
2243 else
2244 pp_string (buffer, "address");
2246 else
2248 if (TREE_CODE (node) == POINTER_TYPE
2249 && TREE_CODE (TREE_TYPE (node)) == INTEGER_TYPE
2250 && !strcmp
2251 (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME
2252 (TREE_TYPE (node)))), "char"))
2254 if (!name_only)
2255 pp_string (buffer, "new ");
2257 if (package_prefix)
2259 pp_string (buffer, "Interfaces.C.Strings.chars_ptr");
2260 append_withs ("Interfaces.C.Strings", false);
2262 else
2263 pp_string (buffer, "chars_ptr");
2265 else
2267 tree type_name = TYPE_NAME (TREE_TYPE (node));
2269 /* For now, handle access-to-access as System.Address. */
2270 if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE)
2272 if (package_prefix)
2274 append_withs ("System", false);
2275 if (!name_only)
2276 pp_string (buffer, "new ");
2277 pp_string (buffer, "System.Address");
2279 else
2280 pp_string (buffer, "address");
2281 return spc;
2284 if (!package_prefix)
2285 pp_string (buffer, "access");
2286 else if (AGGREGATE_TYPE_P (TREE_TYPE (node)))
2288 if (!type || TREE_CODE (type) != FUNCTION_DECL)
2290 pp_string (buffer, "access ");
2291 is_access = true;
2293 if (quals & TYPE_QUAL_CONST)
2294 pp_string (buffer, "constant ");
2295 else if (!name_only)
2296 pp_string (buffer, "all ");
2298 else if (quals & TYPE_QUAL_CONST)
2299 pp_string (buffer, "in ");
2300 else
2302 is_access = true;
2303 pp_string (buffer, "access ");
2304 /* ??? should be configurable: access or in out. */
2307 else
2309 is_access = true;
2310 pp_string (buffer, "access ");
2312 if (!name_only)
2313 pp_string (buffer, "all ");
2316 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node)) && type_name)
2317 dump_ada_node (buffer, type_name, TREE_TYPE (node), spc,
2318 is_access, true);
2319 else
2320 dump_ada_node (buffer, TREE_TYPE (node), TREE_TYPE (node),
2321 spc, false, true);
2325 break;
2327 case ARRAY_TYPE:
2328 if (name_only)
2329 dump_ada_node (buffer, TYPE_NAME (node), node, spc, limited_access,
2330 true);
2331 else
2332 dump_ada_array_type (buffer, node, type, spc);
2333 break;
2335 case RECORD_TYPE:
2336 case UNION_TYPE:
2337 if (name_only)
2339 if (TYPE_NAME (node))
2340 dump_ada_node (buffer, TYPE_NAME (node), node, spc, limited_access,
2341 true);
2342 else
2344 pp_string (buffer, "anon_");
2345 pp_scalar (buffer, "%d", TYPE_UID (node));
2348 else
2349 dump_ada_structure (buffer, node, type, spc, true);
2350 break;
2352 case INTEGER_CST:
2353 /* We treat the upper half of the sizetype range as negative. This
2354 is consistent with the internal treatment and makes it possible
2355 to generate the (0 .. -1) range for flexible array members. */
2356 if (TREE_TYPE (node) == sizetype)
2357 node = fold_convert (ssizetype, node);
2358 if (tree_fits_shwi_p (node))
2359 pp_wide_integer (buffer, tree_to_shwi (node));
2360 else if (tree_fits_uhwi_p (node))
2361 pp_unsigned_wide_integer (buffer, tree_to_uhwi (node));
2362 else
2364 wide_int val = wi::to_wide (node);
2365 int i;
2366 if (wi::neg_p (val))
2368 pp_minus (buffer);
2369 val = -val;
2371 sprintf (pp_buffer (buffer)->digit_buffer,
2372 "16#%" HOST_WIDE_INT_PRINT "x",
2373 val.elt (val.get_len () - 1));
2374 for (i = val.get_len () - 2; i >= 0; i--)
2375 sprintf (pp_buffer (buffer)->digit_buffer,
2376 HOST_WIDE_INT_PRINT_PADDED_HEX, val.elt (i));
2377 pp_string (buffer, pp_buffer (buffer)->digit_buffer);
2379 break;
2381 case REAL_CST:
2382 case FIXED_CST:
2383 case COMPLEX_CST:
2384 case STRING_CST:
2385 case VECTOR_CST:
2386 return 0;
2388 case TYPE_DECL:
2389 if (DECL_IS_BUILTIN (node))
2391 /* Don't print the declaration of built-in types. */
2392 if (name_only)
2394 /* If we're in the middle of a declaration, defaults to
2395 System.Address. */
2396 if (package_prefix)
2398 append_withs ("System", false);
2399 pp_string (buffer, "System.Address");
2401 else
2402 pp_string (buffer, "address");
2404 break;
2407 if (name_only)
2408 dump_ada_decl_name (buffer, node, limited_access);
2409 else
2411 if (is_tagged_type (TREE_TYPE (node)))
2413 int first = 1;
2415 /* Look for ancestors. */
2416 for (tree fld = TYPE_FIELDS (TREE_TYPE (node));
2417 fld;
2418 fld = TREE_CHAIN (fld))
2420 if (!DECL_NAME (fld) && is_tagged_type (TREE_TYPE (fld)))
2422 if (first)
2424 pp_string (buffer, "limited new ");
2425 first = 0;
2427 else
2428 pp_string (buffer, " and ");
2430 dump_ada_decl_name (buffer, TYPE_NAME (TREE_TYPE (fld)),
2431 false);
2435 pp_string (buffer, first ? "tagged limited " : " with ");
2437 else if (has_nontrivial_methods (TREE_TYPE (node)))
2438 pp_string (buffer, "limited ");
2440 dump_ada_node (buffer, TREE_TYPE (node), type, spc, false, false);
2442 break;
2444 case FUNCTION_DECL:
2445 case CONST_DECL:
2446 case VAR_DECL:
2447 case PARM_DECL:
2448 case FIELD_DECL:
2449 case NAMESPACE_DECL:
2450 dump_ada_decl_name (buffer, node, false);
2451 break;
2453 default:
2454 /* Ignore other nodes (e.g. expressions). */
2455 return 0;
2458 return 1;
2461 /* Dump in BUFFER NODE's methods. SPC is the indentation level. Return 1 if
2462 methods were printed, 0 otherwise. */
2464 static int
2465 dump_ada_methods (pretty_printer *buffer, tree node, int spc)
2467 if (!has_nontrivial_methods (node))
2468 return 0;
2470 pp_semicolon (buffer);
2472 int res = 1;
2473 for (tree fld = TYPE_FIELDS (node); fld; fld = DECL_CHAIN (fld))
2474 if (TREE_CODE (fld) == FUNCTION_DECL)
2476 if (res)
2478 pp_newline (buffer);
2479 pp_newline (buffer);
2482 res = dump_ada_declaration (buffer, fld, node, spc);
2485 return 1;
2488 /* Dump in BUFFER a forward declaration for TYPE present inside T.
2489 SPC is the indentation level. */
2491 static void
2492 dump_forward_type (pretty_printer *buffer, tree type, tree t, int spc)
2494 tree decl = get_underlying_decl (type);
2496 /* Anonymous pointer and function types. */
2497 if (!decl)
2499 if (TREE_CODE (type) == POINTER_TYPE)
2500 dump_forward_type (buffer, TREE_TYPE (type), t, spc);
2501 else if (TREE_CODE (type) == FUNCTION_TYPE)
2503 function_args_iterator args_iter;
2504 tree arg;
2505 dump_forward_type (buffer, TREE_TYPE (type), t, spc);
2506 FOREACH_FUNCTION_ARGS (type, arg, args_iter)
2507 dump_forward_type (buffer, arg, t, spc);
2509 return;
2512 if (DECL_IS_BUILTIN (decl) || TREE_VISITED (decl))
2513 return;
2515 /* Forward declarations are only needed within a given file. */
2516 if (DECL_SOURCE_FILE (decl) != DECL_SOURCE_FILE (t))
2517 return;
2519 /* Generate an incomplete type declaration. */
2520 pp_string (buffer, "type ");
2521 dump_ada_node (buffer, decl, NULL_TREE, spc, false, true);
2522 pp_semicolon (buffer);
2523 newline_and_indent (buffer, spc);
2525 /* Only one incomplete declaration is legal for a given type. */
2526 TREE_VISITED (decl) = 1;
2529 static void dump_nested_type (pretty_printer *, tree, tree, tree, int);
2531 /* Dump in BUFFER anonymous types nested inside T's definition.
2532 PARENT is the parent node of T. SPC is the indentation level.
2534 In C anonymous nested tagged types have no name whereas in C++ they have
2535 one. In C their TYPE_DECL is at top level whereas in C++ it is nested.
2536 In both languages untagged types (pointers and arrays) have no name.
2537 In C++ the nested TYPE_DECLs can come after their associated FIELD_DECL.
2539 Therefore, in order to have a common processing for both languages, we
2540 disregard anonymous TYPE_DECLs at top level and here we make a first
2541 pass on the nested TYPE_DECLs and a second pass on the unnamed types. */
2543 static void
2544 dump_nested_types (pretty_printer *buffer, tree t, tree parent, int spc)
2546 tree type, field;
2548 /* Find possible anonymous pointers/arrays/structs/unions recursively. */
2549 type = TREE_TYPE (t);
2550 if (type == NULL_TREE)
2551 return;
2553 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
2554 if (TREE_CODE (field) == TYPE_DECL
2555 && DECL_NAME (field) != DECL_NAME (t)
2556 && !DECL_ORIGINAL_TYPE (field)
2557 && TYPE_NAME (TREE_TYPE (field)) != TYPE_NAME (type))
2558 dump_nested_type (buffer, field, t, parent, spc);
2560 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
2561 if (TREE_CODE (field) == FIELD_DECL && !TYPE_NAME (TREE_TYPE (field)))
2562 dump_nested_type (buffer, field, t, parent, spc);
2565 /* Dump in BUFFER the anonymous type of FIELD inside T.
2566 PARENT is the parent node of T. SPC is the indentation level. */
2568 static void
2569 dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent,
2570 int spc)
2572 tree field_type = TREE_TYPE (field);
2573 tree decl, tmp;
2575 switch (TREE_CODE (field_type))
2577 case POINTER_TYPE:
2578 tmp = TREE_TYPE (field_type);
2579 dump_forward_type (buffer, tmp, t, spc);
2580 break;
2582 case ARRAY_TYPE:
2583 tmp = TREE_TYPE (field_type);
2584 while (TREE_CODE (tmp) == ARRAY_TYPE)
2585 tmp = TREE_TYPE (tmp);
2586 decl = get_underlying_decl (tmp);
2587 if (decl && !DECL_NAME (decl) && !TREE_VISITED (decl))
2589 /* Generate full declaration. */
2590 dump_nested_type (buffer, decl, t, parent, spc);
2591 TREE_VISITED (decl) = 1;
2593 else if (!decl && TREE_CODE (tmp) == POINTER_TYPE)
2594 dump_forward_type (buffer, TREE_TYPE (tmp), t, spc);
2596 /* Special case char arrays. */
2597 if (is_char_array (field))
2598 pp_string (buffer, "sub");
2600 pp_string (buffer, "type ");
2601 dump_ada_double_name (buffer, parent, field);
2602 pp_string (buffer, " is ");
2603 dump_ada_array_type (buffer, field, parent, spc);
2604 pp_semicolon (buffer);
2605 newline_and_indent (buffer, spc);
2606 break;
2608 case RECORD_TYPE:
2609 case UNION_TYPE:
2610 dump_nested_types (buffer, field, t, spc);
2612 pp_string (buffer, "type ");
2614 if (TYPE_NAME (field_type))
2616 dump_ada_node (buffer, field_type, NULL_TREE, spc, false, true);
2617 if (TREE_CODE (field_type) == UNION_TYPE)
2618 pp_string (buffer, " (discr : unsigned := 0)");
2619 pp_string (buffer, " is ");
2620 dump_ada_structure (buffer, field_type, t, spc, false);
2622 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2623 dump_ada_node (buffer, field_type, NULL_TREE, spc, false, true);
2624 pp_string (buffer, ");");
2625 newline_and_indent (buffer, spc);
2627 if (TREE_CODE (field_type) == UNION_TYPE)
2629 pp_string (buffer, "pragma Unchecked_Union (");
2630 dump_ada_node (buffer, field_type, NULL_TREE, spc, false, true);
2631 pp_string (buffer, ");");
2634 else
2636 dump_ada_double_name (buffer, parent, field);
2637 if (TREE_CODE (field_type) == UNION_TYPE)
2638 pp_string (buffer, " (discr : unsigned := 0)");
2639 pp_string (buffer, " is ");
2640 dump_ada_structure (buffer, field_type, t, spc, false);
2642 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2643 dump_ada_double_name (buffer, parent, field);
2644 pp_string (buffer, ");");
2645 newline_and_indent (buffer, spc);
2647 if (TREE_CODE (field_type) == UNION_TYPE)
2649 pp_string (buffer, "pragma Unchecked_Union (");
2650 dump_ada_double_name (buffer, parent, field);
2651 pp_string (buffer, ");");
2655 default:
2656 break;
2660 /* Dump in BUFFER constructor spec corresponding to T for TYPE. */
2662 static void
2663 print_constructor (pretty_printer *buffer, tree t, tree type)
2665 tree decl_name = DECL_NAME (TYPE_NAME (type));
2667 pp_string (buffer, "New_");
2668 pp_ada_tree_identifier (buffer, decl_name, t, 0, false);
2671 /* Dump in BUFFER destructor spec corresponding to T. */
2673 static void
2674 print_destructor (pretty_printer *buffer, tree t, tree type)
2676 tree decl_name = DECL_NAME (TYPE_NAME (type));
2678 pp_string (buffer, "Delete_");
2679 pp_ada_tree_identifier (buffer, decl_name, t, 0, false);
2682 /* Return the name of type T. */
2684 static const char *
2685 type_name (tree t)
2687 tree n = TYPE_NAME (t);
2689 if (TREE_CODE (n) == IDENTIFIER_NODE)
2690 return IDENTIFIER_POINTER (n);
2691 else
2692 return IDENTIFIER_POINTER (DECL_NAME (n));
2695 /* Dump in BUFFER the declaration of a variable T of type TYPE in Ada syntax.
2696 SPC is the indentation level. Return 1 if a declaration was printed,
2697 0 otherwise. */
2699 static int
2700 dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
2702 bool is_var = false;
2703 bool need_indent = false;
2704 bool is_class = false;
2705 tree name = TYPE_NAME (TREE_TYPE (t));
2706 tree decl_name = DECL_NAME (t);
2707 tree orig = NULL_TREE;
2709 if (cpp_check && cpp_check (t, IS_TEMPLATE))
2710 return dump_ada_template (buffer, t, spc);
2712 /* Skip enumeral values: will be handled as part of the type itself. */
2713 if (TREE_CODE (t) == CONST_DECL && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
2714 return 0;
2716 if (TREE_CODE (t) == TYPE_DECL)
2718 orig = DECL_ORIGINAL_TYPE (t);
2720 if (orig && TYPE_STUB_DECL (orig))
2722 tree stub = TYPE_STUB_DECL (orig);
2723 tree typ = TREE_TYPE (stub);
2725 if (TYPE_NAME (typ))
2727 /* If types have same representation, and same name (ignoring
2728 casing), then ignore the second type. */
2729 if (type_name (typ) == type_name (TREE_TYPE (t))
2730 || !strcasecmp (type_name (typ), type_name (TREE_TYPE (t))))
2732 TREE_VISITED (t) = 1;
2733 return 0;
2736 INDENT (spc);
2738 if (RECORD_OR_UNION_TYPE_P (typ))
2739 dump_forward_type (buffer, stub, t, spc);
2741 pp_string (buffer, "subtype ");
2742 dump_ada_node (buffer, t, type, spc, false, true);
2743 pp_string (buffer, " is ");
2744 dump_ada_node (buffer, typ, type, spc, false, true);
2745 pp_string (buffer, "; -- ");
2746 dump_sloc (buffer, t);
2748 TREE_VISITED (t) = 1;
2749 return 1;
2753 /* Skip unnamed or anonymous structs/unions/enum types. */
2754 if (!orig && !decl_name && !name
2755 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))
2756 || TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE))
2757 return 0;
2759 /* Skip anonymous enum types (duplicates of real types). */
2760 if (!orig
2761 && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE
2762 && decl_name
2763 && (*IDENTIFIER_POINTER (decl_name) == '.'
2764 || *IDENTIFIER_POINTER (decl_name) == '$'))
2765 return 0;
2767 INDENT (spc);
2769 switch (TREE_CODE (TREE_TYPE (t)))
2771 case RECORD_TYPE:
2772 case UNION_TYPE:
2773 if (!COMPLETE_TYPE_P (TREE_TYPE (t)))
2775 pp_string (buffer, "type ");
2776 dump_ada_node (buffer, t, type, spc, false, true);
2777 pp_string (buffer, " is null record; -- incomplete struct");
2778 TREE_VISITED (t) = 1;
2779 return 1;
2782 if (decl_name
2783 && (*IDENTIFIER_POINTER (decl_name) == '.'
2784 || *IDENTIFIER_POINTER (decl_name) == '$'))
2786 pp_string (buffer, "-- skipped anonymous struct ");
2787 dump_ada_node (buffer, t, type, spc, false, true);
2788 TREE_VISITED (t) = 1;
2789 return 1;
2792 if (orig && TYPE_NAME (orig))
2793 pp_string (buffer, "subtype ");
2794 else
2796 dump_nested_types (buffer, t, t, spc);
2798 if (separate_class_package (t))
2800 is_class = true;
2801 pp_string (buffer, "package Class_");
2802 dump_ada_node (buffer, t, type, spc, false, true);
2803 pp_string (buffer, " is");
2804 spc += INDENT_INCR;
2805 newline_and_indent (buffer, spc);
2808 pp_string (buffer, "type ");
2810 break;
2812 case POINTER_TYPE:
2813 case REFERENCE_TYPE:
2814 dump_forward_type (buffer, TREE_TYPE (TREE_TYPE (t)), t, spc);
2815 /* fallthrough */
2817 case ARRAY_TYPE:
2818 if ((orig && TYPE_NAME (orig)) || is_char_array (t))
2819 pp_string (buffer, "subtype ");
2820 else
2821 pp_string (buffer, "type ");
2822 break;
2824 case FUNCTION_TYPE:
2825 pp_string (buffer, "-- skipped function type ");
2826 dump_ada_node (buffer, t, type, spc, false, true);
2827 return 1;
2829 case ENUMERAL_TYPE:
2830 if ((orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2831 || !is_simple_enum (TREE_TYPE (t)))
2832 pp_string (buffer, "subtype ");
2833 else
2834 pp_string (buffer, "type ");
2835 break;
2837 default:
2838 pp_string (buffer, "subtype ");
2840 TREE_VISITED (t) = 1;
2842 else
2844 if (VAR_P (t)
2845 && decl_name
2846 && *IDENTIFIER_POINTER (decl_name) == '_')
2847 return 0;
2849 need_indent = true;
2852 /* Print the type and name. */
2853 if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
2855 if (need_indent)
2856 INDENT (spc);
2858 /* Print variable's name. */
2859 dump_ada_node (buffer, t, type, spc, false, true);
2861 if (TREE_CODE (t) == TYPE_DECL)
2863 pp_string (buffer, " is ");
2865 if (orig && TYPE_NAME (orig))
2866 dump_ada_node (buffer, TYPE_NAME (orig), type, spc, false, true);
2867 else
2868 dump_ada_array_type (buffer, t, type, spc);
2870 else
2872 tree tmp = TYPE_NAME (TREE_TYPE (t));
2874 if (spc == INDENT_INCR || TREE_STATIC (t))
2875 is_var = true;
2877 pp_string (buffer, " : ");
2879 if (TREE_CODE (TREE_TYPE (TREE_TYPE (t))) != POINTER_TYPE)
2880 pp_string (buffer, "aliased ");
2882 if (tmp)
2883 dump_ada_node (buffer, tmp, type, spc, false, true);
2884 else if (type)
2885 dump_ada_double_name (buffer, type, t);
2886 else
2887 dump_ada_array_type (buffer, t, type, spc);
2890 else if (TREE_CODE (t) == FUNCTION_DECL)
2892 bool is_abstract_class = false;
2893 bool is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
2894 tree decl_name = DECL_NAME (t);
2895 bool is_abstract = false;
2896 bool is_constructor = false;
2897 bool is_destructor = false;
2898 bool is_copy_constructor = false;
2899 bool is_move_constructor = false;
2901 if (!decl_name)
2902 return 0;
2904 if (cpp_check)
2906 is_abstract = cpp_check (t, IS_ABSTRACT);
2907 is_constructor = cpp_check (t, IS_CONSTRUCTOR);
2908 is_destructor = cpp_check (t, IS_DESTRUCTOR);
2909 is_copy_constructor = cpp_check (t, IS_COPY_CONSTRUCTOR);
2910 is_move_constructor = cpp_check (t, IS_MOVE_CONSTRUCTOR);
2913 /* Skip copy constructors and C++11 move constructors: some are internal
2914 only and those that are not cannot be called easily from Ada. */
2915 if (is_copy_constructor || is_move_constructor)
2916 return 0;
2918 if (is_constructor || is_destructor)
2920 /* ??? Skip implicit constructors/destructors for now. */
2921 if (DECL_ARTIFICIAL (t))
2922 return 0;
2924 /* Only consider constructors/destructors for complete objects. */
2925 if (strncmp (IDENTIFIER_POINTER (decl_name), "__ct_comp", 9) != 0
2926 && strncmp (IDENTIFIER_POINTER (decl_name), "__dt_comp", 9) != 0)
2927 return 0;
2930 /* If this function has an entry in the vtable, we cannot omit it. */
2931 else if (!DECL_VINDEX (t) && *IDENTIFIER_POINTER (decl_name) == '_')
2933 INDENT (spc);
2934 pp_string (buffer, "-- skipped func ");
2935 pp_string (buffer, IDENTIFIER_POINTER (decl_name));
2936 return 1;
2939 if (need_indent)
2940 INDENT (spc);
2942 if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (t))) && !is_constructor)
2943 pp_string (buffer, "procedure ");
2944 else
2945 pp_string (buffer, "function ");
2947 if (is_constructor)
2948 print_constructor (buffer, t, type);
2949 else if (is_destructor)
2950 print_destructor (buffer, t, type);
2951 else
2952 dump_ada_decl_name (buffer, t, false);
2954 dump_ada_function_declaration
2955 (buffer, t, is_method, is_constructor, is_destructor, spc);
2957 if (is_constructor && RECORD_OR_UNION_TYPE_P (type))
2958 for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
2959 if (TREE_CODE (fld) == FUNCTION_DECL && cpp_check (fld, IS_ABSTRACT))
2961 is_abstract_class = true;
2962 break;
2965 if (is_abstract || is_abstract_class)
2966 pp_string (buffer, " is abstract");
2968 pp_semicolon (buffer);
2969 pp_string (buffer, " -- ");
2970 dump_sloc (buffer, t);
2972 if (is_abstract || !DECL_ASSEMBLER_NAME (t))
2973 return 1;
2975 newline_and_indent (buffer, spc);
2977 if (is_constructor)
2979 pp_string (buffer, "pragma CPP_Constructor (");
2980 print_constructor (buffer, t, type);
2981 pp_string (buffer, ", \"");
2982 pp_asm_name (buffer, t);
2983 pp_string (buffer, "\");");
2985 else if (is_destructor)
2987 pp_string (buffer, "pragma Import (CPP, ");
2988 print_destructor (buffer, t, type);
2989 pp_string (buffer, ", \"");
2990 pp_asm_name (buffer, t);
2991 pp_string (buffer, "\");");
2993 else
2994 dump_ada_import (buffer, t);
2996 return 1;
2998 else if (TREE_CODE (t) == TYPE_DECL && !orig)
3000 bool is_interface = false;
3001 bool is_abstract_record = false;
3003 if (need_indent)
3004 INDENT (spc);
3006 /* Anonymous structs/unions. */
3007 dump_ada_node (buffer, TREE_TYPE (t), t, spc, false, true);
3009 if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE)
3010 pp_string (buffer, " (discr : unsigned := 0)");
3012 pp_string (buffer, " is ");
3014 /* Check whether we have an Ada interface compatible class.
3015 That is only have a vtable non-static data member and no
3016 non-abstract methods. */
3017 if (cpp_check
3018 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
3020 bool has_fields = false;
3022 /* Check that there are no fields other than the virtual table. */
3023 for (tree fld = TYPE_FIELDS (TREE_TYPE (t));
3024 fld;
3025 fld = TREE_CHAIN (fld))
3027 if (TREE_CODE (fld) == FIELD_DECL)
3029 if (!has_fields && DECL_VIRTUAL_P (fld))
3030 is_interface = true;
3031 else
3032 is_interface = false;
3033 has_fields = true;
3035 else if (TREE_CODE (fld) == FUNCTION_DECL
3036 && !DECL_ARTIFICIAL (fld))
3038 if (cpp_check (fld, IS_ABSTRACT))
3039 is_abstract_record = true;
3040 else
3041 is_interface = false;
3046 TREE_VISITED (t) = 1;
3047 if (is_interface)
3049 pp_string (buffer, "limited interface; -- ");
3050 dump_sloc (buffer, t);
3051 newline_and_indent (buffer, spc);
3052 pp_string (buffer, "pragma Import (CPP, ");
3053 dump_ada_node (buffer, TYPE_NAME (TREE_TYPE (t)), type, spc, false,
3054 true);
3055 pp_right_paren (buffer);
3057 dump_ada_methods (buffer, TREE_TYPE (t), spc);
3059 else
3061 if (is_abstract_record)
3062 pp_string (buffer, "abstract ");
3063 dump_ada_node (buffer, t, t, spc, false, false);
3066 else
3068 if (need_indent)
3069 INDENT (spc);
3071 if (TREE_CODE (t) == FIELD_DECL && DECL_NAME (t))
3072 check_name (buffer, t);
3074 /* Print variable/type's name. */
3075 dump_ada_node (buffer, t, t, spc, false, true);
3077 if (TREE_CODE (t) == TYPE_DECL)
3079 const bool is_subtype = TYPE_NAME (orig);
3081 if (!is_subtype && TREE_CODE (TREE_TYPE (t)) == UNION_TYPE)
3082 pp_string (buffer, " (discr : unsigned := 0)");
3084 pp_string (buffer, " is ");
3086 dump_ada_node (buffer, orig, t, spc, false, is_subtype);
3088 else
3090 if (spc == INDENT_INCR || TREE_STATIC (t))
3091 is_var = true;
3093 pp_string (buffer, " : ");
3095 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
3097 pp_string (buffer, "aliased ");
3099 if (TREE_READONLY (t) && TREE_CODE (t) != FIELD_DECL)
3100 pp_string (buffer, "constant ");
3102 if (TYPE_NAME (TREE_TYPE (t)))
3103 dump_ada_node (buffer, TREE_TYPE (t), t, spc, false, true);
3104 else if (type)
3105 dump_ada_double_name (buffer, type, t);
3107 else
3109 if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE
3110 && (TYPE_NAME (TREE_TYPE (t))
3111 || TREE_CODE (TREE_TYPE (t)) != INTEGER_TYPE))
3112 pp_string (buffer, "aliased ");
3114 if (TREE_READONLY (t) && TREE_CODE (t) != FIELD_DECL)
3115 pp_string (buffer, "constant ");
3117 dump_ada_node (buffer, TREE_TYPE (t), TREE_TYPE (t), spc, false,
3118 true);
3123 if (is_class)
3125 spc -= INDENT_INCR;
3126 newline_and_indent (buffer, spc);
3127 pp_string (buffer, "end;");
3128 newline_and_indent (buffer, spc);
3129 pp_string (buffer, "use Class_");
3130 dump_ada_node (buffer, t, type, spc, false, true);
3131 pp_semicolon (buffer);
3132 pp_newline (buffer);
3134 /* All needed indentation/newline performed already, so return 0. */
3135 return 0;
3137 else
3139 pp_string (buffer, "; -- ");
3140 dump_sloc (buffer, t);
3143 if (is_var)
3145 newline_and_indent (buffer, spc);
3146 dump_ada_import (buffer, t);
3149 return 1;
3152 /* Dump in BUFFER a structure NODE of type TYPE: name, fields, and methods
3153 with Ada syntax. SPC is the indentation level. If DISPLAY_CONVENTION is
3154 true, also print the pragma Convention for NODE. */
3156 static void
3157 dump_ada_structure (pretty_printer *buffer, tree node, tree type, int spc,
3158 bool display_convention)
3160 tree tmp;
3161 const bool is_union = (TREE_CODE (node) == UNION_TYPE);
3162 char buf[32];
3163 int field_num = 0;
3164 int field_spc = spc + INDENT_INCR;
3165 int need_semicolon;
3167 bitfield_used = false;
3169 /* Print the contents of the structure. */
3170 pp_string (buffer, "record");
3172 if (is_union)
3174 newline_and_indent (buffer, spc + INDENT_INCR);
3175 pp_string (buffer, "case discr is");
3176 field_spc = spc + INDENT_INCR * 3;
3179 pp_newline (buffer);
3181 /* Print the non-static fields of the structure. */
3182 for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
3184 /* Add parent field if needed. */
3185 if (!DECL_NAME (tmp))
3187 if (!is_tagged_type (TREE_TYPE (tmp)))
3189 if (!TYPE_NAME (TREE_TYPE (tmp)))
3190 dump_ada_declaration (buffer, tmp, type, field_spc);
3191 else
3193 INDENT (field_spc);
3195 if (field_num == 0)
3196 pp_string (buffer, "parent : aliased ");
3197 else
3199 sprintf (buf, "field_%d : aliased ", field_num + 1);
3200 pp_string (buffer, buf);
3202 dump_ada_decl_name
3203 (buffer, TYPE_NAME (TREE_TYPE (tmp)), false);
3204 pp_semicolon (buffer);
3207 pp_newline (buffer);
3208 field_num++;
3211 else if (TREE_CODE (tmp) == FIELD_DECL)
3213 /* Skip internal virtual table field. */
3214 if (!DECL_VIRTUAL_P (tmp))
3216 if (is_union)
3218 if (TREE_CHAIN (tmp)
3219 && TREE_TYPE (TREE_CHAIN (tmp)) != node
3220 && TREE_CODE (TREE_CHAIN (tmp)) != TYPE_DECL)
3221 sprintf (buf, "when %d =>", field_num);
3222 else
3223 sprintf (buf, "when others =>");
3225 INDENT (spc + INDENT_INCR * 2);
3226 pp_string (buffer, buf);
3227 pp_newline (buffer);
3230 if (dump_ada_declaration (buffer, tmp, type, field_spc))
3232 pp_newline (buffer);
3233 field_num++;
3239 if (is_union)
3241 INDENT (spc + INDENT_INCR);
3242 pp_string (buffer, "end case;");
3243 pp_newline (buffer);
3246 if (field_num == 0)
3248 INDENT (spc + INDENT_INCR);
3249 pp_string (buffer, "null;");
3250 pp_newline (buffer);
3253 INDENT (spc);
3254 pp_string (buffer, "end record;");
3256 newline_and_indent (buffer, spc);
3258 if (!display_convention)
3259 return;
3261 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
3263 if (has_nontrivial_methods (TREE_TYPE (type)))
3264 pp_string (buffer, "pragma Import (CPP, ");
3265 else
3266 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
3268 else
3269 pp_string (buffer, "pragma Convention (C, ");
3271 package_prefix = false;
3272 dump_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
3273 package_prefix = true;
3274 pp_right_paren (buffer);
3276 if (is_union)
3278 pp_semicolon (buffer);
3279 newline_and_indent (buffer, spc);
3280 pp_string (buffer, "pragma Unchecked_Union (");
3282 dump_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
3283 pp_right_paren (buffer);
3286 if (bitfield_used)
3288 pp_semicolon (buffer);
3289 newline_and_indent (buffer, spc);
3290 pp_string (buffer, "pragma Pack (");
3291 dump_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
3292 pp_right_paren (buffer);
3293 bitfield_used = false;
3296 need_semicolon = !dump_ada_methods (buffer, node, spc);
3298 /* Print the static fields of the structure, if any. */
3299 for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
3301 if (TREE_CODE (tmp) == VAR_DECL && DECL_NAME (tmp))
3303 if (need_semicolon)
3305 need_semicolon = false;
3306 pp_semicolon (buffer);
3308 pp_newline (buffer);
3309 pp_newline (buffer);
3310 dump_ada_declaration (buffer, tmp, type, spc);
3315 /* Dump all the declarations in SOURCE_FILE to an Ada spec.
3316 COLLECT_ALL_REFS is a front-end callback used to collect all relevant
3317 nodes for SOURCE_FILE. CHECK is used to perform C++ queries on nodes. */
3319 static void
3320 dump_ads (const char *source_file,
3321 void (*collect_all_refs)(const char *),
3322 int (*check)(tree, cpp_operation))
3324 char *ads_name;
3325 char *pkg_name;
3326 char *s;
3327 FILE *f;
3329 pkg_name = get_ada_package (source_file);
3331 /* Construct the .ads filename and package name. */
3332 ads_name = xstrdup (pkg_name);
3334 for (s = ads_name; *s; s++)
3335 if (*s == '.')
3336 *s = '-';
3337 else
3338 *s = TOLOWER (*s);
3340 ads_name = reconcat (ads_name, ads_name, ".ads", NULL);
3342 /* Write out the .ads file. */
3343 f = fopen (ads_name, "w");
3344 if (f)
3346 pretty_printer pp;
3348 pp_needs_newline (&pp) = true;
3349 pp.buffer->stream = f;
3351 /* Dump all relevant macros. */
3352 dump_ada_macros (&pp, source_file);
3354 /* Reset the table of withs for this file. */
3355 reset_ada_withs ();
3357 (*collect_all_refs) (source_file);
3359 /* Dump all references. */
3360 cpp_check = check;
3361 dump_ada_nodes (&pp, source_file);
3363 /* Requires Ada 2005 syntax, so generate corresponding pragma.
3364 Also, disable style checks since this file is auto-generated. */
3365 fprintf (f, "pragma Ada_2005;\npragma Style_Checks (Off);\n\n");
3367 /* Dump withs. */
3368 dump_ada_withs (f);
3370 fprintf (f, "\npackage %s is\n\n", pkg_name);
3371 pp_write_text_to_stream (&pp);
3372 /* ??? need to free pp */
3373 fprintf (f, "end %s;\n", pkg_name);
3374 fclose (f);
3377 free (ads_name);
3378 free (pkg_name);
3381 static const char **source_refs = NULL;
3382 static int source_refs_used = 0;
3383 static int source_refs_allocd = 0;
3385 /* Add an entry for FILENAME to the table SOURCE_REFS. */
3387 void
3388 collect_source_ref (const char *filename)
3390 int i;
3392 if (!filename)
3393 return;
3395 if (source_refs_allocd == 0)
3397 source_refs_allocd = 1024;
3398 source_refs = XNEWVEC (const char *, source_refs_allocd);
3401 for (i = 0; i < source_refs_used; i++)
3402 if (filename == source_refs[i])
3403 return;
3405 if (source_refs_used == source_refs_allocd)
3407 source_refs_allocd *= 2;
3408 source_refs = XRESIZEVEC (const char *, source_refs, source_refs_allocd);
3411 source_refs[source_refs_used++] = filename;
3414 /* Main entry point: dump all Ada specs corresponding to SOURCE_REFS
3415 using callbacks COLLECT_ALL_REFS and CHECK.
3416 COLLECT_ALL_REFS is a front-end callback used to collect all relevant
3417 nodes for a given source file.
3418 CHECK is used to perform C++ queries on nodes, or NULL for the C
3419 front-end. */
3421 void
3422 dump_ada_specs (void (*collect_all_refs)(const char *),
3423 int (*check)(tree, cpp_operation))
3425 /* Iterate over the list of files to dump specs for. */
3426 for (int i = 0; i < source_refs_used; i++)
3427 dump_ads (source_refs[i], collect_all_refs, check);
3429 /* Free various tables. */
3430 free (source_refs);
3431 delete overloaded_names;