]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/c-family/c-ada-spec.c
i386.c (ix86_adjust_stack_and_probe_stack_clash): Fix typos and whitespace errors.
[thirdparty/gcc.git] / gcc / c-family / c-ada-spec.c
CommitLineData
9cc54940
AC
1/* Print GENERIC declaration (functions, variables, types) trees coming from
2 the C and C++ front-ends as well as macros in Ada syntax.
cbe34bb5 3 Copyright (C) 2010-2017 Free Software Foundation, Inc.
9cc54940
AC
4 Adapted from tree-pretty-print.c by Arnaud Charlet <charlet@adacore.com>
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
21
22#include "config.h"
23#include "system.h"
24#include "coretypes.h"
25#include "tm.h"
26#include "tree.h"
2adfab87 27#include "c-ada-spec.h"
40e23961 28#include "fold-const.h"
9cc54940
AC
29#include "c-pragma.h"
30#include "cpp-id-data.h"
314e6352
ML
31#include "stringpool.h"
32#include "attribs.h"
909881cb 33
9cc54940 34/* Local functions, macros and variables. */
94159ecf
EB
35static int dump_generic_ada_node (pretty_printer *, tree, tree, int, int,
36 bool);
37static int print_ada_declaration (pretty_printer *, tree, tree, int);
38static void print_ada_struct_decl (pretty_printer *, tree, tree, int, bool);
9cc54940
AC
39static void dump_sloc (pretty_printer *buffer, tree node);
40static void print_comment (pretty_printer *, const char *);
94159ecf 41static void print_generic_ada_decl (pretty_printer *, tree, const char *);
9cc54940 42static char *get_ada_package (const char *);
94159ecf 43static void dump_ada_nodes (pretty_printer *, const char *);
9cc54940
AC
44static void reset_ada_withs (void);
45static void dump_ada_withs (FILE *);
46static void dump_ads (const char *, void (*)(const char *),
621955cb 47 int (*)(tree, cpp_operation));
9cc54940 48static char *to_ada_name (const char *, int *);
1e4bf85b 49static bool separate_class_package (tree);
9cc54940 50
94159ecf
EB
51#define INDENT(SPACE) \
52 do { int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
9cc54940
AC
53
54#define INDENT_INCR 3
55
94159ecf 56/* Global hook used to perform C++ queries on nodes. */
621955cb 57static int (*cpp_check) (tree, cpp_operation) = NULL;
94159ecf
EB
58
59
9cc54940
AC
60/* Given a cpp MACRO, compute the max length BUFFER_LEN of the macro, as well
61 as max length PARAM_LEN of arguments for fun_like macros, and also set
62 SUPPORTED to 0 if the macro cannot be mapped to an Ada construct. */
63
64static void
65macro_length (const cpp_macro *macro, int *supported, int *buffer_len,
66 int *param_len)
67{
68 int i;
69 unsigned j;
70
71 *supported = 1;
72 *buffer_len = 0;
73 *param_len = 0;
74
75 if (macro->fun_like)
76 {
bba81f1c 77 (*param_len)++;
9cc54940
AC
78 for (i = 0; i < macro->paramc; i++)
79 {
80 cpp_hashnode *param = macro->params[i];
81
82 *param_len += NODE_LEN (param);
83
84 if (i + 1 < macro->paramc)
85 {
86 *param_len += 2; /* ", " */
87 }
88 else if (macro->variadic)
89 {
90 *supported = 0;
91 return;
92 }
93 }
94 *param_len += 2; /* ")\0" */
95 }
96
97 for (j = 0; j < macro->count; j++)
98 {
99 cpp_token *token = &macro->exp.tokens[j];
100
101 if (token->flags & PREV_WHITE)
102 (*buffer_len)++;
103
104 if (token->flags & STRINGIFY_ARG || token->flags & PASTE_LEFT)
105 {
106 *supported = 0;
107 return;
108 }
109
110 if (token->type == CPP_MACRO_ARG)
111 *buffer_len +=
112 NODE_LEN (macro->params[token->val.macro_arg.arg_no - 1]);
113 else
114 /* Include enough extra space to handle e.g. special characters. */
115 *buffer_len += (cpp_token_len (token) + 1) * 8;
116 }
117
118 (*buffer_len)++;
119}
120
7e1dde14
EB
121/* Dump all digits/hex chars from NUMBER to BUFFER and return a pointer
122 to the character after the last character written. */
123
124static unsigned char *
125dump_number (unsigned char *number, unsigned char *buffer)
126{
127 while (*number != '\0'
128 && *number != 'U'
129 && *number != 'u'
130 && *number != 'l'
131 && *number != 'L')
132 *buffer++ = *number++;
133
134 return buffer;
135}
136
137/* Handle escape character C and convert to an Ada character into BUFFER.
138 Return a pointer to the character after the last character written, or
139 NULL if the escape character is not supported. */
140
141static unsigned char *
142handle_escape_character (unsigned char *buffer, char c)
143{
144 switch (c)
145 {
146 case '"':
147 *buffer++ = '"';
148 *buffer++ = '"';
149 break;
150
151 case 'n':
152 strcpy ((char *) buffer, "\" & ASCII.LF & \"");
153 buffer += 16;
154 break;
155
156 case 'r':
157 strcpy ((char *) buffer, "\" & ASCII.CR & \"");
158 buffer += 16;
159 break;
160
161 case 't':
162 strcpy ((char *) buffer, "\" & ASCII.HT & \"");
163 buffer += 16;
164 break;
165
166 default:
167 return NULL;
168 }
169
170 return buffer;
171}
172
9cc54940
AC
173/* Dump into PP a set of MAX_ADA_MACROS MACROS (C/C++) as Ada constants when
174 possible. */
175
176static void
177print_ada_macros (pretty_printer *pp, cpp_hashnode **macros, int max_ada_macros)
178{
179 int j, num_macros = 0, prev_line = -1;
180
181 for (j = 0; j < max_ada_macros; j++)
182 {
0b07a57e 183 cpp_hashnode *node = macros[j];
9cc54940
AC
184 const cpp_macro *macro = node->value.macro;
185 unsigned i;
186 int supported = 1, prev_is_one = 0, buffer_len, param_len;
187 int is_string = 0, is_char = 0;
188 char *ada_name;
7e1dde14 189 unsigned char *s, *params, *buffer, *buf_param, *char_one = NULL, *tmp;
9cc54940
AC
190
191 macro_length (macro, &supported, &buffer_len, &param_len);
192 s = buffer = XALLOCAVEC (unsigned char, buffer_len);
193 params = buf_param = XALLOCAVEC (unsigned char, param_len);
194
195 if (supported)
196 {
197 if (macro->fun_like)
198 {
199 *buf_param++ = '(';
200 for (i = 0; i < macro->paramc; i++)
201 {
202 cpp_hashnode *param = macro->params[i];
203
204 memcpy (buf_param, NODE_NAME (param), NODE_LEN (param));
205 buf_param += NODE_LEN (param);
206
207 if (i + 1 < macro->paramc)
208 {
209 *buf_param++ = ',';
210 *buf_param++ = ' ';
211 }
212 else if (macro->variadic)
213 {
214 supported = 0;
215 break;
216 }
217 }
218 *buf_param++ = ')';
219 *buf_param = '\0';
220 }
221
222 for (i = 0; supported && i < macro->count; i++)
223 {
224 cpp_token *token = &macro->exp.tokens[i];
225 int is_one = 0;
226
227 if (token->flags & PREV_WHITE)
228 *buffer++ = ' ';
229
230 if (token->flags & STRINGIFY_ARG || token->flags & PASTE_LEFT)
231 {
232 supported = 0;
233 break;
234 }
235
236 switch (token->type)
237 {
238 case CPP_MACRO_ARG:
239 {
240 cpp_hashnode *param =
241 macro->params[token->val.macro_arg.arg_no - 1];
242 memcpy (buffer, NODE_NAME (param), NODE_LEN (param));
243 buffer += NODE_LEN (param);
244 }
245 break;
246
247 case CPP_EQ_EQ: *buffer++ = '='; break;
248 case CPP_GREATER: *buffer++ = '>'; break;
249 case CPP_LESS: *buffer++ = '<'; break;
250 case CPP_PLUS: *buffer++ = '+'; break;
251 case CPP_MINUS: *buffer++ = '-'; break;
252 case CPP_MULT: *buffer++ = '*'; break;
253 case CPP_DIV: *buffer++ = '/'; break;
254 case CPP_COMMA: *buffer++ = ','; break;
255 case CPP_OPEN_SQUARE:
256 case CPP_OPEN_PAREN: *buffer++ = '('; break;
257 case CPP_CLOSE_SQUARE: /* fallthrough */
258 case CPP_CLOSE_PAREN: *buffer++ = ')'; break;
259 case CPP_DEREF: /* fallthrough */
260 case CPP_SCOPE: /* fallthrough */
261 case CPP_DOT: *buffer++ = '.'; break;
262
263 case CPP_EQ: *buffer++ = ':'; *buffer++ = '='; break;
264 case CPP_NOT_EQ: *buffer++ = '/'; *buffer++ = '='; break;
265 case CPP_GREATER_EQ: *buffer++ = '>'; *buffer++ = '='; break;
266 case CPP_LESS_EQ: *buffer++ = '<'; *buffer++ = '='; break;
267
268 case CPP_NOT:
269 *buffer++ = 'n'; *buffer++ = 'o'; *buffer++ = 't'; break;
270 case CPP_MOD:
271 *buffer++ = 'm'; *buffer++ = 'o'; *buffer++ = 'd'; break;
272 case CPP_AND:
273 *buffer++ = 'a'; *buffer++ = 'n'; *buffer++ = 'd'; break;
274 case CPP_OR:
275 *buffer++ = 'o'; *buffer++ = 'r'; break;
276 case CPP_XOR:
277 *buffer++ = 'x'; *buffer++ = 'o'; *buffer++ = 'r'; break;
278 case CPP_AND_AND:
279 strcpy ((char *) buffer, " and then ");
280 buffer += 10;
281 break;
282 case CPP_OR_OR:
283 strcpy ((char *) buffer, " or else ");
284 buffer += 9;
285 break;
286
287 case CPP_PADDING:
288 *buffer++ = ' ';
289 is_one = prev_is_one;
290 break;
291
292 case CPP_COMMENT: break;
293
294 case CPP_WSTRING:
295 case CPP_STRING16:
296 case CPP_STRING32:
297 case CPP_UTF8STRING:
298 case CPP_WCHAR:
299 case CPP_CHAR16:
300 case CPP_CHAR32:
fe95b036 301 case CPP_UTF8CHAR:
9cc54940 302 case CPP_NAME:
9cc54940
AC
303 if (!macro->fun_like)
304 supported = 0;
305 else
306 buffer = cpp_spell_token (parse_in, token, buffer, false);
307 break;
308
7e1dde14
EB
309 case CPP_STRING:
310 is_string = 1;
311 {
312 const unsigned char *s = token->val.str.text;
313
314 for (; *s; s++)
315 if (*s == '\\')
316 {
317 s++;
318 buffer = handle_escape_character (buffer, *s);
319 if (buffer == NULL)
320 {
321 supported = 0;
322 break;
323 }
324 }
325 else
326 *buffer++ = *s;
327 }
328 break;
329
9cc54940
AC
330 case CPP_CHAR:
331 is_char = 1;
332 {
333 unsigned chars_seen;
334 int ignored;
335 cppchar_t c;
336
337 c = cpp_interpret_charconst (parse_in, token,
338 &chars_seen, &ignored);
339 if (c >= 32 && c <= 126)
340 {
341 *buffer++ = '\'';
342 *buffer++ = (char) c;
343 *buffer++ = '\'';
344 }
345 else
346 {
347 chars_seen = sprintf
348 ((char *) buffer, "Character'Val (%d)", (int) c);
349 buffer += chars_seen;
350 }
351 }
352 break;
353
7e1dde14
EB
354 case CPP_NUMBER:
355 tmp = cpp_token_as_text (parse_in, token);
356
357 switch (*tmp)
358 {
359 case '0':
360 switch (tmp[1])
361 {
362 case '\0':
363 case 'l':
364 case 'L':
365 case 'u':
366 case 'U':
367 *buffer++ = '0';
368 break;
369
370 case 'x':
371 case 'X':
372 *buffer++ = '1';
373 *buffer++ = '6';
374 *buffer++ = '#';
375 buffer = dump_number (tmp + 2, buffer);
376 *buffer++ = '#';
377 break;
378
379 case 'b':
380 case 'B':
381 *buffer++ = '2';
382 *buffer++ = '#';
383 buffer = dump_number (tmp + 2, buffer);
384 *buffer++ = '#';
385 break;
386
387 default:
388 /* Dump floating constants unmodified. */
389 if (strchr ((const char *)tmp, '.'))
390 buffer = dump_number (tmp, buffer);
391 else
392 {
393 *buffer++ = '8';
394 *buffer++ = '#';
395 buffer = dump_number (tmp + 1, buffer);
396 *buffer++ = '#';
397 }
398 break;
399 }
400 break;
401
402 case '1':
403 if (tmp[1] == '\0' || tmp[1] == 'l' || tmp[1] == 'u'
404 || tmp[1] == 'L' || tmp[1] == 'U')
405 {
406 is_one = 1;
407 char_one = buffer;
408 *buffer++ = '1';
409 }
410 else
411 buffer = dump_number (tmp, buffer);
412 break;
413
414 default:
415 buffer = dump_number (tmp, buffer);
416 break;
417 }
418 break;
419
9cc54940
AC
420 case CPP_LSHIFT:
421 if (prev_is_one)
422 {
423 /* Replace "1 << N" by "2 ** N" */
424 *char_one = '2';
425 *buffer++ = '*';
426 *buffer++ = '*';
427 break;
428 }
429 /* fallthrough */
430
431 case CPP_RSHIFT:
432 case CPP_COMPL:
433 case CPP_QUERY:
434 case CPP_EOF:
435 case CPP_PLUS_EQ:
436 case CPP_MINUS_EQ:
437 case CPP_MULT_EQ:
438 case CPP_DIV_EQ:
439 case CPP_MOD_EQ:
440 case CPP_AND_EQ:
441 case CPP_OR_EQ:
442 case CPP_XOR_EQ:
443 case CPP_RSHIFT_EQ:
444 case CPP_LSHIFT_EQ:
445 case CPP_PRAGMA:
446 case CPP_PRAGMA_EOL:
447 case CPP_HASH:
448 case CPP_PASTE:
449 case CPP_OPEN_BRACE:
450 case CPP_CLOSE_BRACE:
451 case CPP_SEMICOLON:
452 case CPP_ELLIPSIS:
453 case CPP_PLUS_PLUS:
454 case CPP_MINUS_MINUS:
455 case CPP_DEREF_STAR:
456 case CPP_DOT_STAR:
457 case CPP_ATSIGN:
458 case CPP_HEADER_NAME:
459 case CPP_AT_NAME:
460 case CPP_OTHER:
461 case CPP_OBJC_STRING:
462 default:
463 if (!macro->fun_like)
464 supported = 0;
465 else
466 buffer = cpp_spell_token (parse_in, token, buffer, false);
467 break;
468 }
469
470 prev_is_one = is_one;
471 }
472
473 if (supported)
474 *buffer = '\0';
475 }
476
477 if (macro->fun_like && supported)
478 {
479 char *start = (char *) s;
480 int is_function = 0;
481
482 pp_string (pp, " -- arg-macro: ");
483
0b07a57e 484 if (*start == '(' && buffer[-1] == ')')
9cc54940
AC
485 {
486 start++;
0b07a57e 487 buffer[-1] = '\0';
9cc54940
AC
488 is_function = 1;
489 pp_string (pp, "function ");
490 }
491 else
492 {
493 pp_string (pp, "procedure ");
494 }
495
496 pp_string (pp, (const char *) NODE_NAME (node));
497 pp_space (pp);
498 pp_string (pp, (char *) params);
499 pp_newline (pp);
500 pp_string (pp, " -- ");
501
502 if (is_function)
503 {
504 pp_string (pp, "return ");
505 pp_string (pp, start);
506 pp_semicolon (pp);
507 }
508 else
509 pp_string (pp, start);
510
511 pp_newline (pp);
512 }
513 else if (supported)
514 {
515 expanded_location sloc = expand_location (macro->line);
516
f07862c7 517 if (sloc.line != prev_line + 1 && prev_line > 0)
9cc54940
AC
518 pp_newline (pp);
519
520 num_macros++;
521 prev_line = sloc.line;
522
523 pp_string (pp, " ");
524 ada_name = to_ada_name ((const char *) NODE_NAME (node), NULL);
525 pp_string (pp, ada_name);
526 free (ada_name);
527 pp_string (pp, " : ");
528
529 if (is_string)
530 pp_string (pp, "aliased constant String");
531 else if (is_char)
532 pp_string (pp, "aliased constant Character");
533 else
534 pp_string (pp, "constant");
535
536 pp_string (pp, " := ");
537 pp_string (pp, (char *) s);
538
539 if (is_string)
540 pp_string (pp, " & ASCII.NUL");
541
542 pp_string (pp, "; -- ");
543 pp_string (pp, sloc.file);
07838b13 544 pp_colon (pp);
9cc54940
AC
545 pp_scalar (pp, "%d", sloc.line);
546 pp_newline (pp);
547 }
548 else
549 {
550 pp_string (pp, " -- unsupported macro: ");
551 pp_string (pp, (const char *) cpp_macro_definition (parse_in, node));
552 pp_newline (pp);
553 }
554 }
555
556 if (num_macros > 0)
557 pp_newline (pp);
558}
559
560static const char *source_file;
561static int max_ada_macros;
562
563/* Callback used to count the number of relevant macros from
564 cpp_forall_identifiers. PFILE and V are not used. NODE is the current macro
565 to consider. */
566
567static int
568count_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *node,
569 void *v ATTRIBUTE_UNUSED)
570{
571 const cpp_macro *macro = node->value.macro;
572
573 if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)
574 && macro->count
575 && *NODE_NAME (node) != '_'
576 && LOCATION_FILE (macro->line) == source_file)
577 max_ada_macros++;
578
579 return 1;
580}
581
582static int store_ada_macro_index;
583
584/* Callback used to store relevant macros from cpp_forall_identifiers.
585 PFILE is not used. NODE is the current macro to store if relevant.
586 MACROS is an array of cpp_hashnode* used to store NODE. */
587
588static int
589store_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED,
590 cpp_hashnode *node, void *macros)
591{
592 const cpp_macro *macro = node->value.macro;
593
594 if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)
595 && macro->count
596 && *NODE_NAME (node) != '_'
597 && LOCATION_FILE (macro->line) == source_file)
598 ((cpp_hashnode **) macros)[store_ada_macro_index++] = node;
599
600 return 1;
601}
602
603/* Callback used to compare (during qsort) macros. NODE1 and NODE2 are the
604 two macro nodes to compare. */
605
606static int
607compare_macro (const void *node1, const void *node2)
608{
609 typedef const cpp_hashnode *const_hnode;
610
611 const_hnode n1 = *(const const_hnode *) node1;
612 const_hnode n2 = *(const const_hnode *) node2;
613
614 return n1->value.macro->line - n2->value.macro->line;
615}
616
617/* Dump in PP all relevant macros appearing in FILE. */
618
619static void
620dump_ada_macros (pretty_printer *pp, const char* file)
621{
622 cpp_hashnode **macros;
623
624 /* Initialize file-scope variables. */
625 max_ada_macros = 0;
626 store_ada_macro_index = 0;
627 source_file = file;
628
629 /* Count all potentially relevant macros, and then sort them by sloc. */
630 cpp_forall_identifiers (parse_in, count_ada_macro, NULL);
631 macros = XALLOCAVEC (cpp_hashnode *, max_ada_macros);
632 cpp_forall_identifiers (parse_in, store_ada_macro, macros);
633 qsort (macros, max_ada_macros, sizeof (cpp_hashnode *), compare_macro);
634
635 print_ada_macros (pp, macros, max_ada_macros);
636}
637
638/* Current source file being handled. */
639
640static const char *source_file_base;
641
f07862c7 642/* Return sloc of DECL, using sloc of last field if LAST is true. */
9cc54940 643
f07862c7
EB
644location_t
645decl_sloc (const_tree decl, bool last)
9cc54940 646{
f07862c7 647 tree field;
9cc54940 648
f07862c7
EB
649 /* Compare the declaration of struct-like types based on the sloc of their
650 last field (if LAST is true), so that more nested types collate before
651 less nested ones. */
9cc54940 652 if (TREE_CODE (decl) == TYPE_DECL
f07862c7
EB
653 && !DECL_ORIGINAL_TYPE (decl)
654 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
655 && (field = TYPE_FIELDS (TREE_TYPE (decl))))
9cc54940 656 {
9cc54940 657 if (last)
f07862c7
EB
658 while (DECL_CHAIN (field))
659 field = DECL_CHAIN (field);
660 return DECL_SOURCE_LOCATION (field);
9cc54940 661 }
9cc54940 662
f07862c7 663 return DECL_SOURCE_LOCATION (decl);
9cc54940
AC
664}
665
67e4210b
EB
666/* Compare two locations LHS and RHS. */
667
668static int
669compare_location (location_t lhs, location_t rhs)
670{
671 expanded_location xlhs = expand_location (lhs);
672 expanded_location xrhs = expand_location (rhs);
673
674 if (xlhs.file != xrhs.file)
675 return filename_cmp (xlhs.file, xrhs.file);
676
677 if (xlhs.line != xrhs.line)
678 return xlhs.line - xrhs.line;
679
680 if (xlhs.column != xrhs.column)
681 return xlhs.column - xrhs.column;
682
683 return 0;
684}
685
9cc54940
AC
686/* Compare two declarations (LP and RP) by their source location. */
687
688static int
689compare_node (const void *lp, const void *rp)
690{
691 const_tree lhs = *((const tree *) lp);
692 const_tree rhs = *((const tree *) rp);
693
67e4210b 694 return compare_location (decl_sloc (lhs, true), decl_sloc (rhs, true));
9cc54940
AC
695}
696
697/* Compare two comments (LP and RP) by their source location. */
698
699static int
700compare_comment (const void *lp, const void *rp)
701{
702 const cpp_comment *lhs = (const cpp_comment *) lp;
703 const cpp_comment *rhs = (const cpp_comment *) rp;
704
67e4210b 705 return compare_location (lhs->sloc, rhs->sloc);
9cc54940
AC
706}
707
708static tree *to_dump = NULL;
709static int to_dump_count = 0;
710
711/* Collect a list of declarations from T relevant to SOURCE_FILE to be dumped
712 by a subsequent call to dump_ada_nodes. */
713
714void
715collect_ada_nodes (tree t, const char *source_file)
716{
717 tree n;
718 int i = to_dump_count;
719
c6a2f2d9
PMR
720 /* Count the likely relevant nodes: do not dump builtins (they are irrelevant
721 in the context of bindings) and namespaces (we do not handle them properly
722 yet). */
9cc54940
AC
723 for (n = t; n; n = TREE_CHAIN (n))
724 if (!DECL_IS_BUILTIN (n)
c6a2f2d9 725 && TREE_CODE (n) != NAMESPACE_DECL
9cc54940
AC
726 && LOCATION_FILE (decl_sloc (n, false)) == source_file)
727 to_dump_count++;
728
729 /* Allocate sufficient storage for all nodes. */
730 to_dump = XRESIZEVEC (tree, to_dump, to_dump_count);
731
732 /* Store the relevant nodes. */
733 for (n = t; n; n = TREE_CHAIN (n))
734 if (!DECL_IS_BUILTIN (n)
c6a2f2d9 735 && TREE_CODE (n) != NAMESPACE_DECL
9cc54940 736 && LOCATION_FILE (decl_sloc (n, false)) == source_file)
0b07a57e 737 to_dump[i++] = n;
9cc54940
AC
738}
739
740/* Call back for walk_tree to clear the TREE_VISITED flag of TP. */
741
742static tree
743unmark_visited_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
744 void *data ATTRIBUTE_UNUSED)
745{
746 if (TREE_VISITED (*tp))
747 TREE_VISITED (*tp) = 0;
748 else
749 *walk_subtrees = 0;
750
751 return NULL_TREE;
752}
753
754/* Dump nodes into PP relevant to SOURCE_FILE, as collected by previous calls
94159ecf 755 to collect_ada_nodes. */
9cc54940
AC
756
757static void
94159ecf 758dump_ada_nodes (pretty_printer *pp, const char *source_file)
9cc54940
AC
759{
760 int i, j;
761 cpp_comment_table *comments;
762
763 /* Sort the table of declarations to dump by sloc. */
764 qsort (to_dump, to_dump_count, sizeof (tree), compare_node);
765
766 /* Fetch the table of comments. */
767 comments = cpp_get_comments (parse_in);
768
769 /* Sort the comments table by sloc. */
00a7ba58
JJ
770 if (comments->count > 1)
771 qsort (comments->entries, comments->count, sizeof (cpp_comment),
772 compare_comment);
9cc54940
AC
773
774 /* Interleave comments and declarations in line number order. */
775 i = j = 0;
776 do
777 {
778 /* Advance j until comment j is in this file. */
779 while (j != comments->count
780 && LOCATION_FILE (comments->entries[j].sloc) != source_file)
781 j++;
782
783 /* Advance j until comment j is not a duplicate. */
784 while (j < comments->count - 1
785 && !compare_comment (&comments->entries[j],
786 &comments->entries[j + 1]))
787 j++;
788
789 /* Write decls until decl i collates after comment j. */
790 while (i != to_dump_count)
791 {
792 if (j == comments->count
793 || LOCATION_LINE (decl_sloc (to_dump[i], false))
794 < LOCATION_LINE (comments->entries[j].sloc))
94159ecf 795 print_generic_ada_decl (pp, to_dump[i++], source_file);
9cc54940
AC
796 else
797 break;
798 }
799
800 /* Write comment j, if there is one. */
801 if (j != comments->count)
802 print_comment (pp, comments->entries[j++].comment);
803
804 } while (i != to_dump_count || j != comments->count);
805
806 /* Clear the TREE_VISITED flag over each subtree we've dumped. */
807 for (i = 0; i < to_dump_count; i++)
808 walk_tree (&to_dump[i], unmark_visited_r, NULL, NULL);
809
810 /* Finalize the to_dump table. */
811 if (to_dump)
812 {
813 free (to_dump);
814 to_dump = NULL;
815 to_dump_count = 0;
816 }
817}
818
819/* Print a COMMENT to the output stream PP. */
820
821static void
822print_comment (pretty_printer *pp, const char *comment)
823{
824 int len = strlen (comment);
825 char *str = XALLOCAVEC (char, len + 1);
826 char *tok;
827 bool extra_newline = false;
828
829 memcpy (str, comment, len + 1);
830
831 /* Trim C/C++ comment indicators. */
832 if (str[len - 2] == '*' && str[len - 1] == '/')
833 {
834 str[len - 2] = ' ';
835 str[len - 1] = '\0';
836 }
837 str += 2;
838
839 tok = strtok (str, "\n");
840 while (tok) {
841 pp_string (pp, " --");
842 pp_string (pp, tok);
843 pp_newline (pp);
844 tok = strtok (NULL, "\n");
845
846 /* Leave a blank line after multi-line comments. */
847 if (tok)
848 extra_newline = true;
849 }
850
851 if (extra_newline)
852 pp_newline (pp);
853}
854
94159ecf
EB
855/* Print declaration DECL to PP in Ada syntax. The current source file being
856 handled is SOURCE_FILE. */
9cc54940
AC
857
858static void
94159ecf 859print_generic_ada_decl (pretty_printer *pp, tree decl, const char *source_file)
9cc54940
AC
860{
861 source_file_base = source_file;
862
f4bcd9eb 863 if (print_ada_declaration (pp, decl, NULL_TREE, INDENT_INCR))
9cc54940
AC
864 {
865 pp_newline (pp);
866 pp_newline (pp);
867 }
868}
869
870/* Dump a newline and indent BUFFER by SPC chars. */
871
872static void
873newline_and_indent (pretty_printer *buffer, int spc)
874{
875 pp_newline (buffer);
876 INDENT (spc);
877}
878
879struct with { char *s; const char *in_file; int limited; };
880static struct with *withs = NULL;
881static int withs_max = 4096;
882static int with_len = 0;
883
884/* Record a "with" clause on package S (a limited with if LIMITED_ACCESS is
885 true), if not already done. */
886
887static void
888append_withs (const char *s, int limited_access)
889{
890 int i;
891
892 if (withs == NULL)
893 withs = XNEWVEC (struct with, withs_max);
894
895 if (with_len == withs_max)
896 {
897 withs_max *= 2;
898 withs = XRESIZEVEC (struct with, withs, withs_max);
899 }
900
901 for (i = 0; i < with_len; i++)
0b07a57e
AC
902 if (!strcmp (s, withs[i].s)
903 && source_file_base == withs[i].in_file)
9cc54940 904 {
0b07a57e 905 withs[i].limited &= limited_access;
9cc54940
AC
906 return;
907 }
908
0b07a57e
AC
909 withs[with_len].s = xstrdup (s);
910 withs[with_len].in_file = source_file_base;
911 withs[with_len].limited = limited_access;
9cc54940
AC
912 with_len++;
913}
914
915/* Reset "with" clauses. */
916
917static void
918reset_ada_withs (void)
919{
920 int i;
921
922 if (!withs)
923 return;
924
925 for (i = 0; i < with_len; i++)
0b07a57e 926 free (withs[i].s);
9cc54940
AC
927 free (withs);
928 withs = NULL;
929 withs_max = 4096;
930 with_len = 0;
931}
932
933/* Dump "with" clauses in F. */
934
935static void
936dump_ada_withs (FILE *f)
937{
938 int i;
939
940 fprintf (f, "with Interfaces.C; use Interfaces.C;\n");
941
942 for (i = 0; i < with_len; i++)
943 fprintf
0b07a57e 944 (f, "%swith %s;\n", withs[i].limited ? "limited " : "", withs[i].s);
9cc54940
AC
945}
946
947/* Return suitable Ada package name from FILE. */
948
949static char *
950get_ada_package (const char *file)
951{
952 const char *base;
953 char *res;
954 const char *s;
955 int i;
da5182be 956 size_t plen;
9cc54940
AC
957
958 s = strstr (file, "/include/");
959 if (s)
960 base = s + 9;
961 else
962 base = lbasename (file);
9cc54940 963
da5182be
TQ
964 if (ada_specs_parent == NULL)
965 plen = 0;
966 else
967 plen = strlen (ada_specs_parent) + 1;
968
969 res = XNEWVEC (char, plen + strlen (base) + 1);
970 if (ada_specs_parent != NULL) {
971 strcpy (res, ada_specs_parent);
972 res[plen - 1] = '.';
973 }
974
975 for (i = plen; *base; base++, i++)
9cc54940
AC
976 switch (*base)
977 {
978 case '+':
0b07a57e 979 res[i] = 'p';
9cc54940
AC
980 break;
981
982 case '.':
983 case '-':
984 case '_':
985 case '/':
986 case '\\':
da5182be 987 res[i] = (i == 0 || res[i - 1] == '.' || res[i - 1] == '_') ? 'u' : '_';
9cc54940
AC
988 break;
989
990 default:
da5182be 991 res[i] = *base;
9cc54940
AC
992 break;
993 }
da5182be 994 res[i] = '\0';
9cc54940
AC
995
996 return res;
997}
998
999static const char *ada_reserved[] = {
1000 "abort", "abs", "abstract", "accept", "access", "aliased", "all", "and",
1001 "array", "at", "begin", "body", "case", "constant", "declare", "delay",
1002 "delta", "digits", "do", "else", "elsif", "end", "entry", "exception",
1003 "exit", "for", "function", "generic", "goto", "if", "in", "interface", "is",
1004 "limited", "loop", "mod", "new", "not", "null", "others", "out", "of", "or",
1005 "overriding", "package", "pragma", "private", "procedure", "protected",
1006 "raise", "range", "record", "rem", "renames", "requeue", "return", "reverse",
1007 "select", "separate", "subtype", "synchronized", "tagged", "task",
1008 "terminate", "then", "type", "until", "use", "when", "while", "with", "xor",
1009 NULL};
1010
1011/* ??? would be nice to specify this list via a config file, so that users
1012 can create their own dictionary of conflicts. */
1013static const char *c_duplicates[] = {
1014 /* system will cause troubles with System.Address. */
1015 "system",
1016
1017 /* The following values have other definitions with same name/other
1018 casing. */
1019 "funmap",
1020 "rl_vi_fWord",
1021 "rl_vi_bWord",
1022 "rl_vi_eWord",
1023 "rl_readline_version",
1024 "_Vx_ushort",
1025 "USHORT",
1026 "XLookupKeysym",
1027 NULL};
1028
1029/* Return a declaration tree corresponding to TYPE. */
1030
1031static tree
1032get_underlying_decl (tree type)
1033{
23f2660f 1034 if (!type)
9cc54940
AC
1035 return NULL_TREE;
1036
1037 /* type is a declaration. */
1038 if (DECL_P (type))
23f2660f 1039 return type;
9cc54940
AC
1040
1041 /* type is a typedef. */
1042 if (TYPE_P (type) && TYPE_NAME (type) && DECL_P (TYPE_NAME (type)))
23f2660f 1043 return TYPE_NAME (type);
9cc54940
AC
1044
1045 /* TYPE_STUB_DECL has been set for type. */
23f2660f
EB
1046 if (TYPE_P (type) && TYPE_STUB_DECL (type))
1047 return TYPE_STUB_DECL (type);
9cc54940 1048
23f2660f 1049 return NULL_TREE;
9cc54940
AC
1050}
1051
1052/* Return whether TYPE has static fields. */
1053
94159ecf 1054static bool
9cc54940
AC
1055has_static_fields (const_tree type)
1056{
94159ecf
EB
1057 if (!type || !RECORD_OR_UNION_TYPE_P (type))
1058 return false;
1059
9f2cb25e 1060 for (tree fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
b854df3c 1061 if (TREE_CODE (fld) == VAR_DECL && DECL_NAME (fld))
94159ecf
EB
1062 return true;
1063
9cc54940
AC
1064 return false;
1065}
1066
1067/* Return whether TYPE corresponds to an Ada tagged type (has a dispatch
1068 table). */
1069
94159ecf 1070static bool
9cc54940
AC
1071is_tagged_type (const_tree type)
1072{
9cc54940
AC
1073 if (!type || !RECORD_OR_UNION_TYPE_P (type))
1074 return false;
1075
5aaa8fb4
NS
1076 for (tree fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
1077 if (TREE_CODE (fld) == FUNCTION_DECL && DECL_VINDEX (fld))
9cc54940
AC
1078 return true;
1079
1080 return false;
1081}
1082
94159ecf
EB
1083/* Return whether TYPE has non-trivial methods, i.e. methods that do something
1084 for the objects of TYPE. In C++, all classes have implicit special methods,
1085 e.g. constructors and destructors, but they can be trivial if the type is
1086 sufficiently simple. */
1087
1088static bool
621955cb 1089has_nontrivial_methods (tree type)
94159ecf 1090{
94159ecf
EB
1091 if (!type || !RECORD_OR_UNION_TYPE_P (type))
1092 return false;
1093
1094 /* Only C++ types can have methods. */
1095 if (!cpp_check)
1096 return false;
1097
1098 /* A non-trivial type has non-trivial special methods. */
1099 if (!cpp_check (type, IS_TRIVIAL))
1100 return true;
1101
1102 /* If there are user-defined methods, they are deemed non-trivial. */
5aaa8fb4 1103 for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
db440138 1104 if (TREE_CODE (fld) == FUNCTION_DECL && !DECL_ARTIFICIAL (fld))
94159ecf
EB
1105 return true;
1106
1107 return false;
1108}
1109
9cc54940
AC
1110/* Generate a legal Ada name from a C NAME, returning a malloc'd string.
1111 SPACE_FOUND, if not NULL, is used to indicate whether a space was found in
1112 NAME. */
1113
1114static char *
1115to_ada_name (const char *name, int *space_found)
1116{
1117 const char **names;
1118 int len = strlen (name);
1119 int j, len2 = 0;
1120 int found = false;
1121 char *s = XNEWVEC (char, len * 2 + 5);
1122 char c;
1123
1124 if (space_found)
1125 *space_found = false;
1126
1127 /* Add trailing "c_" if name is an Ada reserved word. */
1128 for (names = ada_reserved; *names; names++)
1129 if (!strcasecmp (name, *names))
1130 {
0b07a57e
AC
1131 s[len2++] = 'c';
1132 s[len2++] = '_';
9cc54940
AC
1133 found = true;
1134 break;
1135 }
1136
1137 if (!found)
1138 /* Add trailing "c_" if name is an potential case sensitive duplicate. */
1139 for (names = c_duplicates; *names; names++)
1140 if (!strcmp (name, *names))
1141 {
0b07a57e
AC
1142 s[len2++] = 'c';
1143 s[len2++] = '_';
9cc54940
AC
1144 found = true;
1145 break;
1146 }
1147
0b07a57e
AC
1148 for (j = 0; name[j] == '_'; j++)
1149 s[len2++] = 'u';
9cc54940
AC
1150
1151 if (j > 0)
0b07a57e 1152 s[len2++] = '_';
9cc54940
AC
1153 else if (*name == '.' || *name == '$')
1154 {
0b07a57e
AC
1155 s[0] = 'a';
1156 s[1] = 'n';
1157 s[2] = 'o';
1158 s[3] = 'n';
9cc54940
AC
1159 len2 = 4;
1160 j++;
1161 }
1162
1163 /* Replace unsuitable characters for Ada identifiers. */
1164
1165 for (; j < len; j++)
0b07a57e 1166 switch (name[j])
9cc54940
AC
1167 {
1168 case ' ':
1169 if (space_found)
1170 *space_found = true;
0b07a57e 1171 s[len2++] = '_';
9cc54940
AC
1172 break;
1173
1174 /* ??? missing some C++ operators. */
1175 case '=':
0b07a57e 1176 s[len2++] = '_';
9cc54940 1177
0b07a57e 1178 if (name[j + 1] == '=')
9cc54940
AC
1179 {
1180 j++;
0b07a57e
AC
1181 s[len2++] = 'e';
1182 s[len2++] = 'q';
9cc54940
AC
1183 }
1184 else
1185 {
0b07a57e
AC
1186 s[len2++] = 'a';
1187 s[len2++] = 's';
9cc54940
AC
1188 }
1189 break;
1190
1191 case '!':
0b07a57e
AC
1192 s[len2++] = '_';
1193 if (name[j + 1] == '=')
9cc54940
AC
1194 {
1195 j++;
0b07a57e
AC
1196 s[len2++] = 'n';
1197 s[len2++] = 'e';
9cc54940
AC
1198 }
1199 break;
1200
1201 case '~':
0b07a57e
AC
1202 s[len2++] = '_';
1203 s[len2++] = 't';
1204 s[len2++] = 'i';
9cc54940
AC
1205 break;
1206
1207 case '&':
1208 case '|':
1209 case '^':
0b07a57e
AC
1210 s[len2++] = '_';
1211 s[len2++] = name[j] == '&' ? 'a' : name[j] == '|' ? 'o' : 'x';
9cc54940 1212
0b07a57e 1213 if (name[j + 1] == '=')
9cc54940
AC
1214 {
1215 j++;
0b07a57e 1216 s[len2++] = 'e';
9cc54940
AC
1217 }
1218 break;
1219
1220 case '+':
1221 case '-':
1222 case '*':
1223 case '/':
1224 case '(':
1225 case '[':
0b07a57e
AC
1226 if (s[len2 - 1] != '_')
1227 s[len2++] = '_';
9cc54940 1228
0b07a57e 1229 switch (name[j + 1]) {
9cc54940
AC
1230 case '\0':
1231 j++;
0b07a57e
AC
1232 switch (name[j - 1]) {
1233 case '+': s[len2++] = 'p'; break; /* + */
1234 case '-': s[len2++] = 'm'; break; /* - */
1235 case '*': s[len2++] = 't'; break; /* * */
1236 case '/': s[len2++] = 'd'; break; /* / */
9cc54940
AC
1237 }
1238 break;
1239
1240 case '=':
1241 j++;
0b07a57e
AC
1242 switch (name[j - 1]) {
1243 case '+': s[len2++] = 'p'; break; /* += */
1244 case '-': s[len2++] = 'm'; break; /* -= */
1245 case '*': s[len2++] = 't'; break; /* *= */
1246 case '/': s[len2++] = 'd'; break; /* /= */
9cc54940 1247 }
0b07a57e 1248 s[len2++] = 'a';
9cc54940
AC
1249 break;
1250
1251 case '-': /* -- */
1252 j++;
0b07a57e
AC
1253 s[len2++] = 'm';
1254 s[len2++] = 'm';
9cc54940
AC
1255 break;
1256
1257 case '+': /* ++ */
1258 j++;
0b07a57e
AC
1259 s[len2++] = 'p';
1260 s[len2++] = 'p';
9cc54940
AC
1261 break;
1262
1263 case ')': /* () */
1264 j++;
0b07a57e
AC
1265 s[len2++] = 'o';
1266 s[len2++] = 'p';
9cc54940
AC
1267 break;
1268
1269 case ']': /* [] */
1270 j++;
0b07a57e
AC
1271 s[len2++] = 'o';
1272 s[len2++] = 'b';
9cc54940
AC
1273 break;
1274 }
1275
1276 break;
1277
1278 case '<':
1279 case '>':
0b07a57e
AC
1280 c = name[j] == '<' ? 'l' : 'g';
1281 s[len2++] = '_';
9cc54940 1282
0b07a57e 1283 switch (name[j + 1]) {
9cc54940 1284 case '\0':
0b07a57e
AC
1285 s[len2++] = c;
1286 s[len2++] = 't';
9cc54940
AC
1287 break;
1288 case '=':
1289 j++;
0b07a57e
AC
1290 s[len2++] = c;
1291 s[len2++] = 'e';
9cc54940
AC
1292 break;
1293 case '>':
1294 j++;
0b07a57e
AC
1295 s[len2++] = 's';
1296 s[len2++] = 'r';
9cc54940
AC
1297 break;
1298 case '<':
1299 j++;
0b07a57e
AC
1300 s[len2++] = 's';
1301 s[len2++] = 'l';
9cc54940
AC
1302 break;
1303 default:
1304 break;
1305 }
1306 break;
1307
1308 case '_':
0b07a57e
AC
1309 if (len2 && s[len2 - 1] == '_')
1310 s[len2++] = 'u';
9cc54940
AC
1311 /* fall through */
1312
1313 default:
0b07a57e 1314 s[len2++] = name[j];
9cc54940
AC
1315 }
1316
0b07a57e
AC
1317 if (s[len2 - 1] == '_')
1318 s[len2++] = 'u';
9cc54940 1319
0b07a57e 1320 s[len2] = '\0';
9cc54940
AC
1321
1322 return s;
1323}
1324
1e4bf85b
AC
1325/* Return true if DECL refers to a C++ class type for which a
1326 separate enclosing package has been or should be generated. */
1327
1328static bool
1329separate_class_package (tree decl)
1330{
94159ecf
EB
1331 tree type = TREE_TYPE (decl);
1332 return has_nontrivial_methods (type) || has_static_fields (type);
1e4bf85b
AC
1333}
1334
9cc54940
AC
1335static bool package_prefix = true;
1336
1337/* Dump in BUFFER the name of an identifier NODE of type TYPE, following Ada
1338 syntax. LIMITED_ACCESS indicates whether NODE can be accessed via a limited
1339 'with' clause rather than a regular 'with' clause. */
1340
1341static void
1342pp_ada_tree_identifier (pretty_printer *buffer, tree node, tree type,
1343 int limited_access)
1344{
1345 const char *name = IDENTIFIER_POINTER (node);
1346 int space_found = false;
1347 char *s = to_ada_name (name, &space_found);
1348 tree decl;
1349
1350 /* If the entity is a type and comes from another file, generate "package"
1351 prefix. */
9cc54940
AC
1352 decl = get_underlying_decl (type);
1353
1354 if (decl)
1355 {
1356 expanded_location xloc = expand_location (decl_sloc (decl, false));
1357
1358 if (xloc.file && xloc.line)
1359 {
1360 if (xloc.file != source_file_base)
1361 {
1362 switch (TREE_CODE (type))
1363 {
1364 case ENUMERAL_TYPE:
1365 case INTEGER_TYPE:
1366 case REAL_TYPE:
1367 case FIXED_POINT_TYPE:
1368 case BOOLEAN_TYPE:
1369 case REFERENCE_TYPE:
1370 case POINTER_TYPE:
1371 case ARRAY_TYPE:
1372 case RECORD_TYPE:
1373 case UNION_TYPE:
9cc54940 1374 case TYPE_DECL:
94159ecf
EB
1375 if (package_prefix)
1376 {
1377 char *s1 = get_ada_package (xloc.file);
1378 append_withs (s1, limited_access);
1379 pp_string (buffer, s1);
1380 pp_dot (buffer);
1381 free (s1);
1382 }
9cc54940
AC
1383 break;
1384 default:
1385 break;
1386 }
94159ecf
EB
1387
1388 /* Generate the additional package prefix for C++ classes. */
1389 if (separate_class_package (decl))
1390 {
1391 pp_string (buffer, "Class_");
1392 pp_string (buffer, s);
1393 pp_dot (buffer);
1394 }
1395 }
9cc54940
AC
1396 }
1397 }
1398
1399 if (space_found)
1400 if (!strcmp (s, "short_int"))
1401 pp_string (buffer, "short");
1402 else if (!strcmp (s, "short_unsigned_int"))
1403 pp_string (buffer, "unsigned_short");
1404 else if (!strcmp (s, "unsigned_int"))
1405 pp_string (buffer, "unsigned");
1406 else if (!strcmp (s, "long_int"))
1407 pp_string (buffer, "long");
1408 else if (!strcmp (s, "long_unsigned_int"))
1409 pp_string (buffer, "unsigned_long");
1410 else if (!strcmp (s, "long_long_int"))
1411 pp_string (buffer, "Long_Long_Integer");
1412 else if (!strcmp (s, "long_long_unsigned_int"))
1413 {
1414 if (package_prefix)
1415 {
1416 append_withs ("Interfaces.C.Extensions", false);
1417 pp_string (buffer, "Extensions.unsigned_long_long");
1418 }
1419 else
1420 pp_string (buffer, "unsigned_long_long");
1421 }
1422 else
1423 pp_string(buffer, s);
1424 else
1425 if (!strcmp (s, "bool"))
1426 {
1427 if (package_prefix)
1428 {
1429 append_withs ("Interfaces.C.Extensions", false);
1430 pp_string (buffer, "Extensions.bool");
1431 }
1432 else
1433 pp_string (buffer, "bool");
1434 }
1435 else
1436 pp_string(buffer, s);
1437
1438 free (s);
1439}
1440
1441/* Dump in BUFFER the assembly name of T. */
1442
1443static void
1444pp_asm_name (pretty_printer *buffer, tree t)
1445{
1446 tree name = DECL_ASSEMBLER_NAME (t);
1447 char *ada_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (name) + 1), *s;
1448 const char *ident = IDENTIFIER_POINTER (name);
1449
1450 for (s = ada_name; *ident; ident++)
1451 {
1452 if (*ident == ' ')
1453 break;
1454 else if (*ident != '*')
1455 *s++ = *ident;
1456 }
1457
1458 *s = '\0';
1459 pp_string (buffer, ada_name);
1460}
1461
1462/* Dump in BUFFER the name of a DECL node if set, following Ada syntax.
1463 LIMITED_ACCESS indicates whether NODE can be accessed via a limited
1464 'with' clause rather than a regular 'with' clause. */
1465
1466static void
1467dump_ada_decl_name (pretty_printer *buffer, tree decl, int limited_access)
1468{
1469 if (DECL_NAME (decl))
1470 pp_ada_tree_identifier (buffer, DECL_NAME (decl), decl, limited_access);
1471 else
1472 {
1473 tree type_name = TYPE_NAME (TREE_TYPE (decl));
1474
1475 if (!type_name)
1476 {
1477 pp_string (buffer, "anon");
1478 if (TREE_CODE (decl) == FIELD_DECL)
1479 pp_scalar (buffer, "%d", DECL_UID (decl));
1480 else
1481 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (decl)));
1482 }
1483 else if (TREE_CODE (type_name) == IDENTIFIER_NODE)
1484 pp_ada_tree_identifier (buffer, type_name, decl, limited_access);
1485 }
1486}
1487
f07862c7 1488/* Dump in BUFFER a name based on both T1 and T2 followed by a suffix. */
9cc54940
AC
1489
1490static void
f07862c7 1491dump_ada_double_name (pretty_printer *buffer, tree t1, tree t2)
9cc54940
AC
1492{
1493 if (DECL_NAME (t1))
1494 pp_ada_tree_identifier (buffer, DECL_NAME (t1), t1, false);
1495 else
1496 {
1497 pp_string (buffer, "anon");
1498 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t1)));
1499 }
1500
07838b13 1501 pp_underscore (buffer);
9cc54940 1502
a4e26206 1503 if (DECL_NAME (t2))
9cc54940
AC
1504 pp_ada_tree_identifier (buffer, DECL_NAME (t2), t2, false);
1505 else
1506 {
1507 pp_string (buffer, "anon");
1508 pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t2)));
1509 }
1510
f07862c7
EB
1511 switch (TREE_CODE (TREE_TYPE (t2)))
1512 {
1513 case ARRAY_TYPE:
1514 pp_string (buffer, "_array");
1515 break;
1516 case RECORD_TYPE:
1517 pp_string (buffer, "_struct");
1518 break;
1519 case UNION_TYPE:
1520 pp_string (buffer, "_union");
1521 break;
1522 default:
1523 pp_string (buffer, "_unknown");
1524 break;
1525 }
9cc54940
AC
1526}
1527
1528/* Dump in BUFFER pragma Import C/CPP on a given node T. */
1529
1530static void
1531dump_ada_import (pretty_printer *buffer, tree t)
1532{
1533 const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t));
1534 int is_stdcall = TREE_CODE (t) == FUNCTION_DECL &&
1535 lookup_attribute ("stdcall", TYPE_ATTRIBUTES (TREE_TYPE (t)));
1536
1537 if (is_stdcall)
1538 pp_string (buffer, "pragma Import (Stdcall, ");
0b07a57e 1539 else if (name[0] == '_' && name[1] == 'Z')
9cc54940
AC
1540 pp_string (buffer, "pragma Import (CPP, ");
1541 else
1542 pp_string (buffer, "pragma Import (C, ");
1543
1544 dump_ada_decl_name (buffer, t, false);
1545 pp_string (buffer, ", \"");
1546
1547 if (is_stdcall)
1548 pp_string (buffer, IDENTIFIER_POINTER (DECL_NAME (t)));
1549 else
1550 pp_asm_name (buffer, t);
1551
1552 pp_string (buffer, "\");");
1553}
1554
1555/* Check whether T and its type have different names, and append "the_"
1556 otherwise in BUFFER. */
1557
1558static void
1559check_name (pretty_printer *buffer, tree t)
1560{
1561 const char *s;
1562 tree tmp = TREE_TYPE (t);
1563
1564 while (TREE_CODE (tmp) == POINTER_TYPE && !TYPE_NAME (tmp))
1565 tmp = TREE_TYPE (tmp);
1566
1567 if (TREE_CODE (tmp) != FUNCTION_TYPE)
1568 {
1569 if (TREE_CODE (tmp) == IDENTIFIER_NODE)
1570 s = IDENTIFIER_POINTER (tmp);
1571 else if (!TYPE_NAME (tmp))
1572 s = "";
1573 else if (TREE_CODE (TYPE_NAME (tmp)) == IDENTIFIER_NODE)
1574 s = IDENTIFIER_POINTER (TYPE_NAME (tmp));
1575 else
1576 s = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (tmp)));
1577
1578 if (!strcasecmp (IDENTIFIER_POINTER (DECL_NAME (t)), s))
1579 pp_string (buffer, "the_");
1580 }
1581}
1582
1583/* Dump in BUFFER a function declaration FUNC with Ada syntax.
1584 IS_METHOD indicates whether FUNC is a C++ method.
1585 IS_CONSTRUCTOR whether FUNC is a C++ constructor.
1586 IS_DESTRUCTOR whether FUNC is a C++ destructor.
1587 SPC is the current indentation level. */
1588
1589static int
1590dump_ada_function_declaration (pretty_printer *buffer, tree func,
1591 int is_method, int is_constructor,
1592 int is_destructor, int spc)
1593{
1594 tree arg;
1595 const tree node = TREE_TYPE (func);
3d7b83b6 1596 char buf[17];
9cc54940
AC
1597 int num = 0, num_args = 0, have_args = true, have_ellipsis = false;
1598
1599 /* Compute number of arguments. */
1600 arg = TYPE_ARG_TYPES (node);
1601
1602 if (arg)
1603 {
1604 while (TREE_CHAIN (arg) && arg != error_mark_node)
1605 {
1606 num_args++;
1607 arg = TREE_CHAIN (arg);
1608 }
1609
1610 if (TREE_CODE (TREE_VALUE (arg)) != VOID_TYPE)
1611 {
1612 num_args++;
1613 have_ellipsis = true;
1614 }
1615 }
1616
1617 if (is_constructor)
1618 num_args--;
1619
1620 if (is_destructor)
1621 num_args = 1;
1622
1623 if (num_args > 2)
1624 newline_and_indent (buffer, spc + 1);
1625
1626 if (num_args > 0)
1627 {
1628 pp_space (buffer);
07838b13 1629 pp_left_paren (buffer);
9cc54940
AC
1630 }
1631
1632 if (TREE_CODE (func) == FUNCTION_DECL)
1633 arg = DECL_ARGUMENTS (func);
1634 else
1635 arg = NULL_TREE;
1636
1637 if (arg == NULL_TREE)
1638 {
1639 have_args = false;
1640 arg = TYPE_ARG_TYPES (node);
1641
1642 if (arg && TREE_CODE (TREE_VALUE (arg)) == VOID_TYPE)
1643 arg = NULL_TREE;
1644 }
1645
1646 if (is_constructor)
1647 arg = TREE_CHAIN (arg);
1648
1649 /* Print the argument names (if available) & types. */
1650
1651 for (num = 1; num <= num_args; num++)
1652 {
1653 if (have_args)
1654 {
1655 if (DECL_NAME (arg))
1656 {
1657 check_name (buffer, arg);
f4bcd9eb
EB
1658 pp_ada_tree_identifier (buffer, DECL_NAME (arg), NULL_TREE,
1659 false);
9cc54940
AC
1660 pp_string (buffer, " : ");
1661 }
1662 else
1663 {
1664 sprintf (buf, "arg%d : ", num);
1665 pp_string (buffer, buf);
1666 }
1667
94159ecf 1668 dump_generic_ada_node (buffer, TREE_TYPE (arg), node, spc, 0, true);
9cc54940
AC
1669 }
1670 else
1671 {
1672 sprintf (buf, "arg%d : ", num);
1673 pp_string (buffer, buf);
94159ecf 1674 dump_generic_ada_node (buffer, TREE_VALUE (arg), node, spc, 0, true);
9cc54940
AC
1675 }
1676
59909673
EB
1677 /* If the type is a pointer to a tagged type, we need to differentiate
1678 virtual methods from the rest (non-virtual methods, static member
1679 or regular functions) and import only them as primitive operations,
1680 because they make up the virtual table which is mirrored on the Ada
1681 side by the dispatch table. So we add 'Class to the type of every
1682 parameter that is not the first one of a method which either has a
1683 slot in the virtual table or is a constructor. */
1684 if (TREE_TYPE (arg)
1685 && POINTER_TYPE_P (TREE_TYPE (arg))
1686 && is_tagged_type (TREE_TYPE (TREE_TYPE (arg)))
1687 && !(num == 1 && is_method && (DECL_VINDEX (func) || is_constructor)))
1688 pp_string (buffer, "'Class");
9cc54940
AC
1689
1690 arg = TREE_CHAIN (arg);
1691
1692 if (num < num_args)
1693 {
07838b13 1694 pp_semicolon (buffer);
9cc54940
AC
1695
1696 if (num_args > 2)
1697 newline_and_indent (buffer, spc + INDENT_INCR);
1698 else
1699 pp_space (buffer);
1700 }
1701 }
1702
1703 if (have_ellipsis)
1704 {
1705 pp_string (buffer, " -- , ...");
1706 newline_and_indent (buffer, spc + INDENT_INCR);
1707 }
1708
1709 if (num_args > 0)
07838b13 1710 pp_right_paren (buffer);
9cc54940
AC
1711 return num_args;
1712}
1713
1714/* Dump in BUFFER all the domains associated with an array NODE,
1715 using Ada syntax. SPC is the current indentation level. */
1716
1717static void
1718dump_ada_array_domains (pretty_printer *buffer, tree node, int spc)
1719{
1720 int first = 1;
07838b13 1721 pp_left_paren (buffer);
9cc54940
AC
1722
1723 for (; TREE_CODE (node) == ARRAY_TYPE; node = TREE_TYPE (node))
1724 {
1725 tree domain = TYPE_DOMAIN (node);
1726
1727 if (domain)
1728 {
1729 tree min = TYPE_MIN_VALUE (domain);
1730 tree max = TYPE_MAX_VALUE (domain);
1731
1732 if (!first)
1733 pp_string (buffer, ", ");
1734 first = 0;
1735
1736 if (min)
94159ecf 1737 dump_generic_ada_node (buffer, min, NULL_TREE, spc, 0, true);
9cc54940
AC
1738 pp_string (buffer, " .. ");
1739
1740 /* If the upper bound is zero, gcc may generate a NULL_TREE
1741 for TYPE_MAX_VALUE rather than an integer_cst. */
1742 if (max)
94159ecf 1743 dump_generic_ada_node (buffer, max, NULL_TREE, spc, 0, true);
9cc54940
AC
1744 else
1745 pp_string (buffer, "0");
1746 }
1747 else
1748 pp_string (buffer, "size_t");
1749 }
07838b13 1750 pp_right_paren (buffer);
9cc54940
AC
1751}
1752
eff7e30c 1753/* Dump in BUFFER file:line information related to NODE. */
9cc54940
AC
1754
1755static void
1756dump_sloc (pretty_printer *buffer, tree node)
1757{
1758 expanded_location xloc;
1759
1760 xloc.file = NULL;
1761
3a65ee74 1762 if (DECL_P (node))
9cc54940
AC
1763 xloc = expand_location (DECL_SOURCE_LOCATION (node));
1764 else if (EXPR_HAS_LOCATION (node))
1765 xloc = expand_location (EXPR_LOCATION (node));
1766
1767 if (xloc.file)
1768 {
1769 pp_string (buffer, xloc.file);
137a1a27 1770 pp_colon (buffer);
9cc54940 1771 pp_decimal_int (buffer, xloc.line);
9cc54940
AC
1772 }
1773}
1774
1775/* Return true if T designates a one dimension array of "char". */
1776
1777static bool
1778is_char_array (tree t)
1779{
1780 tree tmp;
1781 int num_dim = 0;
1782
1783 /* Retrieve array's type. */
1784 tmp = t;
1785 while (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
1786 {
1787 num_dim++;
1788 tmp = TREE_TYPE (tmp);
1789 }
1790
1791 tmp = TREE_TYPE (tmp);
1792 return num_dim == 1 && TREE_CODE (tmp) == INTEGER_TYPE
a01f151f 1793 && id_equal (DECL_NAME (TYPE_NAME (tmp)), "char");
9cc54940
AC
1794}
1795
1796/* Dump in BUFFER an array type T in Ada syntax. Assume that the "type"
f07862c7
EB
1797 keyword and name have already been printed. PARENT is the parent node of T.
1798 SPC is the indentation level. */
9cc54940
AC
1799
1800static void
f07862c7 1801dump_ada_array_type (pretty_printer *buffer, tree t, tree parent, int spc)
9cc54940 1802{
f07862c7 1803 const bool char_array = is_char_array (t);
9cc54940 1804 tree tmp;
9cc54940
AC
1805
1806 /* Special case char arrays. */
1807 if (char_array)
1808 {
1809 pp_string (buffer, "Interfaces.C.char_array ");
1810 }
1811 else
1812 pp_string (buffer, "array ");
1813
1814 /* Print the dimensions. */
1815 dump_ada_array_domains (buffer, TREE_TYPE (t), spc);
1816
f07862c7 1817 /* Retrieve the element type. */
9cc54940 1818 tmp = TREE_TYPE (t);
f07862c7 1819 while (TREE_CODE (tmp) == ARRAY_TYPE)
9cc54940
AC
1820 tmp = TREE_TYPE (tmp);
1821
1822 /* Print array's type. */
1823 if (!char_array)
1824 {
1825 pp_string (buffer, " of ");
1826
f07862c7 1827 if (TREE_CODE (tmp) != POINTER_TYPE)
9cc54940
AC
1828 pp_string (buffer, "aliased ");
1829
f07862c7
EB
1830 if (TYPE_NAME (tmp) || !RECORD_OR_UNION_TYPE_P (tmp))
1831 dump_generic_ada_node (buffer, tmp, TREE_TYPE (t), spc, false, true);
1832 else
1833 dump_ada_double_name (buffer, parent, get_underlying_decl (tmp));
9cc54940
AC
1834 }
1835}
1836
1837/* Dump in BUFFER type names associated with a template, each prepended with
94159ecf
EB
1838 '_'. TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS. SPC is
1839 the indentation level. */
9cc54940
AC
1840
1841static void
94159ecf 1842dump_template_types (pretty_printer *buffer, tree types, int spc)
9cc54940
AC
1843{
1844 size_t i;
1845 size_t len = TREE_VEC_LENGTH (types);
1846
1847 for (i = 0; i < len; i++)
1848 {
1849 tree elem = TREE_VEC_ELT (types, i);
07838b13 1850 pp_underscore (buffer);
94159ecf 1851 if (!dump_generic_ada_node (buffer, elem, 0, spc, false, true))
9cc54940
AC
1852 {
1853 pp_string (buffer, "unknown");
1854 pp_scalar (buffer, "%lu", (unsigned long) TREE_HASH (elem));
1855 }
1856 }
1857}
1858
d1d879b1 1859/* Dump in BUFFER the contents of all class instantiations associated with
94159ecf 1860 a given template T. SPC is the indentation level. */
9cc54940
AC
1861
1862static int
94159ecf 1863dump_ada_template (pretty_printer *buffer, tree t, int spc)
9cc54940 1864{
83ed54d7
EB
1865 /* DECL_SIZE_UNIT is DECL_TEMPLATE_INSTANTIATIONS in this context. */
1866 tree inst = DECL_SIZE_UNIT (t);
1867 /* This emulates DECL_TEMPLATE_RESULT in this context. */
1868 struct tree_template_decl {
1869 struct tree_decl_common common;
1870 tree arguments;
1871 tree result;
1872 };
1873 tree result = ((struct tree_template_decl *) t)->result;
9cc54940
AC
1874 int num_inst = 0;
1875
f5b02f1e
EB
1876 /* Don't look at template declarations declaring something coming from
1877 another file. This can occur for template friend declarations. */
1878 if (LOCATION_FILE (decl_sloc (result, false))
1879 != LOCATION_FILE (decl_sloc (t, false)))
1880 return 0;
1881
c6a2f2d9 1882 for (; inst && inst != error_mark_node; inst = TREE_CHAIN (inst))
9cc54940
AC
1883 {
1884 tree types = TREE_PURPOSE (inst);
1885 tree instance = TREE_VALUE (inst);
1886
1887 if (TREE_VEC_LENGTH (types) == 0)
1888 break;
1889
5aaa8fb4 1890 if (!RECORD_OR_UNION_TYPE_P (instance))
9cc54940
AC
1891 break;
1892
c6a2f2d9
PMR
1893 /* We are interested in concrete template instantiations only: skip
1894 partially specialized nodes. */
a868811e 1895 if (RECORD_OR_UNION_TYPE_P (instance)
f07862c7
EB
1896 && cpp_check
1897 && cpp_check (instance, HAS_DEPENDENT_TEMPLATE_ARGS))
c6a2f2d9
PMR
1898 continue;
1899
9cc54940
AC
1900 num_inst++;
1901 INDENT (spc);
1902 pp_string (buffer, "package ");
1903 package_prefix = false;
94159ecf
EB
1904 dump_generic_ada_node (buffer, instance, t, spc, false, true);
1905 dump_template_types (buffer, types, spc);
9cc54940
AC
1906 pp_string (buffer, " is");
1907 spc += INDENT_INCR;
1908 newline_and_indent (buffer, spc);
1909
3b0c690e 1910 TREE_VISITED (get_underlying_decl (instance)) = 1;
9cc54940 1911 pp_string (buffer, "type ");
94159ecf 1912 dump_generic_ada_node (buffer, instance, t, spc, false, true);
9cc54940
AC
1913 package_prefix = true;
1914
1915 if (is_tagged_type (instance))
1916 pp_string (buffer, " is tagged limited ");
1917 else
1918 pp_string (buffer, " is limited ");
1919
94159ecf 1920 dump_generic_ada_node (buffer, instance, t, spc, false, false);
9cc54940
AC
1921 pp_newline (buffer);
1922 spc -= INDENT_INCR;
1923 newline_and_indent (buffer, spc);
1924
1925 pp_string (buffer, "end;");
1926 newline_and_indent (buffer, spc);
1927 pp_string (buffer, "use ");
1928 package_prefix = false;
94159ecf
EB
1929 dump_generic_ada_node (buffer, instance, t, spc, false, true);
1930 dump_template_types (buffer, types, spc);
9cc54940
AC
1931 package_prefix = true;
1932 pp_semicolon (buffer);
1933 pp_newline (buffer);
1934 pp_newline (buffer);
9cc54940
AC
1935 }
1936
1937 return num_inst > 0;
1938}
1939
eff7e30c
AC
1940/* Return true if NODE is a simple enum types, that can be mapped to an
1941 Ada enum type directly. */
1942
1943static bool
1944is_simple_enum (tree node)
1945{
eb1ce453 1946 HOST_WIDE_INT count = 0;
eff7e30c
AC
1947 tree value;
1948
1949 for (value = TYPE_VALUES (node); value; value = TREE_CHAIN (value))
1950 {
1951 tree int_val = TREE_VALUE (value);
1952
1953 if (TREE_CODE (int_val) != INTEGER_CST)
1954 int_val = DECL_INITIAL (int_val);
1955
9541ffee 1956 if (!tree_fits_shwi_p (int_val))
eff7e30c 1957 return false;
eb1ce453 1958 else if (tree_to_shwi (int_val) != count)
eff7e30c
AC
1959 return false;
1960
1961 count++;
1962 }
1963
1964 return true;
1965}
1966
9cc54940
AC
1967static bool bitfield_used = false;
1968
1969/* Recursively dump in BUFFER Ada declarations corresponding to NODE of type
94159ecf
EB
1970 TYPE. SPC is the indentation level. LIMITED_ACCESS indicates whether NODE
1971 can be referenced via a "limited with" clause. NAME_ONLY indicates whether
1972 we should only dump the name of NODE, instead of its full declaration. */
9cc54940
AC
1973
1974static int
94159ecf 1975dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
9cc54940
AC
1976 int limited_access, bool name_only)
1977{
1978 if (node == NULL_TREE)
1979 return 0;
1980
1981 switch (TREE_CODE (node))
1982 {
1983 case ERROR_MARK:
1984 pp_string (buffer, "<<< error >>>");
1985 return 0;
1986
1987 case IDENTIFIER_NODE:
1988 pp_ada_tree_identifier (buffer, node, type, limited_access);
1989 break;
1990
1991 case TREE_LIST:
1992 pp_string (buffer, "--- unexpected node: TREE_LIST");
1993 return 0;
1994
1995 case TREE_BINFO:
1996 dump_generic_ada_node
94159ecf 1997 (buffer, BINFO_TYPE (node), type, spc, limited_access, name_only);
f0bc3323 1998 return 0;
9cc54940
AC
1999
2000 case TREE_VEC:
2001 pp_string (buffer, "--- unexpected node: TREE_VEC");
2002 return 0;
2003
2004 case VOID_TYPE:
2005 if (package_prefix)
2006 {
2007 append_withs ("System", false);
2008 pp_string (buffer, "System.Address");
2009 }
2010 else
2011 pp_string (buffer, "address");
2012 break;
2013
2014 case VECTOR_TYPE:
2015 pp_string (buffer, "<vector>");
2016 break;
2017
2018 case COMPLEX_TYPE:
2019 pp_string (buffer, "<complex>");
2020 break;
2021
2022 case ENUMERAL_TYPE:
2023 if (name_only)
f07862c7 2024 dump_generic_ada_node (buffer, TYPE_NAME (node), node, spc, 0, true);
9cc54940
AC
2025 else
2026 {
eff7e30c 2027 tree value = TYPE_VALUES (node);
9cc54940 2028
eff7e30c 2029 if (is_simple_enum (node))
9cc54940 2030 {
eff7e30c
AC
2031 bool first = true;
2032 spc += INDENT_INCR;
2033 newline_and_indent (buffer, spc - 1);
137a1a27 2034 pp_left_paren (buffer);
eff7e30c
AC
2035 for (; value; value = TREE_CHAIN (value))
2036 {
2037 if (first)
2038 first = false;
2039 else
2040 {
137a1a27 2041 pp_comma (buffer);
eff7e30c
AC
2042 newline_and_indent (buffer, spc);
2043 }
9cc54940 2044
eff7e30c
AC
2045 pp_ada_tree_identifier
2046 (buffer, TREE_PURPOSE (value), node, false);
2047 }
2048 pp_string (buffer, ");");
2049 spc -= INDENT_INCR;
2050 newline_and_indent (buffer, spc);
2051 pp_string (buffer, "pragma Convention (C, ");
9cc54940
AC
2052 dump_generic_ada_node
2053 (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
94159ecf 2054 spc, 0, true);
137a1a27 2055 pp_right_paren (buffer);
eff7e30c
AC
2056 }
2057 else
2058 {
942047f2
EB
2059 if (TYPE_UNSIGNED (node))
2060 pp_string (buffer, "unsigned");
2061 else
2062 pp_string (buffer, "int");
eff7e30c
AC
2063 for (; value; value = TREE_CHAIN (value))
2064 {
2065 pp_semicolon (buffer);
2066 newline_and_indent (buffer, spc);
9cc54940 2067
eff7e30c
AC
2068 pp_ada_tree_identifier
2069 (buffer, TREE_PURPOSE (value), node, false);
2070 pp_string (buffer, " : constant ");
2071
2072 dump_generic_ada_node
2073 (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
94159ecf 2074 spc, 0, true);
eff7e30c
AC
2075
2076 pp_string (buffer, " := ");
2077 dump_generic_ada_node
2078 (buffer,
2079 TREE_CODE (TREE_VALUE (value)) == INTEGER_CST ?
2080 TREE_VALUE (value) : DECL_INITIAL (TREE_VALUE (value)),
94159ecf 2081 node, spc, false, true);
eff7e30c 2082 }
9cc54940
AC
2083 }
2084 }
2085 break;
2086
2087 case INTEGER_TYPE:
2088 case REAL_TYPE:
2089 case FIXED_POINT_TYPE:
2090 case BOOLEAN_TYPE:
2091 {
2092 enum tree_code_class tclass;
2093
2094 tclass = TREE_CODE_CLASS (TREE_CODE (node));
2095
2096 if (tclass == tcc_declaration)
2097 {
2098 if (DECL_NAME (node))
2099 pp_ada_tree_identifier
f4bcd9eb 2100 (buffer, DECL_NAME (node), NULL_TREE, limited_access);
9cc54940
AC
2101 else
2102 pp_string (buffer, "<unnamed type decl>");
2103 }
2104 else if (tclass == tcc_type)
2105 {
2106 if (TYPE_NAME (node))
2107 {
2108 if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
2109 pp_ada_tree_identifier (buffer, TYPE_NAME (node),
2110 node, limited_access);
2111 else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
2112 && DECL_NAME (TYPE_NAME (node)))
2113 dump_ada_decl_name (buffer, TYPE_NAME (node), limited_access);
2114 else
2115 pp_string (buffer, "<unnamed type>");
2116 }
2117 else if (TREE_CODE (node) == INTEGER_TYPE)
2118 {
2119 append_withs ("Interfaces.C.Extensions", false);
2120 bitfield_used = true;
2121
2122 if (TYPE_PRECISION (node) == 1)
2123 pp_string (buffer, "Extensions.Unsigned_1");
2124 else
2125 {
2126 pp_string (buffer, (TYPE_UNSIGNED (node)
2127 ? "Extensions.Unsigned_"
2128 : "Extensions.Signed_"));
2129 pp_decimal_int (buffer, TYPE_PRECISION (node));
2130 }
2131 }
2132 else
2133 pp_string (buffer, "<unnamed type>");
2134 }
2135 break;
2136 }
2137
2138 case POINTER_TYPE:
2139 case REFERENCE_TYPE:
c583af79
AC
2140 if (name_only && TYPE_NAME (node))
2141 dump_generic_ada_node
94159ecf 2142 (buffer, TYPE_NAME (node), node, spc, limited_access, true);
c583af79
AC
2143
2144 else if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
9cc54940
AC
2145 {
2146 tree fnode = TREE_TYPE (node);
2147 bool is_function;
9cc54940
AC
2148
2149 if (VOID_TYPE_P (TREE_TYPE (fnode)))
2150 {
2151 is_function = false;
2152 pp_string (buffer, "access procedure");
2153 }
2154 else
2155 {
2156 is_function = true;
2157 pp_string (buffer, "access function");
2158 }
2159
9cc54940
AC
2160 dump_ada_function_declaration
2161 (buffer, node, false, false, false, spc + INDENT_INCR);
9cc54940
AC
2162
2163 if (is_function)
2164 {
2165 pp_string (buffer, " return ");
2166 dump_generic_ada_node
94159ecf 2167 (buffer, TREE_TYPE (fnode), type, spc, 0, true);
9cc54940 2168 }
c583af79
AC
2169
2170 /* If we are dumping the full type, it means we are part of a
2171 type definition and need also a Convention C pragma. */
2172 if (!name_only)
2173 {
2174 pp_semicolon (buffer);
2175 newline_and_indent (buffer, spc);
2176 pp_string (buffer, "pragma Convention (C, ");
2177 dump_generic_ada_node
94159ecf 2178 (buffer, type, 0, spc, false, true);
137a1a27 2179 pp_right_paren (buffer);
c583af79 2180 }
9cc54940
AC
2181 }
2182 else
2183 {
2184 int is_access = false;
2185 unsigned int quals = TYPE_QUALS (TREE_TYPE (node));
2186
c583af79 2187 if (VOID_TYPE_P (TREE_TYPE (node)))
9cc54940
AC
2188 {
2189 if (!name_only)
2190 pp_string (buffer, "new ");
2191 if (package_prefix)
2192 {
2193 append_withs ("System", false);
2194 pp_string (buffer, "System.Address");
2195 }
2196 else
2197 pp_string (buffer, "address");
2198 }
2199 else
2200 {
2201 if (TREE_CODE (node) == POINTER_TYPE
2202 && TREE_CODE (TREE_TYPE (node)) == INTEGER_TYPE
2203 && !strcmp
2204 (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME
2205 (TREE_TYPE (node)))), "char"))
2206 {
2207 if (!name_only)
2208 pp_string (buffer, "new ");
2209
2210 if (package_prefix)
2211 {
2212 pp_string (buffer, "Interfaces.C.Strings.chars_ptr");
2213 append_withs ("Interfaces.C.Strings", false);
2214 }
2215 else
2216 pp_string (buffer, "chars_ptr");
2217 }
2218 else
2219 {
3b0c690e 2220 tree type_name = TYPE_NAME (TREE_TYPE (node));
23f2660f
EB
2221 tree decl = get_underlying_decl (TREE_TYPE (node));
2222 tree enclosing_decl = get_underlying_decl (type);
9cc54940 2223
23f2660f
EB
2224 /* For now, handle access-to-access, access-to-empty-struct
2225 or access-to-incomplete as opaque system.address. */
9cc54940 2226 if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE
9cc54940 2227 || (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
23f2660f
EB
2228 && !TYPE_FIELDS (TREE_TYPE (node)))
2229 || !decl
2230 || (!enclosing_decl
2231 && !TREE_VISITED (decl)
2232 && DECL_SOURCE_FILE (decl) == source_file_base)
2233 || (enclosing_decl
2234 && !TREE_VISITED (decl)
2235 && DECL_SOURCE_FILE (decl)
2236 == DECL_SOURCE_FILE (enclosing_decl)
2237 && decl_sloc (decl, true)
2238 > decl_sloc (enclosing_decl, true)))
9cc54940
AC
2239 {
2240 if (package_prefix)
2241 {
2242 append_withs ("System", false);
2243 if (!name_only)
2244 pp_string (buffer, "new ");
2245 pp_string (buffer, "System.Address");
2246 }
2247 else
2248 pp_string (buffer, "address");
2249 return spc;
2250 }
2251
2252 if (!package_prefix)
2253 pp_string (buffer, "access");
2254 else if (AGGREGATE_TYPE_P (TREE_TYPE (node)))
2255 {
2256 if (!type || TREE_CODE (type) != FUNCTION_DECL)
2257 {
2258 pp_string (buffer, "access ");
2259 is_access = true;
2260
2261 if (quals & TYPE_QUAL_CONST)
2262 pp_string (buffer, "constant ");
2263 else if (!name_only)
2264 pp_string (buffer, "all ");
2265 }
2266 else if (quals & TYPE_QUAL_CONST)
2267 pp_string (buffer, "in ");
9cc54940
AC
2268 else
2269 {
2270 is_access = true;
2271 pp_string (buffer, "access ");
2272 /* ??? should be configurable: access or in out. */
2273 }
2274 }
2275 else
2276 {
2277 is_access = true;
2278 pp_string (buffer, "access ");
2279
2280 if (!name_only)
2281 pp_string (buffer, "all ");
2282 }
2283
f07862c7 2284 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node)) && type_name)
23f2660f
EB
2285 dump_generic_ada_node (buffer, type_name, TREE_TYPE (node),
2286 spc, is_access, true);
9cc54940 2287 else
23f2660f
EB
2288 dump_generic_ada_node (buffer, TREE_TYPE (node),
2289 TREE_TYPE (node), spc, 0, true);
9cc54940
AC
2290 }
2291 }
2292 }
2293 break;
2294
2295 case ARRAY_TYPE:
2296 if (name_only)
2297 dump_generic_ada_node
94159ecf 2298 (buffer, TYPE_NAME (node), node, spc, limited_access, true);
9cc54940 2299 else
f07862c7 2300 dump_ada_array_type (buffer, node, type, spc);
9cc54940
AC
2301 break;
2302
2303 case RECORD_TYPE:
2304 case UNION_TYPE:
9cc54940
AC
2305 if (name_only)
2306 {
2307 if (TYPE_NAME (node))
2308 dump_generic_ada_node
94159ecf 2309 (buffer, TYPE_NAME (node), node, spc, limited_access, true);
9cc54940
AC
2310 else
2311 {
2312 pp_string (buffer, "anon_");
2313 pp_scalar (buffer, "%d", TYPE_UID (node));
2314 }
2315 }
2316 else
94159ecf 2317 print_ada_struct_decl (buffer, node, type, spc, true);
9cc54940
AC
2318 break;
2319
2320 case INTEGER_CST:
909881cb
EB
2321 /* We treat the upper half of the sizetype range as negative. This
2322 is consistent with the internal treatment and makes it possible
2323 to generate the (0 .. -1) range for flexible array members. */
2324 if (TREE_TYPE (node) == sizetype)
2325 node = fold_convert (ssizetype, node);
9541ffee 2326 if (tree_fits_shwi_p (node))
eb1ce453 2327 pp_wide_integer (buffer, tree_to_shwi (node));
cc269bb6 2328 else if (tree_fits_uhwi_p (node))
eb1ce453 2329 pp_unsigned_wide_integer (buffer, tree_to_uhwi (node));
909881cb 2330 else
9cc54940 2331 {
807e902e
KZ
2332 wide_int val = node;
2333 int i;
2334 if (wi::neg_p (val))
9cc54940 2335 {
07838b13 2336 pp_minus (buffer);
807e902e 2337 val = -val;
9cc54940
AC
2338 }
2339 sprintf (pp_buffer (buffer)->digit_buffer,
807e902e
KZ
2340 "16#%" HOST_WIDE_INT_PRINT "x",
2341 val.elt (val.get_len () - 1));
2342 for (i = val.get_len () - 2; i >= 0; i--)
2343 sprintf (pp_buffer (buffer)->digit_buffer,
2344 HOST_WIDE_INT_PRINT_PADDED_HEX, val.elt (i));
9cc54940
AC
2345 pp_string (buffer, pp_buffer (buffer)->digit_buffer);
2346 }
9cc54940
AC
2347 break;
2348
2349 case REAL_CST:
2350 case FIXED_CST:
2351 case COMPLEX_CST:
2352 case STRING_CST:
2353 case VECTOR_CST:
2354 return 0;
2355
2356 case FUNCTION_DECL:
2357 case CONST_DECL:
2358 dump_ada_decl_name (buffer, node, limited_access);
2359 break;
2360
2361 case TYPE_DECL:
2362 if (DECL_IS_BUILTIN (node))
2363 {
2364 /* Don't print the declaration of built-in types. */
2365
2366 if (name_only)
2367 {
2368 /* If we're in the middle of a declaration, defaults to
2369 System.Address. */
2370 if (package_prefix)
2371 {
2372 append_withs ("System", false);
2373 pp_string (buffer, "System.Address");
2374 }
2375 else
2376 pp_string (buffer, "address");
2377 }
2378 break;
2379 }
2380
2381 if (name_only)
2382 dump_ada_decl_name (buffer, node, limited_access);
2383 else
2384 {
2385 if (is_tagged_type (TREE_TYPE (node)))
2386 {
9cc54940
AC
2387 int first = 1;
2388
2389 /* Look for ancestors. */
9f2cb25e
EB
2390 for (tree fld = TYPE_FIELDS (TREE_TYPE (node));
2391 fld;
2392 fld = TREE_CHAIN (fld))
9cc54940 2393 {
9f2cb25e 2394 if (!DECL_NAME (fld) && is_tagged_type (TREE_TYPE (fld)))
9cc54940
AC
2395 {
2396 if (first)
2397 {
2398 pp_string (buffer, "limited new ");
2399 first = 0;
2400 }
2401 else
2402 pp_string (buffer, " and ");
2403
9f2cb25e
EB
2404 dump_ada_decl_name (buffer, TYPE_NAME (TREE_TYPE (fld)),
2405 false);
9cc54940
AC
2406 }
2407 }
2408
2409 pp_string (buffer, first ? "tagged limited " : " with ");
2410 }
94159ecf 2411 else if (has_nontrivial_methods (TREE_TYPE (node)))
9cc54940
AC
2412 pp_string (buffer, "limited ");
2413
2414 dump_generic_ada_node
94159ecf 2415 (buffer, TREE_TYPE (node), type, spc, false, false);
9cc54940
AC
2416 }
2417 break;
2418
2419 case VAR_DECL:
2420 case PARM_DECL:
2421 case FIELD_DECL:
2422 case NAMESPACE_DECL:
2423 dump_ada_decl_name (buffer, node, false);
2424 break;
2425
2426 default:
2427 /* Ignore other nodes (e.g. expressions). */
2428 return 0;
2429 }
2430
2431 return 1;
2432}
2433
94159ecf 2434/* Dump in BUFFER NODE's methods. SPC is the indentation level. Return 1 if
59909673 2435 methods were printed, 0 otherwise. */
9cc54940 2436
94159ecf
EB
2437static int
2438print_ada_methods (pretty_printer *buffer, tree node, int spc)
9cc54940 2439{
94159ecf
EB
2440 if (!has_nontrivial_methods (node))
2441 return 0;
9cc54940 2442
94159ecf
EB
2443 pp_semicolon (buffer);
2444
5aaa8fb4
NS
2445 int res = 1;
2446 for (tree fld = TYPE_FIELDS (node); fld; fld = DECL_CHAIN (fld))
db440138 2447 if (TREE_CODE (fld) == FUNCTION_DECL)
5aaa8fb4
NS
2448 {
2449 if (res)
2450 {
2451 pp_newline (buffer);
2452 pp_newline (buffer);
2453 }
2454
2455 res = print_ada_declaration (buffer, fld, node, spc);
2456 }
2a877204 2457
94159ecf 2458 return 1;
9cc54940
AC
2459}
2460
f07862c7
EB
2461static void dump_nested_type (pretty_printer *, tree, tree, tree, int);
2462
9cc54940 2463/* Dump in BUFFER anonymous types nested inside T's definition.
3b0c690e
AC
2464 PARENT is the parent node of T.
2465 FORWARD indicates whether a forward declaration of T should be generated.
f07862c7
EB
2466 SPC is the indentation level.
2467
2468 In C anonymous nested tagged types have no name whereas in C++ they have
2469 one. In C their TYPE_DECL is at top level whereas in C++ it is nested.
2470 In both languages untagged types (pointers and arrays) have no name.
2471 In C++ the nested TYPE_DECLs can come after their associated FIELD_DECL.
2472
2473 Therefore, in order to have a common processing for both languages, we
2474 disregard anonymous TYPE_DECLs at top level and here we make a first
2475 pass on the nested TYPE_DECLs and a second pass on the unnamed types. */
9cc54940
AC
2476
2477static void
3b0c690e 2478dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward,
94159ecf 2479 int spc)
9cc54940 2480{
f07862c7 2481 tree type, field;
9cc54940
AC
2482
2483 /* Avoid recursing over the same tree. */
2484 if (TREE_VISITED (t))
2485 return;
2486
f07862c7
EB
2487 /* Find possible anonymous pointers/arrays/structs/unions recursively. */
2488 type = TREE_TYPE (t);
2489 if (type == NULL_TREE)
9cc54940
AC
2490 return;
2491
3b0c690e
AC
2492 if (forward)
2493 {
2494 pp_string (buffer, "type ");
94159ecf 2495 dump_generic_ada_node (buffer, t, t, spc, false, true);
3b0c690e
AC
2496 pp_semicolon (buffer);
2497 newline_and_indent (buffer, spc);
2498 TREE_VISITED (t) = 1;
2499 }
2500
f07862c7
EB
2501 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
2502 if (TREE_CODE (field) == TYPE_DECL
2503 && DECL_NAME (field) != DECL_NAME (t)
2504 && TYPE_NAME (TREE_TYPE (field)) != TYPE_NAME (type))
2505 dump_nested_type (buffer, field, t, parent, spc);
9cc54940 2506
f07862c7 2507 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
9f2cb25e 2508 if (TREE_CODE (field) == FIELD_DECL && !TYPE_NAME (TREE_TYPE (field)))
f07862c7 2509 dump_nested_type (buffer, field, t, parent, spc);
9cc54940 2510
f07862c7
EB
2511 TREE_VISITED (t) = 1;
2512}
9cc54940 2513
f07862c7
EB
2514/* Dump in BUFFER the anonymous type of FIELD inside T.
2515 PARENT is the parent node of T.
2516 FORWARD indicates whether a forward declaration of T should be generated.
2517 SPC is the indentation level. */
9cc54940 2518
f07862c7
EB
2519static void
2520dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent,
2521 int spc)
2522{
2523 tree field_type = TREE_TYPE (field);
2524 tree decl, tmp;
9cc54940 2525
f07862c7
EB
2526 switch (TREE_CODE (field_type))
2527 {
2528 case POINTER_TYPE:
2529 tmp = TREE_TYPE (field_type);
2530
2531 if (TREE_CODE (tmp) == FUNCTION_TYPE)
2532 for (tmp = TREE_TYPE (tmp);
2533 tmp && TREE_CODE (tmp) == POINTER_TYPE;
2534 tmp = TREE_TYPE (tmp))
2535 ;
2536
2537 decl = get_underlying_decl (tmp);
2538 if (decl
f07862c7
EB
2539 && !DECL_IS_BUILTIN (decl)
2540 && (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
23f2660f
EB
2541 || TYPE_FIELDS (TREE_TYPE (decl)))
2542 && !TREE_VISITED (decl)
2543 && DECL_SOURCE_FILE (decl) == DECL_SOURCE_FILE (t)
2544 && decl_sloc (decl, true) > decl_sloc (t, true))
f07862c7
EB
2545 {
2546 /* Generate forward declaration. */
2547 pp_string (buffer, "type ");
2548 dump_generic_ada_node (buffer, decl, 0, spc, false, true);
2549 pp_semicolon (buffer);
2550 newline_and_indent (buffer, spc);
2551 TREE_VISITED (decl) = 1;
2552 }
2553 break;
9cc54940 2554
f07862c7
EB
2555 case ARRAY_TYPE:
2556 tmp = TREE_TYPE (field_type);
2557 while (TREE_CODE (tmp) == ARRAY_TYPE)
2558 tmp = TREE_TYPE (tmp);
2559 decl = get_underlying_decl (tmp);
23f2660f 2560 if (decl && !DECL_NAME (decl) && !TREE_VISITED (decl))
f07862c7
EB
2561 {
2562 /* Generate full declaration. */
2563 dump_nested_type (buffer, decl, t, parent, spc);
2564 TREE_VISITED (decl) = 1;
2565 }
9cc54940 2566
f07862c7
EB
2567 /* Special case char arrays. */
2568 if (is_char_array (field))
2569 pp_string (buffer, "sub");
9cc54940 2570
f07862c7
EB
2571 pp_string (buffer, "type ");
2572 dump_ada_double_name (buffer, parent, field);
2573 pp_string (buffer, " is ");
2574 dump_ada_array_type (buffer, field, parent, spc);
2575 pp_semicolon (buffer);
2576 newline_and_indent (buffer, spc);
2577 break;
9cc54940 2578
f07862c7
EB
2579 case RECORD_TYPE:
2580 case UNION_TYPE:
2581 if (TYPE_NAME (TREE_TYPE (t)) && !TREE_VISITED (t))
2582 {
2583 pp_string (buffer, "type ");
2584 dump_generic_ada_node (buffer, t, parent, spc, false, true);
2585 pp_semicolon (buffer);
2586 newline_and_indent (buffer, spc);
2587 }
9cc54940 2588
f07862c7
EB
2589 TREE_VISITED (t) = 1;
2590 dump_nested_types (buffer, field, t, false, spc);
9cc54940 2591
f07862c7 2592 pp_string (buffer, "type ");
9cc54940 2593
f07862c7
EB
2594 if (TYPE_NAME (field_type))
2595 {
2596 dump_generic_ada_node (buffer, field_type, 0, spc, false, true);
2597 if (TREE_CODE (field_type) == UNION_TYPE)
2598 pp_string (buffer, " (discr : unsigned := 0)");
2599 pp_string (buffer, " is ");
2600 print_ada_struct_decl (buffer, field_type, t, spc, false);
9cc54940 2601
f07862c7
EB
2602 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2603 dump_generic_ada_node (buffer, field_type, 0, spc, false, true);
2604 pp_string (buffer, ");");
2605 newline_and_indent (buffer, spc);
9cc54940 2606
f07862c7
EB
2607 if (TREE_CODE (field_type) == UNION_TYPE)
2608 {
2609 pp_string (buffer, "pragma Unchecked_Union (");
2610 dump_generic_ada_node (buffer, field_type, 0, spc, false, true);
2611 pp_string (buffer, ");");
2612 }
2613 }
2614 else
2615 {
2616 dump_ada_double_name (buffer, parent, field);
2617 if (TREE_CODE (field_type) == UNION_TYPE)
2618 pp_string (buffer, " (discr : unsigned := 0)");
2619 pp_string (buffer, " is ");
2620 print_ada_struct_decl (buffer, field_type, t, spc, false);
9cc54940 2621
f07862c7
EB
2622 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
2623 dump_ada_double_name (buffer, parent, field);
2624 pp_string (buffer, ");");
2625 newline_and_indent (buffer, spc);
9cc54940 2626
f07862c7
EB
2627 if (TREE_CODE (field_type) == UNION_TYPE)
2628 {
2629 pp_string (buffer, "pragma Unchecked_Union (");
2630 dump_ada_double_name (buffer, parent, field);
2631 pp_string (buffer, ");");
9cc54940
AC
2632 }
2633 }
3b0c690e 2634
f07862c7
EB
2635 default:
2636 break;
2637 }
9cc54940
AC
2638}
2639
b854df3c 2640/* Dump in BUFFER constructor spec corresponding to T for TYPE. */
f2aa696b
EB
2641
2642static void
b854df3c 2643print_constructor (pretty_printer *buffer, tree t, tree type)
f2aa696b 2644{
b854df3c 2645 tree decl_name = DECL_NAME (TYPE_NAME (type));
f2aa696b
EB
2646
2647 pp_string (buffer, "New_");
2648 pp_ada_tree_identifier (buffer, decl_name, t, false);
2649}
2650
9cc54940
AC
2651/* Dump in BUFFER destructor spec corresponding to T. */
2652
2653static void
b854df3c 2654print_destructor (pretty_printer *buffer, tree t, tree type)
9cc54940 2655{
b854df3c 2656 tree decl_name = DECL_NAME (TYPE_NAME (type));
9cc54940 2657
0d2489f4
EB
2658 pp_string (buffer, "Delete_");
2659 pp_ada_tree_identifier (buffer, decl_name, t, false);
9cc54940
AC
2660}
2661
2662/* Return the name of type T. */
2663
2664static const char *
2665type_name (tree t)
2666{
2667 tree n = TYPE_NAME (t);
2668
2669 if (TREE_CODE (n) == IDENTIFIER_NODE)
2670 return IDENTIFIER_POINTER (n);
2671 else
2672 return IDENTIFIER_POINTER (DECL_NAME (n));
2673}
2674
2675/* Print in BUFFER the declaration of a variable T of type TYPE in Ada syntax.
94159ecf
EB
2676 SPC is the indentation level. Return 1 if a declaration was printed,
2677 0 otherwise. */
9cc54940
AC
2678
2679static int
94159ecf 2680print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
9cc54940
AC
2681{
2682 int is_var = 0, need_indent = 0;
2683 int is_class = false;
2684 tree name = TYPE_NAME (TREE_TYPE (t));
2685 tree decl_name = DECL_NAME (t);
9cc54940
AC
2686 tree orig = NULL_TREE;
2687
2688 if (cpp_check && cpp_check (t, IS_TEMPLATE))
94159ecf 2689 return dump_ada_template (buffer, t, spc);
9cc54940
AC
2690
2691 if (TREE_CODE (t) == CONST_DECL && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
2692 /* Skip enumeral values: will be handled as part of the type itself. */
2693 return 0;
2694
2695 if (TREE_CODE (t) == TYPE_DECL)
2696 {
2697 orig = DECL_ORIGINAL_TYPE (t);
2698
2699 if (orig && TYPE_STUB_DECL (orig))
2700 {
3b0c690e
AC
2701 tree stub = TYPE_STUB_DECL (orig);
2702 tree typ = TREE_TYPE (stub);
9cc54940
AC
2703
2704 if (TYPE_NAME (typ))
2705 {
2706 /* If types have same representation, and same name (ignoring
2707 casing), then ignore the second type. */
2708 if (type_name (typ) == type_name (TREE_TYPE (t))
2709 || !strcasecmp (type_name (typ), type_name (TREE_TYPE (t))))
23f2660f
EB
2710 {
2711 TREE_VISITED (t) = 1;
2712 return 0;
2713 }
9cc54940
AC
2714
2715 INDENT (spc);
2716
2717 if (RECORD_OR_UNION_TYPE_P (typ) && !TYPE_FIELDS (typ))
2718 {
2719 pp_string (buffer, "-- skipped empty struct ");
94159ecf 2720 dump_generic_ada_node (buffer, t, type, spc, false, true);
9cc54940
AC
2721 }
2722 else
2723 {
4be719cd 2724 if (RECORD_OR_UNION_TYPE_P (typ)
3b0c690e 2725 && DECL_SOURCE_FILE (stub) == source_file_base)
94159ecf 2726 dump_nested_types (buffer, stub, stub, true, spc);
3b0c690e 2727
9cc54940 2728 pp_string (buffer, "subtype ");
94159ecf 2729 dump_generic_ada_node (buffer, t, type, spc, false, true);
9cc54940 2730 pp_string (buffer, " is ");
94159ecf 2731 dump_generic_ada_node (buffer, typ, type, spc, false, true);
4be719cd
EB
2732 pp_string (buffer, "; -- ");
2733 dump_sloc (buffer, t);
9cc54940 2734 }
23f2660f
EB
2735
2736 TREE_VISITED (t) = 1;
9cc54940
AC
2737 return 1;
2738 }
2739 }
2740
2741 /* Skip unnamed or anonymous structs/unions/enum types. */
f07862c7
EB
2742 if (!orig && !decl_name && !name
2743 && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))
2744 || TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE))
2745 return 0;
9cc54940 2746
f07862c7 2747 /* Skip anonymous enum types (duplicates of real types). */
9cc54940
AC
2748 if (!orig
2749 && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE
2750 && decl_name
2751 && (*IDENTIFIER_POINTER (decl_name) == '.'
2752 || *IDENTIFIER_POINTER (decl_name) == '$'))
9cc54940
AC
2753 return 0;
2754
2755 INDENT (spc);
2756
2757 switch (TREE_CODE (TREE_TYPE (t)))
2758 {
2759 case RECORD_TYPE:
2760 case UNION_TYPE:
9cc54940
AC
2761 /* Skip empty structs (typically forward references to real
2762 structs). */
2763 if (!TYPE_FIELDS (TREE_TYPE (t)))
2764 {
2765 pp_string (buffer, "-- skipped empty struct ");
94159ecf 2766 dump_generic_ada_node (buffer, t, type, spc, false, true);
9cc54940
AC
2767 return 1;
2768 }
2769
2770 if (decl_name
2771 && (*IDENTIFIER_POINTER (decl_name) == '.'
2772 || *IDENTIFIER_POINTER (decl_name) == '$'))
2773 {
2774 pp_string (buffer, "-- skipped anonymous struct ");
94159ecf 2775 dump_generic_ada_node (buffer, t, type, spc, false, true);
3b0c690e 2776 TREE_VISITED (t) = 1;
9cc54940
AC
2777 return 1;
2778 }
2779
2780 if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2781 pp_string (buffer, "subtype ");
2782 else
2783 {
94159ecf 2784 dump_nested_types (buffer, t, t, false, spc);
9cc54940 2785
1e4bf85b 2786 if (separate_class_package (t))
9cc54940
AC
2787 {
2788 is_class = true;
2789 pp_string (buffer, "package Class_");
94159ecf 2790 dump_generic_ada_node (buffer, t, type, spc, false, true);
9cc54940
AC
2791 pp_string (buffer, " is");
2792 spc += INDENT_INCR;
2793 newline_and_indent (buffer, spc);
2794 }
2795
2796 pp_string (buffer, "type ");
2797 }
2798 break;
2799
2800 case ARRAY_TYPE:
2801 case POINTER_TYPE:
2802 case REFERENCE_TYPE:
2803 if ((orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2804 || is_char_array (t))
2805 pp_string (buffer, "subtype ");
2806 else
2807 pp_string (buffer, "type ");
2808 break;
2809
2810 case FUNCTION_TYPE:
2811 pp_string (buffer, "-- skipped function type ");
94159ecf 2812 dump_generic_ada_node (buffer, t, type, spc, false, true);
9cc54940 2813 return 1;
9cc54940 2814
eff7e30c
AC
2815 case ENUMERAL_TYPE:
2816 if ((orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2817 || !is_simple_enum (TREE_TYPE (t)))
2818 pp_string (buffer, "subtype ");
2819 else
2820 pp_string (buffer, "type ");
2821 break;
2822
9cc54940
AC
2823 default:
2824 pp_string (buffer, "subtype ");
2825 }
3b0c690e 2826 TREE_VISITED (t) = 1;
9cc54940
AC
2827 }
2828 else
2829 {
0ae9bd27 2830 if (VAR_P (t)
9cc54940
AC
2831 && decl_name
2832 && *IDENTIFIER_POINTER (decl_name) == '_')
2833 return 0;
2834
2835 need_indent = 1;
2836 }
2837
2838 /* Print the type and name. */
2839 if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
2840 {
2841 if (need_indent)
2842 INDENT (spc);
2843
2844 /* Print variable's name. */
94159ecf 2845 dump_generic_ada_node (buffer, t, type, spc, false, true);
9cc54940
AC
2846
2847 if (TREE_CODE (t) == TYPE_DECL)
2848 {
2849 pp_string (buffer, " is ");
2850
2851 if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
2852 dump_generic_ada_node
94159ecf 2853 (buffer, TYPE_NAME (orig), type, spc, false, true);
9cc54940 2854 else
f07862c7 2855 dump_ada_array_type (buffer, t, type, spc);
9cc54940
AC
2856 }
2857 else
2858 {
2859 tree tmp = TYPE_NAME (TREE_TYPE (t));
2860
2861 if (spc == INDENT_INCR || TREE_STATIC (t))
2862 is_var = 1;
2863
2864 pp_string (buffer, " : ");
2865
f07862c7
EB
2866 if (TREE_CODE (TREE_TYPE (TREE_TYPE (t))) != POINTER_TYPE)
2867 pp_string (buffer, "aliased ");
9cc54940 2868
f07862c7
EB
2869 if (tmp)
2870 dump_generic_ada_node (buffer, tmp, type, spc, false, true);
2871 else if (type)
2872 dump_ada_double_name (buffer, type, t);
9cc54940 2873 else
f07862c7 2874 dump_ada_array_type (buffer, t, type, spc);
9cc54940
AC
2875 }
2876 }
2877 else if (TREE_CODE (t) == FUNCTION_DECL)
2878 {
f2aa696b 2879 bool is_function, is_abstract_class = false;
94159ecf 2880 bool is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
9cc54940 2881 tree decl_name = DECL_NAME (t);
9cc54940
AC
2882 bool is_abstract = false;
2883 bool is_constructor = false;
2884 bool is_destructor = false;
2885 bool is_copy_constructor = false;
2a7fb83f 2886 bool is_move_constructor = false;
9cc54940
AC
2887
2888 if (!decl_name)
2889 return 0;
2890
2891 if (cpp_check)
2892 {
2893 is_abstract = cpp_check (t, IS_ABSTRACT);
2894 is_constructor = cpp_check (t, IS_CONSTRUCTOR);
2895 is_destructor = cpp_check (t, IS_DESTRUCTOR);
2896 is_copy_constructor = cpp_check (t, IS_COPY_CONSTRUCTOR);
2a7fb83f 2897 is_move_constructor = cpp_check (t, IS_MOVE_CONSTRUCTOR);
9cc54940
AC
2898 }
2899
2a7fb83f
EB
2900 /* Skip copy constructors and C++11 move constructors: some are internal
2901 only and those that are not cannot be called easily from Ada. */
2902 if (is_copy_constructor || is_move_constructor)
9cc54940
AC
2903 return 0;
2904
f2aa696b 2905 if (is_constructor || is_destructor)
9cc54940 2906 {
bb49ee66
EB
2907 /* ??? Skip implicit constructors/destructors for now. */
2908 if (DECL_ARTIFICIAL (t))
a9dcd529
EB
2909 return 0;
2910
f2aa696b 2911 /* Only consider constructors/destructors for complete objects. */
b854df3c
EB
2912 if (strncmp (IDENTIFIER_POINTER (decl_name), "__ct_comp", 9) != 0
2913 && strncmp (IDENTIFIER_POINTER (decl_name), "__dt_comp", 9) != 0)
9cc54940 2914 return 0;
f2aa696b 2915 }
9cc54940 2916
f2aa696b
EB
2917 /* If this function has an entry in the vtable, we cannot omit it. */
2918 else if (!DECL_VINDEX (t) && *IDENTIFIER_POINTER (decl_name) == '_')
2919 {
9cc54940
AC
2920 INDENT (spc);
2921 pp_string (buffer, "-- skipped func ");
2922 pp_string (buffer, IDENTIFIER_POINTER (decl_name));
2923 return 1;
2924 }
2925
2926 if (need_indent)
2927 INDENT (spc);
2928
f2aa696b 2929 if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (t))) && !is_constructor)
9cc54940 2930 {
9cc54940 2931 pp_string (buffer, "procedure ");
f2aa696b 2932 is_function = false;
9cc54940
AC
2933 }
2934 else
f2aa696b
EB
2935 {
2936 pp_string (buffer, "function ");
2937 is_function = true;
2938 }
9cc54940 2939
f2aa696b 2940 if (is_constructor)
b854df3c 2941 print_constructor (buffer, t, type);
f2aa696b 2942 else if (is_destructor)
b854df3c 2943 print_destructor (buffer, t, type);
9cc54940
AC
2944 else
2945 dump_ada_decl_name (buffer, t, false);
2946
2947 dump_ada_function_declaration
2948 (buffer, t, is_method, is_constructor, is_destructor, spc);
9cc54940
AC
2949
2950 if (is_function)
2951 {
2952 pp_string (buffer, " return ");
f2aa696b
EB
2953 tree ret_type
2954 = is_constructor ? DECL_CONTEXT (t) : TREE_TYPE (TREE_TYPE (t));
2955 dump_generic_ada_node (buffer, ret_type, type, spc, false, true);
9cc54940
AC
2956 }
2957
5aaa8fb4
NS
2958 if (is_constructor && RECORD_OR_UNION_TYPE_P (type))
2959 for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
db440138 2960 if (TREE_CODE (fld) == FUNCTION_DECL && cpp_check (fld, IS_ABSTRACT))
5aaa8fb4
NS
2961 {
2962 is_abstract_class = true;
2963 break;
2964 }
9cc54940
AC
2965
2966 if (is_abstract || is_abstract_class)
2967 pp_string (buffer, " is abstract");
2968
2969 pp_semicolon (buffer);
2970 pp_string (buffer, " -- ");
2971 dump_sloc (buffer, t);
2972
65a372f4 2973 if (is_abstract || !DECL_ASSEMBLER_NAME (t))
9cc54940
AC
2974 return 1;
2975
2976 newline_and_indent (buffer, spc);
2977
2978 if (is_constructor)
2979 {
f2aa696b 2980 pp_string (buffer, "pragma CPP_Constructor (");
b854df3c 2981 print_constructor (buffer, t, type);
9cc54940
AC
2982 pp_string (buffer, ", \"");
2983 pp_asm_name (buffer, t);
2984 pp_string (buffer, "\");");
2985 }
2986 else if (is_destructor)
2987 {
2988 pp_string (buffer, "pragma Import (CPP, ");
b854df3c 2989 print_destructor (buffer, t, type);
9cc54940
AC
2990 pp_string (buffer, ", \"");
2991 pp_asm_name (buffer, t);
2992 pp_string (buffer, "\");");
2993 }
2994 else
2995 {
2996 dump_ada_import (buffer, t);
2997 }
2998
2999 return 1;
3000 }
3001 else if (TREE_CODE (t) == TYPE_DECL && !DECL_ORIGINAL_TYPE (t))
3002 {
3003 int is_interface = 0;
3004 int is_abstract_record = 0;
3005
3006 if (need_indent)
3007 INDENT (spc);
3008
3009 /* Anonymous structs/unions */
94159ecf 3010 dump_generic_ada_node (buffer, TREE_TYPE (t), t, spc, false, true);
9cc54940 3011
f07862c7 3012 if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE)
9cc54940
AC
3013 {
3014 pp_string (buffer, " (discr : unsigned := 0)");
3015 }
3016
3017 pp_string (buffer, " is ");
3018
5aaa8fb4
NS
3019 /* Check whether we have an Ada interface compatible class.
3020 That is only have a vtable non-static data member and no
3021 non-abstract methods. */
94159ecf 3022 if (cpp_check
5aaa8fb4 3023 && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
9cc54940 3024 {
9f2cb25e 3025 bool has_fields = false;
9cc54940
AC
3026
3027 /* Check that there are no fields other than the virtual table. */
5aaa8fb4 3028 for (tree fld = TYPE_FIELDS (TREE_TYPE (t));
9f2cb25e
EB
3029 fld;
3030 fld = TREE_CHAIN (fld))
9cc54940 3031 {
5aaa8fb4
NS
3032 if (TREE_CODE (fld) == FIELD_DECL)
3033 {
9f2cb25e 3034 if (!has_fields && DECL_VIRTUAL_P (fld))
5aaa8fb4
NS
3035 is_interface = 1;
3036 else
3037 is_interface = 0;
9f2cb25e 3038 has_fields = true;
5aaa8fb4 3039 }
db440138 3040 else if (TREE_CODE (fld) == FUNCTION_DECL
5aaa8fb4
NS
3041 && !DECL_ARTIFICIAL (fld))
3042 {
3043 if (cpp_check (fld, IS_ABSTRACT))
3044 is_abstract_record = 1;
3045 else
3046 is_interface = 0;
3047 }
9cc54940
AC
3048 }
3049 }
3050
3b0c690e 3051 TREE_VISITED (t) = 1;
9cc54940
AC
3052 if (is_interface)
3053 {
3054 pp_string (buffer, "limited interface; -- ");
3055 dump_sloc (buffer, t);
3056 newline_and_indent (buffer, spc);
3057 pp_string (buffer, "pragma Import (CPP, ");
3058 dump_generic_ada_node
94159ecf 3059 (buffer, TYPE_NAME (TREE_TYPE (t)), type, spc, false, true);
07838b13 3060 pp_right_paren (buffer);
9cc54940 3061
94159ecf 3062 print_ada_methods (buffer, TREE_TYPE (t), spc);
9cc54940
AC
3063 }
3064 else
3065 {
3066 if (is_abstract_record)
3067 pp_string (buffer, "abstract ");
94159ecf 3068 dump_generic_ada_node (buffer, t, t, spc, false, false);
9cc54940
AC
3069 }
3070 }
3071 else
3072 {
3073 if (need_indent)
3074 INDENT (spc);
3075
3076 if (TREE_CODE (t) == FIELD_DECL && DECL_NAME (t))
3077 check_name (buffer, t);
3078
3079 /* Print variable/type's name. */
94159ecf 3080 dump_generic_ada_node (buffer, t, t, spc, false, true);
9cc54940
AC
3081
3082 if (TREE_CODE (t) == TYPE_DECL)
3083 {
3084 tree orig = DECL_ORIGINAL_TYPE (t);
3085 int is_subtype = orig && TYPE_NAME (orig) && orig != TREE_TYPE (t);
3086
f07862c7 3087 if (!is_subtype && TREE_CODE (TREE_TYPE (t)) == UNION_TYPE)
9cc54940
AC
3088 pp_string (buffer, " (discr : unsigned := 0)");
3089
3090 pp_string (buffer, " is ");
3091
94159ecf 3092 dump_generic_ada_node (buffer, orig, t, spc, false, is_subtype);
9cc54940
AC
3093 }
3094 else
3095 {
3096 if (spc == INDENT_INCR || TREE_STATIC (t))
3097 is_var = 1;
3098
3099 pp_string (buffer, " : ");
3100
f07862c7 3101 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
9cc54940 3102 {
f07862c7 3103 pp_string (buffer, "aliased ");
9cc54940 3104
f4bcd9eb
EB
3105 if (TREE_READONLY (t))
3106 pp_string (buffer, "constant ");
3107
f07862c7
EB
3108 if (TYPE_NAME (TREE_TYPE (t)))
3109 dump_generic_ada_node
3110 (buffer, TREE_TYPE (t), t, spc, false, true);
942047f2 3111 else if (type)
f07862c7 3112 dump_ada_double_name (buffer, type, t);
9cc54940
AC
3113 }
3114 else
3115 {
3116 if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE
3117 && (TYPE_NAME (TREE_TYPE (t))
3118 || TREE_CODE (TREE_TYPE (t)) != INTEGER_TYPE))
3119 pp_string (buffer, "aliased ");
3120
f4bcd9eb
EB
3121 if (TREE_READONLY (t))
3122 pp_string (buffer, "constant ");
3123
9cc54940 3124 dump_generic_ada_node
94159ecf 3125 (buffer, TREE_TYPE (t), TREE_TYPE (t), spc, false, true);
9cc54940
AC
3126 }
3127 }
3128 }
3129
3130 if (is_class)
3131 {
2a877204 3132 spc -= INDENT_INCR;
9cc54940
AC
3133 newline_and_indent (buffer, spc);
3134 pp_string (buffer, "end;");
3135 newline_and_indent (buffer, spc);
3136 pp_string (buffer, "use Class_");
94159ecf 3137 dump_generic_ada_node (buffer, t, type, spc, false, true);
9cc54940
AC
3138 pp_semicolon (buffer);
3139 pp_newline (buffer);
3140
3141 /* All needed indentation/newline performed already, so return 0. */
3142 return 0;
3143 }
3144 else
3145 {
3146 pp_string (buffer, "; -- ");
3147 dump_sloc (buffer, t);
3148 }
3149
3150 if (is_var)
3151 {
3152 newline_and_indent (buffer, spc);
3153 dump_ada_import (buffer, t);
3154 }
3155
3156 return 1;
3157}
3158
3159/* Prints in BUFFER a structure NODE of type TYPE: name, fields, and methods
94159ecf
EB
3160 with Ada syntax. SPC is the indentation level. If DISPLAY_CONVENTION is
3161 true, also print the pragma Convention for NODE. */
9cc54940
AC
3162
3163static void
94159ecf 3164print_ada_struct_decl (pretty_printer *buffer, tree node, tree type, int spc,
9cc54940
AC
3165 bool display_convention)
3166{
3167 tree tmp;
f07862c7 3168 const bool is_union = (TREE_CODE (node) == UNION_TYPE);
b46dbc6c 3169 char buf[32];
9cc54940
AC
3170 int field_num = 0;
3171 int field_spc = spc + INDENT_INCR;
3172 int need_semicolon;
3173
3174 bitfield_used = false;
3175
f07862c7 3176 if (TYPE_FIELDS (node))
9cc54940 3177 {
9cc54940 3178 /* Print the contents of the structure. */
f07862c7 3179 pp_string (buffer, "record");
9cc54940
AC
3180
3181 if (is_union)
3182 {
3183 newline_and_indent (buffer, spc + INDENT_INCR);
3184 pp_string (buffer, "case discr is");
3185 field_spc = spc + INDENT_INCR * 3;
3186 }
3187
3188 pp_newline (buffer);
3189
3190 /* Print the non-static fields of the structure. */
3191 for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
3192 {
3193 /* Add parent field if needed. */
3194 if (!DECL_NAME (tmp))
3195 {
3196 if (!is_tagged_type (TREE_TYPE (tmp)))
3197 {
3198 if (!TYPE_NAME (TREE_TYPE (tmp)))
94159ecf 3199 print_ada_declaration (buffer, tmp, type, field_spc);
9cc54940
AC
3200 else
3201 {
3202 INDENT (field_spc);
3203
3204 if (field_num == 0)
c583af79 3205 pp_string (buffer, "parent : aliased ");
9cc54940
AC
3206 else
3207 {
c583af79 3208 sprintf (buf, "field_%d : aliased ", field_num + 1);
9cc54940
AC
3209 pp_string (buffer, buf);
3210 }
3211 dump_ada_decl_name
3212 (buffer, TYPE_NAME (TREE_TYPE (tmp)), false);
3213 pp_semicolon (buffer);
3214 }
3215 pp_newline (buffer);
3216 field_num++;
3217 }
3218 }
b854df3c 3219 else if (TREE_CODE (tmp) == FIELD_DECL)
9cc54940
AC
3220 {
3221 /* Skip internal virtual table field. */
9f2cb25e 3222 if (!DECL_VIRTUAL_P (tmp))
9cc54940
AC
3223 {
3224 if (is_union)
3225 {
3226 if (TREE_CHAIN (tmp)
3227 && TREE_TYPE (TREE_CHAIN (tmp)) != node
3228 && TREE_CODE (TREE_CHAIN (tmp)) != TYPE_DECL)
3229 sprintf (buf, "when %d =>", field_num);
3230 else
3231 sprintf (buf, "when others =>");
3232
3233 INDENT (spc + INDENT_INCR * 2);
3234 pp_string (buffer, buf);
3235 pp_newline (buffer);
3236 }
3237
94159ecf 3238 if (print_ada_declaration (buffer, tmp, type, field_spc))
9cc54940
AC
3239 {
3240 pp_newline (buffer);
3241 field_num++;
3242 }
3243 }
3244 }
3245 }
3246
3247 if (is_union)
3248 {
3249 INDENT (spc + INDENT_INCR);
3250 pp_string (buffer, "end case;");
3251 pp_newline (buffer);
3252 }
3253
3254 if (field_num == 0)
3255 {
3256 INDENT (spc + INDENT_INCR);
3257 pp_string (buffer, "null;");
3258 pp_newline (buffer);
3259 }
3260
3261 INDENT (spc);
3262 pp_string (buffer, "end record;");
3263 }
f07862c7
EB
3264 else
3265 pp_string (buffer, "null record;");
9cc54940
AC
3266
3267 newline_and_indent (buffer, spc);
3268
3269 if (!display_convention)
3270 return;
3271
3272 if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
3273 {
94159ecf 3274 if (has_nontrivial_methods (TREE_TYPE (type)))
9cc54940
AC
3275 pp_string (buffer, "pragma Import (CPP, ");
3276 else
3277 pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
3278 }
3279 else
3280 pp_string (buffer, "pragma Convention (C, ");
3281
3282 package_prefix = false;
94159ecf 3283 dump_generic_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
9cc54940 3284 package_prefix = true;
07838b13 3285 pp_right_paren (buffer);
9cc54940
AC
3286
3287 if (is_union)
3288 {
3289 pp_semicolon (buffer);
3290 newline_and_indent (buffer, spc);
3291 pp_string (buffer, "pragma Unchecked_Union (");
3292
94159ecf 3293 dump_generic_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
07838b13 3294 pp_right_paren (buffer);
9cc54940
AC
3295 }
3296
3297 if (bitfield_used)
3298 {
3299 pp_semicolon (buffer);
3300 newline_and_indent (buffer, spc);
3301 pp_string (buffer, "pragma Pack (");
3302 dump_generic_ada_node
94159ecf 3303 (buffer, TREE_TYPE (type), type, spc, false, true);
07838b13 3304 pp_right_paren (buffer);
9cc54940
AC
3305 bitfield_used = false;
3306 }
3307
94159ecf 3308 need_semicolon = !print_ada_methods (buffer, node, spc);
9cc54940
AC
3309
3310 /* Print the static fields of the structure, if any. */
9cc54940
AC
3311 for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
3312 {
b854df3c 3313 if (TREE_CODE (tmp) == VAR_DECL && DECL_NAME (tmp))
9cc54940
AC
3314 {
3315 if (need_semicolon)
3316 {
3317 need_semicolon = false;
3318 pp_semicolon (buffer);
3319 }
3320 pp_newline (buffer);
3321 pp_newline (buffer);
94159ecf 3322 print_ada_declaration (buffer, tmp, type, spc);
9cc54940
AC
3323 }
3324 }
3325}
3326
3327/* Dump all the declarations in SOURCE_FILE to an Ada spec.
3328 COLLECT_ALL_REFS is a front-end callback used to collect all relevant
94159ecf 3329 nodes for SOURCE_FILE. CHECK is used to perform C++ queries on nodes. */
9cc54940
AC
3330
3331static void
3332dump_ads (const char *source_file,
3333 void (*collect_all_refs)(const char *),
621955cb 3334 int (*check)(tree, cpp_operation))
9cc54940
AC
3335{
3336 char *ads_name;
3337 char *pkg_name;
3338 char *s;
3339 FILE *f;
3340
3341 pkg_name = get_ada_package (source_file);
3342
dd5a833e 3343 /* Construct the .ads filename and package name. */
9cc54940
AC
3344 ads_name = xstrdup (pkg_name);
3345
3346 for (s = ads_name; *s; s++)
da5182be
TQ
3347 if (*s == '.')
3348 *s = '-';
3349 else
3350 *s = TOLOWER (*s);
9cc54940
AC
3351
3352 ads_name = reconcat (ads_name, ads_name, ".ads", NULL);
3353
3354 /* Write out the .ads file. */
3355 f = fopen (ads_name, "w");
3356 if (f)
3357 {
3358 pretty_printer pp;
3359
9cc54940
AC
3360 pp_needs_newline (&pp) = true;
3361 pp.buffer->stream = f;
3362
3363 /* Dump all relevant macros. */
3364 dump_ada_macros (&pp, source_file);
3365
3366 /* Reset the table of withs for this file. */
3367 reset_ada_withs ();
3368
3369 (*collect_all_refs) (source_file);
3370
3371 /* Dump all references. */
94159ecf
EB
3372 cpp_check = check;
3373 dump_ada_nodes (&pp, source_file);
9cc54940 3374
c583af79
AC
3375 /* Requires Ada 2005 syntax, so generate corresponding pragma.
3376 Also, disable style checks since this file is auto-generated. */
3377 fprintf (f, "pragma Ada_2005;\npragma Style_Checks (Off);\n\n");
3378
9cc54940
AC
3379 /* Dump withs. */
3380 dump_ada_withs (f);
3381
3382 fprintf (f, "\npackage %s is\n\n", pkg_name);
3383 pp_write_text_to_stream (&pp);
3384 /* ??? need to free pp */
3385 fprintf (f, "end %s;\n", pkg_name);
3386 fclose (f);
3387 }
3388
3389 free (ads_name);
3390 free (pkg_name);
3391}
3392
3393static const char **source_refs = NULL;
3394static int source_refs_used = 0;
3395static int source_refs_allocd = 0;
3396
3397/* Add an entry for FILENAME to the table SOURCE_REFS. */
3398
3399void
3400collect_source_ref (const char *filename)
3401{
3402 int i;
3403
3404 if (!filename)
3405 return;
3406
3407 if (source_refs_allocd == 0)
3408 {
3409 source_refs_allocd = 1024;
3410 source_refs = XNEWVEC (const char *, source_refs_allocd);
3411 }
3412
3413 for (i = 0; i < source_refs_used; i++)
0b07a57e 3414 if (filename == source_refs[i])
9cc54940
AC
3415 return;
3416
3417 if (source_refs_used == source_refs_allocd)
3418 {
3419 source_refs_allocd *= 2;
3420 source_refs = XRESIZEVEC (const char *, source_refs, source_refs_allocd);
3421 }
3422
0b07a57e 3423 source_refs[source_refs_used++] = filename;
9cc54940
AC
3424}
3425
3426/* Main entry point: dump all Ada specs corresponding to SOURCE_REFS
94159ecf 3427 using callbacks COLLECT_ALL_REFS and CHECK.
9cc54940
AC
3428 COLLECT_ALL_REFS is a front-end callback used to collect all relevant
3429 nodes for a given source file.
94159ecf 3430 CHECK is used to perform C++ queries on nodes, or NULL for the C
9cc54940
AC
3431 front-end. */
3432
3433void
3434dump_ada_specs (void (*collect_all_refs)(const char *),
621955cb 3435 int (*check)(tree, cpp_operation))
9cc54940
AC
3436{
3437 int i;
3438
3439 /* Iterate over the list of files to dump specs for */
3440 for (i = 0; i < source_refs_used; i++)
94159ecf 3441 dump_ads (source_refs[i], collect_all_refs, check);
9cc54940
AC
3442
3443 /* Free files table. */
3444 free (source_refs);
3445}