LCOV - code coverage report
Current view: top level - gcc/c-family - c-ada-spec.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 1148 1790 64.1 %
Date: 2020-03-28 11:57:23 Functions: 51 59 86.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

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

Generated by: LCOV version 1.0

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto --enable-host-shared. GCC test suite is run with the built compiler.