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