diff gcc/c-family/c-ada-spec.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents 561a7518be6b
children 84e7813d76e9
line wrap: on
line diff
--- a/gcc/c-family/c-ada-spec.c	Sun Aug 21 07:07:55 2011 +0900
+++ b/gcc/c-family/c-ada-spec.c	Fri Oct 27 22:46:09 2017 +0900
@@ -1,6 +1,6 @@
 /* Print GENERIC declaration (functions, variables, types) trees coming from
    the C and C++ front-ends as well as macros in Ada syntax.
-   Copyright (C) 2010 Free Software Foundation, Inc.
+   Copyright (C) 2010-2017 Free Software Foundation, Inc.
    Adapted from tree-pretty-print.c by Arnaud Charlet  <charlet@adacore.com>
 
 This file is part of GCC.
@@ -24,42 +24,33 @@
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "tree-pass.h"	/* For TDI_ada and friends.  */
-#include "output.h"
 #include "c-ada-spec.h"
-#include "cpplib.h"
+#include "fold-const.h"
 #include "c-pragma.h"
 #include "cpp-id-data.h"
+#include "stringpool.h"
+#include "attribs.h"
 
 /* Local functions, macros and variables.  */
-static int dump_generic_ada_node (pretty_printer *, tree, tree,
-				  int (*)(tree, cpp_operation), int, int, bool);
-static int print_ada_declaration (pretty_printer *, tree, tree,
-				  int (*cpp_check)(tree, cpp_operation), int);
-static void print_ada_struct_decl (pretty_printer *, tree, tree,
-				   int (*cpp_check)(tree, cpp_operation), int,
+static int  dump_generic_ada_node (pretty_printer *, tree, tree, int, bool,
 				   bool);
-static void dump_sloc (pretty_printer *buffer, tree node);
-static void print_comment (pretty_printer *, const char *);
-static void print_generic_ada_decl (pretty_printer *, tree,
-				    int (*)(tree, cpp_operation), const char *);
-static char *get_ada_package (const char *);
-static void dump_ada_nodes (pretty_printer *, const char *,
-			    int (*)(tree, cpp_operation));
-static void reset_ada_withs (void);
-static void dump_ada_withs (FILE *);
-static void dump_ads (const char *, void (*)(const char *),
-		      int (*)(tree, cpp_operation));
-static char *to_ada_name (const char *, int *);
-static bool separate_class_package (tree);
-
-#define LOCATION_COL(LOC) ((expand_location (LOC)).column)
-
-#define INDENT(SPACE) do { \
-  int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
+static int  dump_ada_declaration (pretty_printer *, tree, tree, int);
+static void dump_ada_struct_decl (pretty_printer *, tree, tree, int, bool);
+static char *to_ada_name (const char *, unsigned int, bool *);
+
+#define INDENT(SPACE) \
+  do { int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
 
 #define INDENT_INCR 3
 
+/* Global hook used to perform C++ queries on nodes.  */
+static int (*cpp_check) (tree, cpp_operation) = NULL;
+
+/* Global variables used in macro-related callbacks.  */
+static int max_ada_macros;
+static int store_ada_macro_index;
+static const char *macro_source_file;
+
 /* Given a cpp MACRO, compute the max length BUFFER_LEN of the macro, as well
    as max length PARAM_LEN of arguments for fun_like macros, and also set
    SUPPORTED to 0 if the macro cannot be mapped to an Ada construct.  */
@@ -77,7 +68,7 @@
 
   if (macro->fun_like)
     {
-      param_len++;
+      (*param_len)++;
       for (i = 0; i < macro->paramc; i++)
 	{
 	  cpp_hashnode *param = macro->params[i];
@@ -121,23 +112,137 @@
   (*buffer_len)++;
 }
 
-/* Dump into PP a set of MAX_ADA_MACROS MACROS (C/C++) as Ada constants when
-   possible.  */
+/* Dump all digits/hex chars from NUMBER to BUFFER and return a pointer
+   to the character after the last character written.  */
+
+static unsigned char *
+dump_number (unsigned char *number, unsigned char *buffer)
+{
+  while (*number != '\0'
+	 && *number != 'U'
+	 && *number != 'u'
+	 && *number != 'l'
+	 && *number != 'L')
+    *buffer++ = *number++;
+
+  return buffer;
+}
+
+/* Handle escape character C and convert to an Ada character into BUFFER.
+   Return a pointer to the character after the last character written, or
+   NULL if the escape character is not supported.  */
+
+static unsigned char *
+handle_escape_character (unsigned char *buffer, char c)
+{
+  switch (c)
+    {
+      case '"':
+	*buffer++ = '"';
+	*buffer++ = '"';
+	break;
+
+      case 'n':
+	strcpy ((char *) buffer, "\" & ASCII.LF & \"");
+	buffer += 16;
+	break;
+
+      case 'r':
+	strcpy ((char *) buffer, "\" & ASCII.CR & \"");
+	buffer += 16;
+	break;
+
+      case 't':
+	strcpy ((char *) buffer, "\" & ASCII.HT & \"");
+	buffer += 16;
+	break;
+
+      default:
+	return NULL;
+    }
+
+  return buffer;
+}
+
+/* Callback used to count the number of macros from cpp_forall_identifiers.
+   PFILE and V are not used.  NODE is the current macro to consider.  */
+
+static int
+count_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *node,
+		 void *v ATTRIBUTE_UNUSED)
+{
+  const cpp_macro *macro = node->value.macro;
+
+  if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)
+      && macro->count
+      && *NODE_NAME (node) != '_'
+      && LOCATION_FILE (macro->line) == macro_source_file)
+    max_ada_macros++;
+
+  return 1;
+}
+
+/* Callback used to store relevant macros from cpp_forall_identifiers.
+   PFILE is not used.  NODE is the current macro to store if relevant.
+   MACROS is an array of cpp_hashnode* used to store NODE.  */
+
+static int
+store_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED,
+		 cpp_hashnode *node, void *macros)
+{
+  const cpp_macro *macro = node->value.macro;
+
+  if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)
+      && macro->count
+      && *NODE_NAME (node) != '_'
+      && LOCATION_FILE (macro->line) == macro_source_file)
+    ((cpp_hashnode **) macros)[store_ada_macro_index++] = node;
+
+  return 1;
+}
+
+/* Callback used to compare (during qsort) macros.  NODE1 and NODE2 are the
+   two macro nodes to compare.  */
+
+static int
+compare_macro (const void *node1, const void *node2)
+{
+  typedef const cpp_hashnode *const_hnode;
+
+  const_hnode n1 = *(const const_hnode *) node1;
+  const_hnode n2 = *(const const_hnode *) node2;
+
+  return n1->value.macro->line - n2->value.macro->line;
+}
+
+/* Dump in PP all relevant macros appearing in FILE.  */
 
 static void
-print_ada_macros (pretty_printer *pp, cpp_hashnode **macros, int max_ada_macros)
+dump_ada_macros (pretty_printer *pp, const char* file)
 {
-  int j, num_macros = 0, prev_line = -1;
-
-  for (j = 0; j < max_ada_macros; j++)
+  int num_macros = 0, prev_line = -1;
+  cpp_hashnode **macros;
+
+  /* Initialize file-scope variables.  */
+  max_ada_macros = 0;
+  store_ada_macro_index = 0;
+  macro_source_file = file;
+
+  /* Count all potentially relevant macros, and then sort them by sloc.  */
+  cpp_forall_identifiers (parse_in, count_ada_macro, NULL);
+  macros = XALLOCAVEC (cpp_hashnode *, max_ada_macros);
+  cpp_forall_identifiers (parse_in, store_ada_macro, macros);
+  qsort (macros, max_ada_macros, sizeof (cpp_hashnode *), compare_macro);
+
+  for (int j = 0; j < max_ada_macros; j++)
     {
-      cpp_hashnode *node = macros [j];
+      cpp_hashnode *node = macros[j];
       const cpp_macro *macro = node->value.macro;
       unsigned i;
       int supported = 1, prev_is_one = 0, buffer_len, param_len;
       int is_string = 0, is_char = 0;
       char *ada_name;
-      unsigned char *s, *params, *buffer, *buf_param, *char_one = NULL;
+      unsigned char *s, *params, *buffer, *buf_param, *char_one = NULL, *tmp;
 
       macro_length (macro, &supported, &buffer_len, &param_len);
       s = buffer = XALLOCAVEC (unsigned char, buffer_len);
@@ -249,15 +354,35 @@
 		  case CPP_WCHAR:
 		  case CPP_CHAR16:
 		  case CPP_CHAR32:
+		  case CPP_UTF8CHAR:
 		  case CPP_NAME:
-		  case CPP_STRING:
-		  case CPP_NUMBER:
 		    if (!macro->fun_like)
 		      supported = 0;
 		    else
 		      buffer = cpp_spell_token (parse_in, token, buffer, false);
 		    break;
 
+		  case CPP_STRING:
+		    is_string = 1;
+		    {
+		      const unsigned char *s = token->val.str.text;
+
+		      for (; *s; s++)
+			if (*s == '\\')
+			  {
+			    s++;
+			    buffer = handle_escape_character (buffer, *s);
+			    if (buffer == NULL)
+			      {
+				supported = 0;
+				break;
+			      }
+			  }
+			else
+			  *buffer++ = *s;
+		    }
+		    break;
+
 		  case CPP_CHAR:
 		    is_char = 1;
 		    {
@@ -282,6 +407,72 @@
 		    }
 		    break;
 
+		  case CPP_NUMBER:
+		    tmp = cpp_token_as_text (parse_in, token);
+
+		    switch (*tmp)
+		      {
+			case '0':
+			  switch (tmp[1])
+			    {
+			      case '\0':
+			      case 'l':
+			      case 'L':
+			      case 'u':
+			      case 'U':
+				*buffer++ = '0';
+				break;
+
+			      case 'x':
+			      case 'X':
+				*buffer++ = '1';
+				*buffer++ = '6';
+				*buffer++ = '#';
+				buffer = dump_number (tmp + 2, buffer);
+				*buffer++ = '#';
+				break;
+
+			      case 'b':
+			      case 'B':
+				*buffer++ = '2';
+				*buffer++ = '#';
+				buffer = dump_number (tmp + 2, buffer);
+				*buffer++ = '#';
+				break;
+
+			      default:
+				/* Dump floating constants unmodified.  */
+				if (strchr ((const char *)tmp, '.'))
+				  buffer = dump_number (tmp, buffer);
+				else
+				  {
+				    *buffer++ = '8';
+				    *buffer++ = '#';
+				    buffer = dump_number (tmp + 1, buffer);
+				    *buffer++ = '#';
+				  }
+				break;
+			    }
+			  break;
+
+			case '1':
+			  if (tmp[1] == '\0' || tmp[1] == 'l' || tmp[1] == 'u'
+			      || tmp[1] == 'L' || tmp[1] == 'U')
+			    {
+			      is_one = 1;
+			      char_one = buffer;
+			      *buffer++ = '1';
+			    }
+			  else
+			    buffer = dump_number (tmp, buffer);
+			  break;
+
+			default:
+			  buffer = dump_number (tmp, buffer);
+			  break;
+		      }
+		    break;
+
 		  case CPP_LSHIFT:
 		    if (prev_is_one)
 		      {
@@ -346,10 +537,10 @@
 
 	  pp_string (pp, "   --  arg-macro: ");
 
-	  if (*start == '(' && buffer [-1] == ')')
+	  if (*start == '(' && buffer[-1] == ')')
 	    {
 	      start++;
-	      buffer [-1] = '\0';
+	      buffer[-1] = '\0';
 	      is_function = 1;
 	      pp_string (pp, "function ");
 	    }
@@ -379,14 +570,14 @@
 	{
 	  expanded_location sloc = expand_location (macro->line);
 
-	  if (sloc.line != prev_line + 1)
+	  if (sloc.line != prev_line + 1 && prev_line > 0)
 	    pp_newline (pp);
 
 	  num_macros++;
 	  prev_line = sloc.line;
 
 	  pp_string (pp, "   ");
-	  ada_name = to_ada_name ((const char *) NODE_NAME (node), NULL);
+	  ada_name = to_ada_name ((const char *) NODE_NAME (node), 0, NULL);
 	  pp_string (pp, ada_name);
 	  free (ada_name);
 	  pp_string (pp, " : ");
@@ -406,7 +597,7 @@
 
 	  pp_string (pp, ";  --  ");
 	  pp_string (pp, sloc.file);
-	  pp_character (pp, ':');
+	  pp_colon (pp);
 	  pp_scalar (pp, "%d", sloc.line);
 	  pp_newline (pp);
 	}
@@ -422,121 +613,51 @@
     pp_newline (pp);
 }
 
-static const char *source_file;
-static int max_ada_macros;
-
-/* Callback used to count the number of relevant macros from
-   cpp_forall_identifiers. PFILE and V are not used. NODE is the current macro
-   to consider.  */
-
-static int
-count_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *node,
-		 void *v ATTRIBUTE_UNUSED)
-{
-  const cpp_macro *macro = node->value.macro;
-
-  if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)
-      && macro->count
-      && *NODE_NAME (node) != '_'
-      && LOCATION_FILE (macro->line) == source_file)
-    max_ada_macros++;
-
-  return 1;
-}
-
-static int store_ada_macro_index;
-
-/* Callback used to store relevant macros from cpp_forall_identifiers.
-   PFILE is not used. NODE is the current macro to store if relevant.
-   MACROS is an array of cpp_hashnode* used to store NODE.  */
-
-static int
-store_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED,
-		 cpp_hashnode *node, void *macros)
-{
-  const cpp_macro *macro = node->value.macro;
-
-  if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)
-      && macro->count
-      && *NODE_NAME (node) != '_'
-      && LOCATION_FILE (macro->line) == source_file)
-    ((cpp_hashnode **) macros)[store_ada_macro_index++] = node;
-
-  return 1;
-}
-
-/* Callback used to compare (during qsort) macros.  NODE1 and NODE2 are the
-   two macro nodes to compare.  */
-
-static int
-compare_macro (const void *node1, const void *node2)
-{
-  typedef const cpp_hashnode *const_hnode;
-
-  const_hnode n1 = *(const const_hnode *) node1;
-  const_hnode n2 = *(const const_hnode *) node2;
-
-  return n1->value.macro->line - n2->value.macro->line;
-}
-
-/* Dump in PP all relevant macros appearing in FILE.  */
-
-static void
-dump_ada_macros (pretty_printer *pp, const char* file)
-{
-  cpp_hashnode **macros;
-
-  /* Initialize file-scope variables.  */
-  max_ada_macros = 0;
-  store_ada_macro_index = 0;
-  source_file = file;
-
-  /* Count all potentially relevant macros, and then sort them by sloc.  */
-  cpp_forall_identifiers (parse_in, count_ada_macro, NULL);
-  macros = XALLOCAVEC (cpp_hashnode *, max_ada_macros);
-  cpp_forall_identifiers (parse_in, store_ada_macro, macros);
-  qsort (macros, max_ada_macros, sizeof (cpp_hashnode *), compare_macro);
-
-  print_ada_macros (pp, macros, max_ada_macros);
-}
-
 /* Current source file being handled.  */
-
-static const char *source_file_base;
-
-/* Compare the declaration (DECL) of struct-like types based on the sloc of
-   their last field (if LAST is true), so that more nested types collate before
-   less nested ones.
-   If ORIG_TYPE is true, also consider struct with a DECL_ORIGINAL_TYPE.  */
-
-static location_t
-decl_sloc_common (const_tree decl, bool last, bool orig_type)
-{
-  tree type = TREE_TYPE (decl);
-
-  if (TREE_CODE (decl) == TYPE_DECL
-      && (orig_type || !DECL_ORIGINAL_TYPE (decl))
-      && RECORD_OR_UNION_TYPE_P (type)
-      && TYPE_FIELDS (type))
-    {
-      tree f = TYPE_FIELDS (type);
-
-      if (last)
-	while (TREE_CHAIN (f))
-	  f = TREE_CHAIN (f);
-
-      return DECL_SOURCE_LOCATION (f);
-    }
-  else
-    return DECL_SOURCE_LOCATION (decl);
-}
+static const char *current_source_file;
 
 /* Return sloc of DECL, using sloc of last field if LAST is true.  */
 
 location_t
 decl_sloc (const_tree decl, bool last)
 {
-  return decl_sloc_common (decl, last, false);
+  tree field;
+
+  /* Compare the declaration of struct-like types based on the sloc of their
+     last field (if LAST is true), so that more nested types collate before
+     less nested ones.  */
+  if (TREE_CODE (decl) == TYPE_DECL
+      && !DECL_ORIGINAL_TYPE (decl)
+      && RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
+      && (field = TYPE_FIELDS (TREE_TYPE (decl))))
+    {
+      if (last)
+	while (DECL_CHAIN (field))
+	  field = DECL_CHAIN (field);
+      return DECL_SOURCE_LOCATION (field);
+    }
+
+  return DECL_SOURCE_LOCATION (decl);
+}
+
+/* Compare two locations LHS and RHS.  */
+
+static int
+compare_location (location_t lhs, location_t rhs)
+{
+  expanded_location xlhs = expand_location (lhs);
+  expanded_location xrhs = expand_location (rhs);
+
+  if (xlhs.file != xrhs.file)
+    return filename_cmp (xlhs.file, xrhs.file);
+
+  if (xlhs.line != xrhs.line)
+    return xlhs.line - xrhs.line;
+
+  if (xlhs.column != xrhs.column)
+    return xlhs.column - xrhs.column;
+
+  return 0;
 }
 
 /* Compare two declarations (LP and RP) by their source location.  */
@@ -547,7 +668,7 @@
   const_tree lhs = *((const tree *) lp);
   const_tree rhs = *((const tree *) rp);
 
-  return decl_sloc (lhs, true) - decl_sloc (rhs, true);
+  return compare_location (decl_sloc (lhs, true), decl_sloc (rhs, true));
 }
 
 /* Compare two comments (LP and RP) by their source location.  */
@@ -558,16 +679,7 @@
   const cpp_comment *lhs = (const cpp_comment *) lp;
   const cpp_comment *rhs = (const cpp_comment *) rp;
 
-  if (LOCATION_FILE (lhs->sloc) != LOCATION_FILE (rhs->sloc))
-    return strcmp (LOCATION_FILE (lhs->sloc), LOCATION_FILE (rhs->sloc));
-
-  if (LOCATION_LINE (lhs->sloc) != LOCATION_LINE (rhs->sloc))
-    return LOCATION_LINE (lhs->sloc) - LOCATION_LINE (rhs->sloc);
-
-  if (LOCATION_COL (lhs->sloc) != LOCATION_COL (rhs->sloc))
-    return LOCATION_COL (lhs->sloc) - LOCATION_COL (rhs->sloc);
-
-  return 0;
+  return compare_location (lhs->sloc, rhs->sloc);
 }
 
 static tree *to_dump = NULL;
@@ -582,9 +694,12 @@
   tree n;
   int i = to_dump_count;
 
-  /* Count the likely relevant nodes.  */
+  /* Count the likely relevant nodes: do not dump builtins (they are irrelevant
+     in the context of bindings) and namespaces (we do not handle them properly
+     yet).  */
   for (n = t; n; n = TREE_CHAIN (n))
     if (!DECL_IS_BUILTIN (n)
+	&& TREE_CODE (n) != NAMESPACE_DECL
 	&& LOCATION_FILE (decl_sloc (n, false)) == source_file)
       to_dump_count++;
 
@@ -594,8 +709,9 @@
   /* Store the relevant nodes.  */
   for (n = t; n; n = TREE_CHAIN (n))
     if (!DECL_IS_BUILTIN (n)
+	&& TREE_CODE (n) != NAMESPACE_DECL
 	&& LOCATION_FILE (decl_sloc (n, false)) == source_file)
-      to_dump [i++] = n;
+      to_dump[i++] = n;
 }
 
 /* Call back for walk_tree to clear the TREE_VISITED flag of TP.  */
@@ -612,71 +728,6 @@
   return NULL_TREE;
 }
 
-/* Dump nodes into PP relevant to SOURCE_FILE, as collected by previous calls
-   to collect_ada_nodes.  CPP_CHECK is used to perform C++ queries on nodes.  */
-
-static void
-dump_ada_nodes (pretty_printer *pp, const char *source_file,
-		int (*cpp_check)(tree, cpp_operation))
-{
-  int i, j;
-  cpp_comment_table *comments;
-
-  /* Sort the table of declarations to dump by sloc.  */
-  qsort (to_dump, to_dump_count, sizeof (tree), compare_node);
-
-  /* Fetch the table of comments.  */
-  comments = cpp_get_comments (parse_in);
-
-  /* Sort the comments table by sloc.  */
-  qsort (comments->entries, comments->count, sizeof (cpp_comment),
-	 compare_comment);
-
-  /* Interleave comments and declarations in line number order.  */
-  i = j = 0;
-  do
-    {
-      /* Advance j until comment j is in this file.  */
-      while (j != comments->count
-	     && LOCATION_FILE (comments->entries[j].sloc) != source_file)
-	j++;
-
-      /* Advance j until comment j is not a duplicate.  */
-      while (j < comments->count - 1
-	     && !compare_comment (&comments->entries[j],
-				  &comments->entries[j + 1]))
-	j++;
-
-      /* Write decls until decl i collates after comment j.  */
-      while (i != to_dump_count)
-	{
-	  if (j == comments->count
-	      || LOCATION_LINE (decl_sloc (to_dump[i], false))
-	      <  LOCATION_LINE (comments->entries[j].sloc))
-	    print_generic_ada_decl (pp, to_dump[i++], cpp_check, source_file);
-	  else
-	    break;
-	}
-
-      /* Write comment j, if there is one.  */
-      if (j != comments->count)
-	print_comment (pp, comments->entries[j++].comment);
-
-    } while (i != to_dump_count || j != comments->count);
-
-  /* Clear the TREE_VISITED flag over each subtree we've dumped.  */
-  for (i = 0; i < to_dump_count; i++)
-    walk_tree (&to_dump[i], unmark_visited_r, NULL, NULL);
-
-  /* Finalize the to_dump table.  */
-  if (to_dump)
-    {
-      free (to_dump);
-      to_dump = NULL;
-      to_dump_count = 0;
-    }
-}
-
 /* Print a COMMENT to the output stream PP.  */
 
 static void
@@ -713,21 +764,77 @@
     pp_newline (pp);
 }
 
-/* Prints declaration DECL to PP in Ada syntax. The current source file being
-   handled is SOURCE_FILE, and CPP_CHECK is used to perform C++ queries on
-   nodes.  */
+/* Dump nodes into PP relevant to SOURCE_FILE, as collected by previous calls
+   to collect_ada_nodes.  */
 
 static void
-print_generic_ada_decl (pretty_printer *pp, tree decl,
-			int (*cpp_check)(tree, cpp_operation),
-			const char* source_file)
+dump_ada_nodes (pretty_printer *pp, const char *source_file)
 {
-  source_file_base = source_file;
-
-  if (print_ada_declaration (pp, decl, 0, cpp_check, INDENT_INCR))
+  int i, j;
+  cpp_comment_table *comments;
+
+  /* Sort the table of declarations to dump by sloc.  */
+  qsort (to_dump, to_dump_count, sizeof (tree), compare_node);
+
+  /* Fetch the table of comments.  */
+  comments = cpp_get_comments (parse_in);
+
+  /* Sort the comments table by sloc.  */
+  if (comments->count > 1)
+    qsort (comments->entries, comments->count, sizeof (cpp_comment),
+	   compare_comment);
+
+  /* Interleave comments and declarations in line number order.  */
+  i = j = 0;
+  do
     {
-      pp_newline (pp);
-      pp_newline (pp);
+      /* Advance j until comment j is in this file.  */
+      while (j != comments->count
+	     && LOCATION_FILE (comments->entries[j].sloc) != source_file)
+	j++;
+
+      /* Advance j until comment j is not a duplicate.  */
+      while (j < comments->count - 1
+	     && !compare_comment (&comments->entries[j],
+				  &comments->entries[j + 1]))
+	j++;
+
+      /* Write decls until decl i collates after comment j.  */
+      while (i != to_dump_count)
+	{
+	  if (j == comments->count
+	      || LOCATION_LINE (decl_sloc (to_dump[i], false))
+	      <  LOCATION_LINE (comments->entries[j].sloc))
+	    {
+	      current_source_file = source_file;
+
+	      if (dump_ada_declaration (pp, to_dump[i++], NULL_TREE,
+					 INDENT_INCR))
+		{
+		  pp_newline (pp);
+		  pp_newline (pp);
+		}
+	    }
+	  else
+	    break;
+	}
+
+      /* Write comment j, if there is one.  */
+      if (j != comments->count)
+	print_comment (pp, comments->entries[j++].comment);
+
+    } while (i != to_dump_count || j != comments->count);
+
+  /* Clear the TREE_VISITED flag over each subtree we've dumped.  */
+  for (i = 0; i < to_dump_count; i++)
+    walk_tree (&to_dump[i], unmark_visited_r, NULL, NULL);
+
+  /* Finalize the to_dump table.  */
+  if (to_dump)
+    {
+      free (to_dump);
+      to_dump = NULL;
+      to_dump_count = 0;
     }
 }
 
@@ -740,7 +847,7 @@
   INDENT (spc);
 }
 
-struct with { char *s; const char *in_file; int limited; };
+struct with { char *s; const char *in_file; bool limited; };
 static struct with *withs = NULL;
 static int withs_max = 4096;
 static int with_len = 0;
@@ -749,7 +856,7 @@
    true), if not already done.  */
 
 static void
-append_withs (const char *s, int limited_access)
+append_withs (const char *s, bool limited_access)
 {
   int i;
 
@@ -763,16 +870,16 @@
     }
 
   for (i = 0; i < with_len; i++)
-    if (!strcmp (s, withs [i].s)
-	&& source_file_base == withs [i].in_file)
+    if (!strcmp (s, withs[i].s)
+	&& current_source_file == withs[i].in_file)
       {
-	withs [i].limited &= limited_access;
+	withs[i].limited &= limited_access;
 	return;
       }
 
-  withs [with_len].s = xstrdup (s);
-  withs [with_len].in_file = source_file_base;
-  withs [with_len].limited = limited_access;
+  withs[with_len].s = xstrdup (s);
+  withs[with_len].in_file = current_source_file;
+  withs[with_len].limited = limited_access;
   with_len++;
 }
 
@@ -787,7 +894,7 @@
     return;
 
   for (i = 0; i < with_len; i++)
-    free (withs [i].s);
+    free (withs[i].s);
   free (withs);
   withs = NULL;
   withs_max = 4096;
@@ -805,7 +912,7 @@
 
   for (i = 0; i < with_len; i++)
     fprintf
-      (f, "%swith %s;\n", withs [i].limited ? "limited " : "", withs [i].s);
+      (f, "%swith %s;\n", withs[i].limited ? "limited " : "", withs[i].s);
 }
 
 /* Return suitable Ada package name from FILE.  */
@@ -817,19 +924,30 @@
   char *res;
   const char *s;
   int i;
+  size_t plen;
 
   s = strstr (file, "/include/");
   if (s)
     base = s + 9;
   else
     base = lbasename (file);
-  res = XNEWVEC (char, strlen (base) + 1);
-
-  for (i = 0; *base; base++, i++)
+
+  if (ada_specs_parent == NULL)
+    plen = 0;
+  else
+    plen = strlen (ada_specs_parent) + 1;
+
+  res = XNEWVEC (char, plen + strlen (base) + 1);
+  if (ada_specs_parent != NULL) {
+    strcpy (res, ada_specs_parent);
+    res[plen - 1] = '.';
+  }
+
+  for (i = plen; *base; base++, i++)
     switch (*base)
       {
 	case '+':
-	  res [i] = 'p';
+	  res[i] = 'p';
 	  break;
 
 	case '.':
@@ -837,14 +955,14 @@
 	case '_':
 	case '/':
 	case '\\':
-	  res [i] = (i == 0 || res [i - 1] == '_') ? 'u' : '_';
+	  res[i] = (i == 0 || res[i - 1] == '.' || res[i - 1] == '_') ? 'u' : '_';
 	  break;
 
 	default:
-	  res [i] = *base;
+	  res[i] = *base;
 	  break;
       }
-  res [i] = '\0';
+  res[i] = '\0';
 
   return res;
 }
@@ -884,167 +1002,190 @@
 static tree
 get_underlying_decl (tree type)
 {
-  tree decl = NULL_TREE;
-
-  if (type == NULL_TREE)
+  if (!type)
     return NULL_TREE;
 
   /* type is a declaration.  */
   if (DECL_P (type))
-    decl = type;
+    return type;
 
   /* type is a typedef.  */
   if (TYPE_P (type) && TYPE_NAME (type) && DECL_P (TYPE_NAME (type)))
-    decl = TYPE_NAME (type);
+    return TYPE_NAME (type);
 
   /* TYPE_STUB_DECL has been set for type.  */
-  if (TYPE_P (type) && TYPE_STUB_DECL (type) &&
-      DECL_P (TYPE_STUB_DECL (type)))
-    decl = TYPE_STUB_DECL (type);
-
-  return decl;
+  if (TYPE_P (type) && TYPE_STUB_DECL (type))
+    return TYPE_STUB_DECL (type);
+
+  return NULL_TREE;
 }
 
 /* Return whether TYPE has static fields.  */
 
-static int
+static bool
 has_static_fields (const_tree type)
 {
-  tree tmp;
-
-  for (tmp = TYPE_FIELDS (type); tmp; tmp = TREE_CHAIN (tmp))
-    {
-      if (DECL_NAME (tmp) && TREE_STATIC (tmp))
-	return true;
-    }
+  if (!type || !RECORD_OR_UNION_TYPE_P (type))
+    return false;
+
+  for (tree fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
+    if (TREE_CODE (fld) == VAR_DECL && DECL_NAME (fld))
+      return true;
+
   return false;
 }
 
 /* Return whether TYPE corresponds to an Ada tagged type (has a dispatch
    table).  */
 
-static int
+static bool
 is_tagged_type (const_tree type)
 {
-  tree tmp;
-
   if (!type || !RECORD_OR_UNION_TYPE_P (type))
     return false;
 
-  for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
-    if (DECL_VINDEX (tmp))
+  for (tree fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
+    if (TREE_CODE (fld) == FUNCTION_DECL && DECL_VINDEX (fld))
       return true;
 
   return false;
 }
 
-/* Generate a legal Ada name from a C NAME, returning a malloc'd string.
-   SPACE_FOUND, if not NULL, is used to indicate whether a space was found in
-   NAME.  */
+/* Return whether TYPE has non-trivial methods, i.e. methods that do something
+   for the objects of TYPE.  In C++, all classes have implicit special methods,
+   e.g. constructors and destructors, but they can be trivial if the type is
+   sufficiently simple.  */
+
+static bool
+has_nontrivial_methods (tree type)
+{
+  if (!type || !RECORD_OR_UNION_TYPE_P (type))
+    return false;
+
+  /* Only C++ types can have methods.  */
+  if (!cpp_check)
+    return false;
+
+  /* A non-trivial type has non-trivial special methods.  */
+  if (!cpp_check (type, IS_TRIVIAL))
+    return true;
+
+  /* If there are user-defined methods, they are deemed non-trivial.  */
+  for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
+    if (TREE_CODE (fld) == FUNCTION_DECL && !DECL_ARTIFICIAL (fld))
+      return true;
+
+  return false;
+}
+
+#define INDEX_LENGTH 8
+
+/* Generate a legal Ada name from a C/C++ NAME and return a malloc'ed string.
+   INDEX, if non-zero, is used to disambiguate overloaded names.  SPACE_FOUND,
+   if not NULL, is used to indicate whether a space was found in NAME.  */
 
 static char *
-to_ada_name (const char *name, int *space_found)
+to_ada_name (const char *name, unsigned int index, bool *space_found)
 {
   const char **names;
-  int len = strlen (name);
+  const int len = strlen (name);
   int j, len2 = 0;
-  int found = false;
-  char *s = XNEWVEC (char, len * 2 + 5);
+  bool found = false;
+  char *s = XNEWVEC (char, len * 2 + 5 + (index ? INDEX_LENGTH : 0));
   char c;
 
   if (space_found)
     *space_found = false;
 
-  /* Add trailing "c_" if name is an Ada reserved word.  */
+  /* Add "c_" prefix if name is an Ada reserved word.  */
   for (names = ada_reserved; *names; names++)
     if (!strcasecmp (name, *names))
       {
-	s [len2++] = 'c';
-	s [len2++] = '_';
+	s[len2++] = 'c';
+	s[len2++] = '_';
 	found = true;
 	break;
       }
 
   if (!found)
-    /* Add trailing "c_" if name is an potential case sensitive duplicate.  */
+    /* Add "c_" prefix if name is a potential case sensitive duplicate.  */
     for (names = c_duplicates; *names; names++)
       if (!strcmp (name, *names))
 	{
-	  s [len2++] = 'c';
-	  s [len2++] = '_';
+	  s[len2++] = 'c';
+	  s[len2++] = '_';
 	  found = true;
 	  break;
 	}
 
-  for (j = 0; name [j] == '_'; j++)
-    s [len2++] = 'u';
+  for (j = 0; name[j] == '_'; j++)
+    s[len2++] = 'u';
 
   if (j > 0)
-    s [len2++] = '_';
+    s[len2++] = '_';
   else if (*name == '.' || *name == '$')
     {
-      s [0] = 'a';
-      s [1] = 'n';
-      s [2] = 'o';
-      s [3] = 'n';
+      s[0] = 'a';
+      s[1] = 'n';
+      s[2] = 'o';
+      s[3] = 'n';
       len2 = 4;
       j++;
     }
 
   /* Replace unsuitable characters for Ada identifiers.  */
-
   for (; j < len; j++)
-    switch (name [j])
+    switch (name[j])
       {
 	case ' ':
 	  if (space_found)
 	    *space_found = true;
-	  s [len2++] = '_';
+	  s[len2++] = '_';
 	  break;
 
 	/* ??? missing some C++ operators.  */
 	case '=':
-	  s [len2++] = '_';
-
-	  if (name [j + 1] == '=')
+	  s[len2++] = '_';
+
+	  if (name[j + 1] == '=')
 	    {
 	      j++;
-	      s [len2++] = 'e';
-	      s [len2++] = 'q';
+	      s[len2++] = 'e';
+	      s[len2++] = 'q';
 	    }
 	  else
 	    {
-	      s [len2++] = 'a';
-	      s [len2++] = 's';
+	      s[len2++] = 'a';
+	      s[len2++] = 's';
 	    }
 	  break;
 
 	case '!':
-	  s [len2++] = '_';
-	  if (name [j + 1] == '=')
+	  s[len2++] = '_';
+	  if (name[j + 1] == '=')
 	    {
 	      j++;
-	      s [len2++] = 'n';
-	      s [len2++] = 'e';
+	      s[len2++] = 'n';
+	      s[len2++] = 'e';
 	    }
 	  break;
 
 	case '~':
-	  s [len2++] = '_';
-	  s [len2++] = 't';
-	  s [len2++] = 'i';
+	  s[len2++] = '_';
+	  s[len2++] = 't';
+	  s[len2++] = 'i';
 	  break;
 
 	case '&':
 	case '|':
 	case '^':
-	  s [len2++] = '_';
-	  s [len2++] = name [j] == '&' ? 'a' : name [j] == '|' ? 'o' : 'x';
-
-	  if (name [j + 1] == '=')
+	  s[len2++] = '_';
+	  s[len2++] = name[j] == '&' ? 'a' : name[j] == '|' ? 'o' : 'x';
+
+	  if (name[j + 1] == '=')
 	    {
 	      j++;
-	      s [len2++] = 'e';
+	      s[len2++] = 'e';
 	    }
 	  break;
 
@@ -1054,53 +1195,53 @@
 	case '/':
 	case '(':
 	case '[':
-	  if (s [len2 - 1] != '_')
-	    s [len2++] = '_';
-
-	  switch (name [j + 1]) {
+	  if (s[len2 - 1] != '_')
+	    s[len2++] = '_';
+
+	  switch (name[j + 1]) {
 	    case '\0':
 	      j++;
-	      switch (name [j - 1]) {
-		case '+': s [len2++] = 'p'; break;  /* + */
-		case '-': s [len2++] = 'm'; break;  /* - */
-		case '*': s [len2++] = 't'; break;  /* * */
-		case '/': s [len2++] = 'd'; break;  /* / */
+	      switch (name[j - 1]) {
+		case '+': s[len2++] = 'p'; break;  /* + */
+		case '-': s[len2++] = 'm'; break;  /* - */
+		case '*': s[len2++] = 't'; break;  /* * */
+		case '/': s[len2++] = 'd'; break;  /* / */
 	      }
 	      break;
 
 	    case '=':
 	      j++;
-	      switch (name [j - 1]) {
-		case '+': s [len2++] = 'p'; break;  /* += */
-		case '-': s [len2++] = 'm'; break;  /* -= */
-		case '*': s [len2++] = 't'; break;  /* *= */
-		case '/': s [len2++] = 'd'; break;  /* /= */
+	      switch (name[j - 1]) {
+		case '+': s[len2++] = 'p'; break;  /* += */
+		case '-': s[len2++] = 'm'; break;  /* -= */
+		case '*': s[len2++] = 't'; break;  /* *= */
+		case '/': s[len2++] = 'd'; break;  /* /= */
 	      }
-	      s [len2++] = 'a';
+	      s[len2++] = 'a';
 	      break;
 
 	    case '-':  /* -- */
 	      j++;
-	      s [len2++] = 'm';
-	      s [len2++] = 'm';
+	      s[len2++] = 'm';
+	      s[len2++] = 'm';
 	      break;
 
 	    case '+':  /* ++ */
 	      j++;
-	      s [len2++] = 'p';
-	      s [len2++] = 'p';
+	      s[len2++] = 'p';
+	      s[len2++] = 'p';
 	      break;
 
 	    case ')':  /* () */
 	      j++;
-	      s [len2++] = 'o';
-	      s [len2++] = 'p';
+	      s[len2++] = 'o';
+	      s[len2++] = 'p';
 	      break;
 
 	    case ']':  /* [] */
 	      j++;
-	      s [len2++] = 'o';
-	      s [len2++] = 'b';
+	      s[len2++] = 'o';
+	      s[len2++] = 'b';
 	      break;
 	  }
 
@@ -1108,28 +1249,28 @@
 
 	case '<':
 	case '>':
-	  c = name [j] == '<' ? 'l' : 'g';
-	  s [len2++] = '_';
-
-	  switch (name [j + 1]) {
+	  c = name[j] == '<' ? 'l' : 'g';
+	  s[len2++] = '_';
+
+	  switch (name[j + 1]) {
 	    case '\0':
-	      s [len2++] = c;
-	      s [len2++] = 't';
+	      s[len2++] = c;
+	      s[len2++] = 't';
 	      break;
 	    case '=':
 	      j++;
-	      s [len2++] = c;
-	      s [len2++] = 'e';
+	      s[len2++] = c;
+	      s[len2++] = 'e';
 	      break;
 	    case '>':
 	      j++;
-	      s [len2++] = 's';
-	      s [len2++] = 'r';
+	      s[len2++] = 's';
+	      s[len2++] = 'r';
 	      break;
 	    case '<':
 	      j++;
-	      s [len2++] = 's';
-	      s [len2++] = 'l';
+	      s[len2++] = 's';
+	      s[len2++] = 'l';
 	      break;
 	    default:
 	      break;
@@ -1137,18 +1278,21 @@
 	  break;
 
 	case '_':
-	  if (len2 && s [len2 - 1] == '_')
-	    s [len2++] = 'u';
+	  if (len2 && s[len2 - 1] == '_')
+	    s[len2++] = 'u';
 	  /* fall through */
 
 	default:
-	  s [len2++] = name [j];
+	  s[len2++] = name[j];
       }
 
-  if (s [len2 - 1] == '_')
-    s [len2++] = 'u';
-
-  s [len2] = '\0';
+  if (s[len2 - 1] == '_')
+    s[len2++] = 'u';
+
+  if (index)
+    snprintf (&s[len2], INDEX_LENGTH, "_u_%d", index + 1);
+  else
+    s[len2] = '\0';
 
   return s;
 }
@@ -1159,44 +1303,34 @@
 static bool
 separate_class_package (tree decl)
 {
-  if (decl) 
-    {
-      tree type = TREE_TYPE (decl);
-      return type
-	&& TREE_CODE (type) == RECORD_TYPE
-	&& (TYPE_METHODS (type) || has_static_fields (type));
-    }
-  else
-    return false;
+  tree type = TREE_TYPE (decl);
+  return has_nontrivial_methods (type) || has_static_fields (type);
 }
 
 static bool package_prefix = true;
 
 /* Dump in BUFFER the name of an identifier NODE of type TYPE, following Ada
-   syntax.  LIMITED_ACCESS indicates whether NODE can be accessed via a limited
+   syntax.  INDEX, if non-zero, is used to disambiguate overloaded names.
+   LIMITED_ACCESS indicates whether NODE can be accessed via a limited
    'with' clause rather than a regular 'with' clause.  */
 
 static void
 pp_ada_tree_identifier (pretty_printer *buffer, tree node, tree type,
-			int limited_access)
+			unsigned int index, bool limited_access)
 {
   const char *name = IDENTIFIER_POINTER (node);
-  int space_found = false;
-  char *s = to_ada_name (name, &space_found);
-  tree decl;
-
-  /* If the entity is a type and comes from another file, generate "package"
-     prefix.  */
-
-  decl = get_underlying_decl (type);
-
+  bool space_found = false;
+  char *s = to_ada_name (name, index, &space_found);
+  tree decl = get_underlying_decl (type);
+
+  /* If the entity comes from another file, generate a package prefix.  */
   if (decl)
     {
       expanded_location xloc = expand_location (decl_sloc (decl, false));
 
       if (xloc.file && xloc.line)
 	{
-	  if (xloc.file != source_file_base)
+	  if (xloc.file != current_source_file)
 	    {
 	      switch (TREE_CODE (type))
 		{
@@ -1210,32 +1344,28 @@
 		  case ARRAY_TYPE:
 		  case RECORD_TYPE:
 		  case UNION_TYPE:
-		  case QUAL_UNION_TYPE:
 		  case TYPE_DECL:
-		    {
-		      char *s1 = get_ada_package (xloc.file);
-
-		      if (package_prefix)
-			{
-			  append_withs (s1, limited_access);
-			  pp_string (buffer, s1);
-			  pp_character (buffer, '.');
-			}
-		      free (s1);
-		    }
+		    if (package_prefix)
+		      {
+			char *s1 = get_ada_package (xloc.file);
+			append_withs (s1, limited_access);
+			pp_string (buffer, s1);
+			pp_dot (buffer);
+			free (s1);
+		      }
 		    break;
 		  default:
 		    break;
 		}
-              
-              if (separate_class_package (decl))
-                {
-                  pp_string (buffer, "Class_");
-                  pp_string (buffer, s);
-                  pp_string (buffer, ".");
-                }
-
-            }
+
+	      /* Generate the additional package prefix for C++ classes.  */
+	      if (separate_class_package (decl))
+		{
+		  pp_string (buffer, "Class_");
+		  pp_string (buffer, s);
+		  pp_dot (buffer);
+		}
+	     }
 	}
     }
 
@@ -1302,15 +1432,86 @@
   pp_string (buffer, ada_name);
 }
 
+/* Hash table of overloaded names associating identifier nodes with DECL_UIDs.
+   It is needed in Ada 2005 because we can have at most one import directive
+   per subprogram name in a given scope, so we have to mangle the subprogram
+   names on the Ada side to import overloaded subprograms from C++.  */
+
+struct overloaded_name_hash {
+  hashval_t hash;
+  tree name;
+  tree context;
+  vec<unsigned int> homonyms;
+};
+
+struct overloaded_name_hasher : delete_ptr_hash<overloaded_name_hash>
+{
+  static inline hashval_t hash (overloaded_name_hash *t)
+    { return t->hash; }
+  static inline bool equal (overloaded_name_hash *a, overloaded_name_hash *b)
+    { return a->name == b->name && a->context == b->context; }
+};
+
+static hash_table<overloaded_name_hasher> *overloaded_names;
+
+/* Compute the overloading index of function DECL in its context.  */
+
+static unsigned int
+compute_overloading_index (tree decl)
+{
+  const hashval_t hashcode
+    = iterative_hash_hashval_t (htab_hash_pointer (DECL_NAME (decl)),
+			        htab_hash_pointer (DECL_CONTEXT (decl)));
+  struct overloaded_name_hash in, *h, **slot;
+  unsigned int index, *iter;
+
+  if (!overloaded_names)
+    overloaded_names = new hash_table<overloaded_name_hasher> (512);
+
+  /* Look up the list of homonyms in the table.  */
+  in.hash = hashcode;
+  in.name = DECL_NAME (decl);
+  in.context = DECL_CONTEXT (decl);
+  slot = overloaded_names->find_slot_with_hash (&in, hashcode, INSERT);
+  if (*slot)
+    h = *slot;
+  else
+    {
+      h = new overloaded_name_hash;
+      h->hash = hashcode;
+      h->name = DECL_NAME (decl);
+      h->context = DECL_CONTEXT (decl);
+      h->homonyms.create (0);
+      *slot = h;
+    }
+
+  /* Look up the function in the list of homonyms.  */
+  FOR_EACH_VEC_ELT (h->homonyms, index, iter)
+    if (*iter == DECL_UID (decl))
+      break;
+
+  /* If it is not present, push it onto the list.  */
+  if (!iter)
+    h->homonyms.safe_push (DECL_UID (decl));
+
+  return index;
+}
+
 /* Dump in BUFFER the name of a DECL node if set, following Ada syntax.
    LIMITED_ACCESS indicates whether NODE can be accessed via a limited
    'with' clause rather than a regular 'with' clause.  */
 
 static void
-dump_ada_decl_name (pretty_printer *buffer, tree decl, int limited_access)
+dump_ada_decl_name (pretty_printer *buffer, tree decl, bool limited_access)
 {
   if (DECL_NAME (decl))
-    pp_ada_tree_identifier (buffer, DECL_NAME (decl), decl, limited_access);
+    {
+      const unsigned int index
+	= (TREE_CODE (decl) == FUNCTION_DECL && cpp_check)
+	  ? compute_overloading_index (decl) : 0;
+      pp_ada_tree_identifier (buffer, DECL_NAME (decl), decl, index,
+			      limited_access);
+    }
   else
     {
       tree type_name = TYPE_NAME (TREE_TYPE (decl));
@@ -1324,34 +1525,48 @@
 	    pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (decl)));
 	}
       else if (TREE_CODE (type_name) == IDENTIFIER_NODE)
-	pp_ada_tree_identifier (buffer, type_name, decl, limited_access);
+	pp_ada_tree_identifier (buffer, type_name, decl, 0, limited_access);
     }
 }
 
-/* Dump in BUFFER a name based on both T1 and T2, followed by S.  */
+/* Dump in BUFFER a name based on both T1 and T2 followed by a suffix.  */
 
 static void
-dump_ada_double_name (pretty_printer *buffer, tree t1, tree t2, const char *s)
+dump_ada_double_name (pretty_printer *buffer, tree t1, tree t2)
 {
   if (DECL_NAME (t1))
-    pp_ada_tree_identifier (buffer, DECL_NAME (t1), t1, false);
+    pp_ada_tree_identifier (buffer, DECL_NAME (t1), t1, 0, false);
   else
     {
       pp_string (buffer, "anon");
       pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t1)));
     }
 
-  pp_character (buffer, '_');
-
-  if (DECL_NAME (t1))
-    pp_ada_tree_identifier (buffer, DECL_NAME (t2), t2, false);
+  pp_underscore (buffer);
+
+  if (DECL_NAME (t2))
+    pp_ada_tree_identifier (buffer, DECL_NAME (t2), t2, 0, false);
   else
     {
       pp_string (buffer, "anon");
       pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t2)));
     }
 
-  pp_string (buffer, s);
+  switch (TREE_CODE (TREE_TYPE (t2)))
+    {
+    case ARRAY_TYPE:
+      pp_string (buffer, "_array");
+      break;
+    case RECORD_TYPE:
+      pp_string (buffer, "_struct");
+      break;
+    case UNION_TYPE:
+      pp_string (buffer, "_union");
+      break;
+    default:
+      pp_string (buffer, "_unknown");
+      break;
+    }
 }
 
 /* Dump in BUFFER pragma Import C/CPP on a given node T.  */
@@ -1365,7 +1580,7 @@
 
   if (is_stdcall)
     pp_string (buffer, "pragma Import (Stdcall, ");
-  else if (name [0] == '_' && name [1] == 'Z')
+  else if (name[0] == '_' && name[1] == 'Z')
     pp_string (buffer, "pragma Import (CPP, ");
   else
     pp_string (buffer, "pragma Import (C, ");
@@ -1415,14 +1630,14 @@
    IS_DESTRUCTOR whether FUNC is a C++ destructor.
    SPC is the current indentation level.  */
 
-static int
+static void
 dump_ada_function_declaration (pretty_printer *buffer, tree func,
-			       int is_method, int is_constructor,
-			       int is_destructor, int spc)
+			       bool is_method, bool is_constructor,
+			       bool is_destructor, int spc)
 {
   tree arg;
   const tree node = TREE_TYPE (func);
-  char buf [16];
+  char buf[17];
   int num = 0, num_args = 0, have_args = true, have_ellipsis = false;
 
   /* Compute number of arguments.  */
@@ -1455,7 +1670,7 @@
   if (num_args > 0)
     {
       pp_space (buffer);
-      pp_character (buffer, '(');
+      pp_left_paren (buffer);
     }
 
   if (TREE_CODE (func) == FUNCTION_DECL)
@@ -1484,7 +1699,8 @@
 	  if (DECL_NAME (arg))
 	    {
 	      check_name (buffer, arg);
-	      pp_ada_tree_identifier (buffer, DECL_NAME (arg), 0, false);
+	      pp_ada_tree_identifier (buffer, DECL_NAME (arg), NULL_TREE, 0,
+				      false);
 	      pp_string (buffer, " : ");
 	    }
 	  else
@@ -1493,30 +1709,33 @@
 	      pp_string (buffer, buf);
 	    }
 
-	  dump_generic_ada_node
-	    (buffer, TREE_TYPE (arg), node, NULL, spc, 0, true);
+	  dump_generic_ada_node (buffer, TREE_TYPE (arg), node, spc, 0, true);
 	}
       else
 	{
 	  sprintf (buf, "arg%d : ", num);
 	  pp_string (buffer, buf);
-	  dump_generic_ada_node
-	    (buffer, TREE_VALUE (arg), node, NULL, spc, 0, true);
+	  dump_generic_ada_node (buffer, TREE_VALUE (arg), node, spc, 0, true);
 	}
 
-      if (TREE_TYPE (arg) && TREE_TYPE (TREE_TYPE (arg))
-	  && is_tagged_type (TREE_TYPE (TREE_TYPE (arg))))
-	{
-	  if (!is_method
-	      || (num != 1 || (!DECL_VINDEX (func) && !is_constructor)))
-	    pp_string (buffer, "'Class");
-	}
+      /* If the type is a pointer to a tagged type, we need to differentiate
+	 virtual methods from the rest (non-virtual methods, static member
+	 or regular functions) and import only them as primitive operations,
+	 because they make up the virtual table which is mirrored on the Ada
+	 side by the dispatch table.  So we add 'Class to the type of every
+	 parameter that is not the first one of a method which either has a
+	 slot in the virtual table or is a constructor.  */
+      if (TREE_TYPE (arg)
+	  && POINTER_TYPE_P (TREE_TYPE (arg))
+	  && is_tagged_type (TREE_TYPE (TREE_TYPE (arg)))
+	  && !(num == 1 && is_method && (DECL_VINDEX (func) || is_constructor)))
+	pp_string (buffer, "'Class");
 
       arg = TREE_CHAIN (arg);
 
       if (num < num_args)
 	{
-	  pp_character (buffer, ';');
+	  pp_semicolon (buffer);
 
 	  if (num_args > 2)
 	    newline_and_indent (buffer, spc + INDENT_INCR);
@@ -1532,8 +1751,14 @@
     }
 
   if (num_args > 0)
-    pp_character (buffer, ')');
-  return num_args;
+    pp_right_paren (buffer);
+
+  if (is_constructor || !VOID_TYPE_P (TREE_TYPE (node)))
+    {
+      pp_string (buffer, " return ");
+      tree type = is_constructor ? DECL_CONTEXT (func) : TREE_TYPE (node);
+      dump_generic_ada_node (buffer, type, type, spc, false, true);
+    }
 }
 
 /* Dump in BUFFER all the domains associated with an array NODE,
@@ -1543,7 +1768,7 @@
 dump_ada_array_domains (pretty_printer *buffer, tree node, int spc)
 {
   int first = 1;
-  pp_character (buffer, '(');
+  pp_left_paren (buffer);
 
   for (; TREE_CODE (node) == ARRAY_TYPE; node = TREE_TYPE (node))
     {
@@ -1559,20 +1784,20 @@
 	  first = 0;
 
 	  if (min)
-	    dump_generic_ada_node (buffer, min, NULL_TREE, NULL, spc, 0, true);
+	    dump_generic_ada_node (buffer, min, NULL_TREE, spc, 0, true);
 	  pp_string (buffer, " .. ");
 
 	  /* If the upper bound is zero, gcc may generate a NULL_TREE
 	     for TYPE_MAX_VALUE rather than an integer_cst.  */
 	  if (max)
-	    dump_generic_ada_node (buffer, max, NULL_TREE, NULL, spc, 0, true);
+	    dump_generic_ada_node (buffer, max, NULL_TREE, spc, 0, true);
 	  else
 	    pp_string (buffer, "0");
 	}
       else
 	pp_string (buffer, "size_t");
     }
-  pp_character (buffer, ')');
+  pp_right_paren (buffer);
 }
 
 /* Dump in BUFFER file:line information related to NODE.  */
@@ -1584,7 +1809,7 @@
 
   xloc.file = NULL;
 
-  if (TREE_CODE_CLASS (TREE_CODE (node)) == tcc_declaration)
+  if (DECL_P (node))
     xloc = expand_location (DECL_SOURCE_LOCATION (node));
   else if (EXPR_HAS_LOCATION (node))
     xloc = expand_location (EXPR_LOCATION (node));
@@ -1592,7 +1817,7 @@
   if (xloc.file)
     {
       pp_string (buffer, xloc.file);
-      pp_string (buffer, ":");
+      pp_colon (buffer);
       pp_decimal_int (buffer, xloc.line);
     }
 }
@@ -1615,18 +1840,18 @@
 
   tmp = TREE_TYPE (tmp);
   return num_dim == 1 && TREE_CODE (tmp) == INTEGER_TYPE
-    && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (tmp))), "char");
+    && id_equal (DECL_NAME (TYPE_NAME (tmp)), "char");
 }
 
 /* Dump in BUFFER an array type T in Ada syntax.  Assume that the "type"
-   keyword and name have already been printed.  SPC is the indentation
-   level.  */
+   keyword and name have already been printed.  PARENT is the parent node of T.
+   SPC is the indentation level.  */
 
 static void
-dump_ada_array_type (pretty_printer *buffer, tree t, int spc)
+dump_ada_array_type (pretty_printer *buffer, tree t, tree parent, int spc)
 {
+  const bool char_array = is_char_array (t);
   tree tmp;
-  bool char_array = is_char_array (t);
 
   /* Special case char arrays.  */
   if (char_array)
@@ -1639,9 +1864,9 @@
   /* Print the dimensions.  */
   dump_ada_array_domains (buffer, TREE_TYPE (t), spc);
 
-  /* Retrieve array's type.  */
+  /* Retrieve the element type.  */
   tmp = TREE_TYPE (t);
-  while (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
+  while (TREE_CODE (tmp) == ARRAY_TYPE)
     tmp = TREE_TYPE (tmp);
 
   /* Print array's type.  */
@@ -1649,22 +1874,22 @@
     {
       pp_string (buffer, " of ");
 
-      if (TREE_CODE (TREE_TYPE (tmp)) != POINTER_TYPE)
+      if (TREE_CODE (tmp) != POINTER_TYPE)
 	pp_string (buffer, "aliased ");
 
-      dump_generic_ada_node
-	(buffer, TREE_TYPE (tmp), TREE_TYPE (t), NULL, spc, false, true);
+      if (TYPE_NAME (tmp) || !RECORD_OR_UNION_TYPE_P (tmp))
+	dump_generic_ada_node (buffer, tmp, TREE_TYPE (t), spc, false, true);
+      else
+	dump_ada_double_name (buffer, parent, get_underlying_decl (tmp));
     }
 }
 
 /* Dump in BUFFER type names associated with a template, each prepended with
-   '_'.  TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS.
-   CPP_CHECK is used to perform C++ queries on nodes.
-   SPC is the indentation level.  */
+   '_'.  TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS.  SPC is
+   the indentation level.  */
 
 static void
-dump_template_types (pretty_printer *buffer, tree types,
-		     int (*cpp_check)(tree, cpp_operation), int spc)
+dump_template_types (pretty_printer *buffer, tree types, int spc)
 {
   size_t i;
   size_t len = TREE_VEC_LENGTH (types);
@@ -1672,8 +1897,8 @@
   for (i = 0; i < len; i++)
     {
       tree elem = TREE_VEC_ELT (types, i);
-      pp_character (buffer, '_');
-      if (!dump_generic_ada_node (buffer, elem, 0, cpp_check, spc, false, true))
+      pp_underscore (buffer);
+      if (!dump_generic_ada_node (buffer, elem, 0, spc, false, true))
 	{
 	  pp_string (buffer, "unknown");
 	  pp_scalar (buffer, "%lu", (unsigned long) TREE_HASH (elem));
@@ -1681,19 +1906,30 @@
     }
 }
 
-/* Dump in BUFFER the contents of all instantiations associated with a given
-   template T.  CPP_CHECK is used to perform C++ queries on nodes.
-   SPC is the indentation level. */
+/* Dump in BUFFER the contents of all class instantiations associated with
+   a given template T.  SPC is the indentation level.  */
 
 static int
-dump_ada_template (pretty_printer *buffer, tree t,
-		   int (*cpp_check)(tree, cpp_operation), int spc)
+dump_ada_template (pretty_printer *buffer, tree t, int spc)
 {
-  tree inst = DECL_VINDEX (t);
-  /* DECL_VINDEX is DECL_TEMPLATE_INSTANTIATIONS in this context.  */
+  /* DECL_SIZE_UNIT is DECL_TEMPLATE_INSTANTIATIONS in this context.  */
+  tree inst = DECL_SIZE_UNIT (t);
+  /* This emulates DECL_TEMPLATE_RESULT in this context.  */
+  struct tree_template_decl {
+    struct tree_decl_common common;
+    tree arguments;
+    tree result;
+  };
+  tree result = ((struct tree_template_decl *) t)->result;
   int num_inst = 0;
 
-  while (inst && inst != error_mark_node)
+  /* Don't look at template declarations declaring something coming from
+     another file.  This can occur for template friend declarations.  */
+  if (LOCATION_FILE (decl_sloc (result, false))
+      != LOCATION_FILE (decl_sloc (t, false)))
+    return 0;
+
+  for (; inst && inst != error_mark_node; inst = TREE_CHAIN (inst))
     {
       tree types = TREE_PURPOSE (inst);
       tree instance = TREE_VALUE (inst);
@@ -1701,22 +1937,29 @@
       if (TREE_VEC_LENGTH (types) == 0)
 	break;
 
-      if (!TYPE_METHODS (instance))
+      if (!RECORD_OR_UNION_TYPE_P (instance))
 	break;
 
+      /* We are interested in concrete template instantiations only: skip
+	 partially specialized nodes.  */
+      if (RECORD_OR_UNION_TYPE_P (instance)
+	  && cpp_check
+	  && cpp_check (instance, HAS_DEPENDENT_TEMPLATE_ARGS))
+	continue;
+
       num_inst++;
       INDENT (spc);
       pp_string (buffer, "package ");
       package_prefix = false;
-      dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
-      dump_template_types (buffer, types, cpp_check, spc);
+      dump_generic_ada_node (buffer, instance, t, spc, false, true);
+      dump_template_types (buffer, types, spc);
       pp_string (buffer, " is");
       spc += INDENT_INCR;
       newline_and_indent (buffer, spc);
 
       TREE_VISITED (get_underlying_decl (instance)) = 1;
       pp_string (buffer, "type ");
-      dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
+      dump_generic_ada_node (buffer, instance, t, spc, false, true);
       package_prefix = true;
 
       if (is_tagged_type (instance))
@@ -1724,7 +1967,7 @@
       else
 	pp_string (buffer, " is limited ");
 
-      dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, false);
+      dump_generic_ada_node (buffer, instance, t, spc, false, false);
       pp_newline (buffer);
       spc -= INDENT_INCR;
       newline_and_indent (buffer, spc);
@@ -1733,14 +1976,12 @@
       newline_and_indent (buffer, spc);
       pp_string (buffer, "use ");
       package_prefix = false;
-      dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true);
-      dump_template_types (buffer, types, cpp_check, spc);
+      dump_generic_ada_node (buffer, instance, t, spc, false, true);
+      dump_template_types (buffer, types, spc);
       package_prefix = true;
       pp_semicolon (buffer);
       pp_newline (buffer);
       pp_newline (buffer);
-
-      inst = TREE_CHAIN (inst);
     }
 
   return num_inst > 0;
@@ -1752,7 +1993,7 @@
 static bool
 is_simple_enum (tree node)
 {
-  unsigned HOST_WIDE_INT count = 0;
+  HOST_WIDE_INT count = 0;
   tree value;
 
   for (value = TYPE_VALUES (node); value; value = TREE_CHAIN (value))
@@ -1762,9 +2003,9 @@
       if (TREE_CODE (int_val) != INTEGER_CST)
 	int_val = DECL_INITIAL (int_val);
 
-      if (!host_integerp (int_val, 0))
+      if (!tree_fits_shwi_p (int_val))
 	return false;
-      else if (TREE_INT_CST_LOW (int_val) != count)
+      else if (tree_to_shwi (int_val) != count)
 	return false;
 
       count++;
@@ -1773,19 +2014,16 @@
   return true;
 }
 
-static bool in_function = true;
 static bool bitfield_used = false;
 
 /* Recursively dump in BUFFER Ada declarations corresponding to NODE of type
-   TYPE.  CPP_CHECK is used to perform C++ queries on nodes.  SPC is the
-   indentation level.  LIMITED_ACCESS indicates whether NODE can be referenced
-   via a "limited with" clause.  NAME_ONLY indicates whether we should only
-   dump the name of NODE, instead of its full declaration.  */
+   TYPE.  SPC is the indentation level.  LIMITED_ACCESS indicates whether NODE
+   can be referenced via a "limited with" clause.  NAME_ONLY indicates whether
+   we should only dump the name of NODE, instead of its full declaration.  */
 
 static int
-dump_generic_ada_node (pretty_printer *buffer, tree node, tree type,
-		       int (*cpp_check)(tree, cpp_operation), int spc,
-		       int limited_access, bool name_only)
+dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
+		       bool limited_access, bool name_only)
 {
   if (node == NULL_TREE)
     return 0;
@@ -1797,7 +2035,7 @@
       return 0;
 
     case IDENTIFIER_NODE:
-      pp_ada_tree_identifier (buffer, node, type, limited_access);
+      pp_ada_tree_identifier (buffer, node, type, 0, limited_access);
       break;
 
     case TREE_LIST:
@@ -1806,8 +2044,8 @@
 
     case TREE_BINFO:
       dump_generic_ada_node
-	(buffer, BINFO_TYPE (node), type, cpp_check,
-	 spc, limited_access, name_only);
+	(buffer, BINFO_TYPE (node), type, spc, limited_access, name_only);
+      return 0;
 
     case TREE_VEC:
       pp_string (buffer, "--- unexpected node: TREE_VEC");
@@ -1833,8 +2071,7 @@
 
     case ENUMERAL_TYPE:
       if (name_only)
-	dump_generic_ada_node
-	  (buffer, TYPE_NAME (node), node, cpp_check, spc, 0, true);
+	dump_generic_ada_node (buffer, TYPE_NAME (node), node, spc, 0, true);
       else
 	{
 	  tree value = TYPE_VALUES (node);
@@ -1844,19 +2081,19 @@
 	      bool first = true;
 	      spc += INDENT_INCR;
 	      newline_and_indent (buffer, spc - 1);
-	      pp_string (buffer, "(");
+	      pp_left_paren (buffer);
 	      for (; value; value = TREE_CHAIN (value))
 		{
 		  if (first)
 		    first = false;
 		  else
 		    {
-		      pp_string (buffer, ",");
+		      pp_comma (buffer);
 		      newline_and_indent (buffer, spc);
 		    }
 
-		  pp_ada_tree_identifier
-		    (buffer, TREE_PURPOSE (value), node, false);
+		  pp_ada_tree_identifier (buffer, TREE_PURPOSE (value), node,
+					  0, false);
 		}
 	      pp_string (buffer, ");");
 	      spc -= INDENT_INCR;
@@ -1864,31 +2101,34 @@
 	      pp_string (buffer, "pragma Convention (C, ");
 	      dump_generic_ada_node
 		(buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
-		 cpp_check, spc, 0, true);
-	      pp_string (buffer, ")");
+		 spc, 0, true);
+	      pp_right_paren (buffer);
 	    }
 	  else
 	    {
-	      pp_string (buffer, "unsigned");
+	      if (TYPE_UNSIGNED (node))
+		pp_string (buffer, "unsigned");
+	      else
+		pp_string (buffer, "int");
 	      for (; value; value = TREE_CHAIN (value))
 		{
 		  pp_semicolon (buffer);
 		  newline_and_indent (buffer, spc);
 
-		  pp_ada_tree_identifier
-		    (buffer, TREE_PURPOSE (value), node, false);
+		  pp_ada_tree_identifier (buffer, TREE_PURPOSE (value), node,
+					  0, false);
 		  pp_string (buffer, " : constant ");
 
 		  dump_generic_ada_node
 		    (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
-		     cpp_check, spc, 0, true);
+		     spc, 0, true);
 
 		  pp_string (buffer, " := ");
 		  dump_generic_ada_node
 		    (buffer,
 		     TREE_CODE (TREE_VALUE (value)) == INTEGER_CST ?
 		       TREE_VALUE (value) : DECL_INITIAL (TREE_VALUE (value)),
-		     node, cpp_check, spc, false, true);
+		     node, spc, false, true);
 		}
 	    }
 	}
@@ -1906,8 +2146,8 @@
 	if (tclass == tcc_declaration)
 	  {
 	    if (DECL_NAME (node))
-	      pp_ada_tree_identifier
-		(buffer, DECL_NAME (node), 0, limited_access);
+	      pp_ada_tree_identifier (buffer, DECL_NAME (node), NULL_TREE, 0,
+				      limited_access);
 	    else
 	      pp_string (buffer, "<unnamed type decl>");
 	  }
@@ -1916,8 +2156,8 @@
 	    if (TYPE_NAME (node))
 	      {
 		if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
-		  pp_ada_tree_identifier (buffer, TYPE_NAME (node),
-					  node, limited_access);
+		  pp_ada_tree_identifier (buffer, TYPE_NAME (node), node, 0,
+					  limited_access);
 		else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
 			 && DECL_NAME (TYPE_NAME (node)))
 		  dump_ada_decl_name (buffer, TYPE_NAME (node), limited_access);
@@ -1947,33 +2187,29 @@
 
     case POINTER_TYPE:
     case REFERENCE_TYPE:
-      if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
+      if (name_only && TYPE_NAME (node))
+	dump_generic_ada_node
+	  (buffer, TYPE_NAME (node), node, spc, limited_access, true);
+
+      else if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
 	{
-	  tree fnode = TREE_TYPE (node);
-	  bool is_function;
-	  bool prev_in_function = in_function;
-
-	  if (VOID_TYPE_P (TREE_TYPE (fnode)))
-	    {
-	      is_function = false;
-	      pp_string (buffer, "access procedure");
-	    }
+	  if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (node))))
+	    pp_string (buffer, "access procedure ");
 	  else
-	    {
-	      is_function = true;
-	      pp_string (buffer, "access function");
-	    }
-
-	  in_function = is_function;
+	    pp_string (buffer, "access function ");
+
 	  dump_ada_function_declaration
 	    (buffer, node, false, false, false, spc + INDENT_INCR);
-	  in_function = prev_in_function;
-
-	  if (is_function)
+
+	  /* If we are dumping the full type, it means we are part of a
+	     type definition and need also a Convention C pragma.  */
+	  if (!name_only)
 	    {
-	      pp_string (buffer, " return ");
-	      dump_generic_ada_node
-		(buffer, TREE_TYPE (fnode), type, cpp_check, spc, 0, true);
+	      pp_semicolon (buffer);
+	      newline_and_indent (buffer, spc);
+	      pp_string (buffer, "pragma Convention (C, ");
+	      dump_generic_ada_node (buffer, type, 0, spc, false, true);
+	      pp_right_paren (buffer);
 	    }
 	}
       else
@@ -1981,11 +2217,7 @@
 	  int is_access = false;
 	  unsigned int quals = TYPE_QUALS (TREE_TYPE (node));
 
-	  if (name_only && TYPE_NAME (node))
-	    dump_generic_ada_node
-	      (buffer, TYPE_NAME (node), node, cpp_check,
-	       spc, limited_access, true);
-	  else if (VOID_TYPE_P (TREE_TYPE (node)))
+	  if (VOID_TYPE_P (TREE_TYPE (node)))
 	    {
 	      if (!name_only)
 		pp_string (buffer, "new ");
@@ -2018,37 +2250,25 @@
 		}
 	      else
 		{
-		  /* For now, handle all access-to-access or
-		     access-to-unknown-structs as opaque system.address.  */
-
 		  tree type_name = TYPE_NAME (TREE_TYPE (node));
-		  const_tree typ2 = !type ||
-		    DECL_P (type) ? type : TYPE_NAME (type);
-		  const_tree underlying_type =
-		    get_underlying_decl (TREE_TYPE (node));
-
+		  tree decl = get_underlying_decl (TREE_TYPE (node));
+		  tree enclosing_decl = get_underlying_decl (type);
+
+		  /* For now, handle access-to-access, access-to-empty-struct
+		     or access-to-incomplete as opaque system.address.  */
 		  if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE
-		      /* Pointer to pointer.  */
-
 		      || (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
-			  && (!underlying_type
-			      || !TYPE_FIELDS (TREE_TYPE (underlying_type))))
-		      /* Pointer to opaque structure.  */
-
-		      || underlying_type == NULL_TREE
-		      || (!typ2
-			  && !TREE_VISITED (underlying_type)
-			  && !TREE_VISITED (type_name)
-			  && !is_tagged_type (TREE_TYPE (node))
-			  && DECL_SOURCE_FILE (underlying_type)
-			       == source_file_base)
-		      || (type_name && typ2
-			  && DECL_P (underlying_type)
-			  && DECL_P (typ2)
-			  && decl_sloc (underlying_type, true)
-			       > decl_sloc (typ2, true)
-			  && DECL_SOURCE_FILE (underlying_type)
-			       == DECL_SOURCE_FILE (typ2)))
+			  && !TYPE_FIELDS (TREE_TYPE (node)))
+		      || !decl
+		      || (!enclosing_decl
+			  && !TREE_VISITED (decl)
+			  && DECL_SOURCE_FILE (decl) == current_source_file)
+		      || (enclosing_decl
+			  && !TREE_VISITED (decl)
+			  && DECL_SOURCE_FILE (decl)
+			       == DECL_SOURCE_FILE (enclosing_decl)
+			  && decl_sloc (decl, true)
+			       > decl_sloc (enclosing_decl, true)))
 		    {
 		      if (package_prefix)
 			{
@@ -2078,11 +2298,6 @@
 			}
 		      else if (quals & TYPE_QUAL_CONST)
 			pp_string (buffer, "in ");
-		      else if (in_function)
-			{
-			  is_access = true;
-			  pp_string (buffer, "access ");
-			}
 		      else
 			{
 			  is_access = true;
@@ -2099,15 +2314,12 @@
 			pp_string (buffer, "all ");
 		    }
 
-		  if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
-		      && type_name != NULL_TREE)
-		    dump_generic_ada_node
-		      (buffer, type_name,
-		       TREE_TYPE (node), cpp_check, spc, is_access, true);
+		  if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node)) && type_name)
+		    dump_generic_ada_node (buffer, type_name, TREE_TYPE (node),
+					   spc, is_access, true);
 		  else
-		    dump_generic_ada_node
-		      (buffer, TREE_TYPE (node), TREE_TYPE (node),
-		       cpp_check, spc, 0, true);
+		    dump_generic_ada_node (buffer, TREE_TYPE (node),
+					   TREE_TYPE (node), spc, 0, true);
 		}
 	    }
 	}
@@ -2116,21 +2328,18 @@
     case ARRAY_TYPE:
       if (name_only)
 	dump_generic_ada_node
-	  (buffer, TYPE_NAME (node), node, cpp_check,
-	   spc, limited_access, true);
+	  (buffer, TYPE_NAME (node), node, spc, limited_access, true);
       else
-	dump_ada_array_type (buffer, node, spc);
+	dump_ada_array_type (buffer, node, type, spc);
       break;
 
     case RECORD_TYPE:
     case UNION_TYPE:
-    case QUAL_UNION_TYPE:
       if (name_only)
 	{
 	  if (TYPE_NAME (node))
 	    dump_generic_ada_node
-	      (buffer, TYPE_NAME (node), node, cpp_check,
-	       spc, limited_access, true);
+	      (buffer, TYPE_NAME (node), node, spc, limited_access, true);
 	  else
 	    {
 	      pp_string (buffer, "anon_");
@@ -2138,35 +2347,36 @@
 	    }
 	}
       else
-	print_ada_struct_decl
-	  (buffer, node, type, cpp_check, spc, true);
+	dump_ada_struct_decl (buffer, node, type, spc, true);
       break;
 
     case INTEGER_CST:
-      if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE)
-	{
-	  pp_wide_integer (buffer, TREE_INT_CST_LOW (node));
-	  pp_string (buffer, "B"); /* pseudo-unit */
-	}
-      else if (!host_integerp (node, 0))
+      /* We treat the upper half of the sizetype range as negative.  This
+	 is consistent with the internal treatment and makes it possible
+	 to generate the (0 .. -1) range for flexible array members.  */
+      if (TREE_TYPE (node) == sizetype)
+	node = fold_convert (ssizetype, node);
+      if (tree_fits_shwi_p (node))
+	pp_wide_integer (buffer, tree_to_shwi (node));
+      else if (tree_fits_uhwi_p (node))
+	pp_unsigned_wide_integer (buffer, tree_to_uhwi (node));
+      else
 	{
-	  tree val = node;
-	  unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (val);
-	  HOST_WIDE_INT high = TREE_INT_CST_HIGH (val);
-
-	  if (tree_int_cst_sgn (val) < 0)
+	  wide_int val = wi::to_wide (node);
+	  int i;
+	  if (wi::neg_p (val))
 	    {
-	      pp_character (buffer, '-');
-	      high = ~high + !low;
-	      low = -low;
+	      pp_minus (buffer);
+	      val = -val;
 	    }
 	  sprintf (pp_buffer (buffer)->digit_buffer,
-	  HOST_WIDE_INT_PRINT_DOUBLE_HEX,
-	    (unsigned HOST_WIDE_INT) high, low);
+		   "16#%" HOST_WIDE_INT_PRINT "x",
+		   val.elt (val.get_len () - 1));
+	  for (i = val.get_len () - 2; i >= 0; i--)
+	    sprintf (pp_buffer (buffer)->digit_buffer,
+		     HOST_WIDE_INT_PRINT_PADDED_HEX, val.elt (i));
 	  pp_string (buffer, pp_buffer (buffer)->digit_buffer);
 	}
-      else
-	pp_wide_integer (buffer, TREE_INT_CST_LOW (node));
       break;
 
     case REAL_CST:
@@ -2176,11 +2386,6 @@
     case VECTOR_CST:
       return 0;
 
-    case FUNCTION_DECL:
-    case CONST_DECL:
-      dump_ada_decl_name (buffer, node, limited_access);
-      break;
-
     case TYPE_DECL:
       if (DECL_IS_BUILTIN (node))
 	{
@@ -2207,13 +2412,14 @@
 	{
 	  if (is_tagged_type (TREE_TYPE (node)))
 	    {
-	      tree tmp = TYPE_FIELDS (TREE_TYPE (node));
 	      int first = 1;
 
 	      /* Look for ancestors.  */
-	      for (; tmp; tmp = TREE_CHAIN (tmp))
+	      for (tree fld = TYPE_FIELDS (TREE_TYPE (node));
+		   fld;
+		   fld = TREE_CHAIN (fld))
 		{
-		  if (!DECL_NAME (tmp) && is_tagged_type (TREE_TYPE (tmp)))
+		  if (!DECL_NAME (fld) && is_tagged_type (TREE_TYPE (fld)))
 		    {
 		      if (first)
 			{
@@ -2223,22 +2429,23 @@
 		      else
 			pp_string (buffer, " and ");
 
-		      dump_ada_decl_name
-			(buffer, TYPE_NAME (TREE_TYPE (tmp)), false);
+		      dump_ada_decl_name (buffer, TYPE_NAME (TREE_TYPE (fld)),
+					  false);
 		    }
 		}
 
 	      pp_string (buffer, first ? "tagged limited " : " with ");
 	    }
-	  else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
-		   && TYPE_METHODS (TREE_TYPE (node)))
+	  else if (has_nontrivial_methods (TREE_TYPE (node)))
 	    pp_string (buffer, "limited ");
 
 	  dump_generic_ada_node
-	    (buffer, TREE_TYPE (node), type, cpp_check, spc, false, false);
+	    (buffer, TREE_TYPE (node), type, spc, false, false);
 	}
       break;
 
+    case FUNCTION_DECL:
+    case CONST_DECL:
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
@@ -2254,235 +2461,232 @@
   return 1;
 }
 
-/* Dump in BUFFER NODE's methods.  CPP_CHECK is used to perform C++ queries on
-   nodes.  SPC is the indentation level.  */
-
-static void
-print_ada_methods (pretty_printer *buffer, tree node,
-		   int (*cpp_check)(tree, cpp_operation), int spc)
+/* Dump in BUFFER NODE's methods.  SPC is the indentation level.  Return 1 if
+   methods were printed, 0 otherwise.  */
+
+static int
+dump_ada_methods (pretty_printer *buffer, tree node, int spc)
 {
-  tree tmp = TYPE_METHODS (node);
+  if (!has_nontrivial_methods (node))
+    return 0;
+
+  pp_semicolon (buffer);
+
   int res = 1;
-
-  if (tmp)
-    {
-      pp_semicolon (buffer);
-
-      for (; tmp; tmp = TREE_CHAIN (tmp))
-	{
-	  if (res)
-	    {
-	      pp_newline (buffer);
-	      pp_newline (buffer);
-	    }
-	  res = print_ada_declaration (buffer, tmp, node, cpp_check, spc);
-	}
-    }
+  for (tree fld = TYPE_FIELDS (node); fld; fld = DECL_CHAIN (fld))
+    if (TREE_CODE (fld) == FUNCTION_DECL)
+      {
+	if (res)
+	  {
+	    pp_newline (buffer);
+	    pp_newline (buffer);
+	  }
+
+	res = dump_ada_declaration (buffer, fld, node, spc);
+      }
+
+  return 1;
 }
 
+static void dump_nested_type (pretty_printer *, tree, tree, tree, int);
+
 /* Dump in BUFFER anonymous types nested inside T's definition.
    PARENT is the parent node of T.
    FORWARD indicates whether a forward declaration of T should be generated.
-   CPP_CHECK is used to perform C++ queries on
-   nodes.  SPC is the indentation level.  */
+   SPC is the indentation level.
+
+   In C anonymous nested tagged types have no name whereas in C++ they have
+   one.  In C their TYPE_DECL is at top level whereas in C++ it is nested.
+   In both languages untagged types (pointers and arrays) have no name.
+   In C++ the nested TYPE_DECLs can come after their associated FIELD_DECL.
+
+   Therefore, in order to have a common processing for both languages, we
+   disregard anonymous TYPE_DECLs at top level and here we make a first
+   pass on the nested TYPE_DECLs and a second pass on the unnamed types.  */
 
 static void
 dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward,
-		   int (*cpp_check)(tree, cpp_operation), int spc)
+		   int spc)
 {
-  tree field, outer, decl;
+  tree type, field;
 
   /* Avoid recursing over the same tree.  */
   if (TREE_VISITED (t))
     return;
 
-  /* Find possible anonymous arrays/unions/structs recursively.  */
-
-  outer = TREE_TYPE (t);
-
-  if (outer == NULL_TREE)
+  /* Find possible anonymous pointers/arrays/structs/unions recursively.  */
+  type = TREE_TYPE (t);
+  if (type == NULL_TREE)
     return;
 
   if (forward)
     {
       pp_string (buffer, "type ");
-      dump_generic_ada_node
-	(buffer, t, t, cpp_check, spc, false, true);
+      dump_generic_ada_node (buffer, t, t, spc, false, true);
       pp_semicolon (buffer);
       newline_and_indent (buffer, spc);
       TREE_VISITED (t) = 1;
     }
 
-  field = TYPE_FIELDS (outer);
-  while (field)
+  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+    if (TREE_CODE (field) == TYPE_DECL
+	&& DECL_NAME (field) != DECL_NAME (t)
+	&& TYPE_NAME (TREE_TYPE (field)) != TYPE_NAME (type))
+      dump_nested_type (buffer, field, t, parent, spc);
+
+  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+    if (TREE_CODE (field) == FIELD_DECL && !TYPE_NAME (TREE_TYPE (field)))
+      dump_nested_type (buffer, field, t, parent, spc);
+
+  TREE_VISITED (t) = 1;
+}
+
+/* Dump in BUFFER the anonymous type of FIELD inside T.
+   PARENT is the parent node of T.
+   FORWARD indicates whether a forward declaration of T should be generated.
+   SPC is the indentation level.  */
+
+static void
+dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent,
+		  int spc)
+{
+  tree field_type = TREE_TYPE (field);
+  tree decl, tmp;
+
+  switch (TREE_CODE (field_type))
     {
-      if ((TREE_TYPE (field) != outer
-	   || (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
-	       && TREE_TYPE (TREE_TYPE (field)) != outer))
-	   && (!TYPE_NAME (TREE_TYPE (field))
-	      || (TREE_CODE (field) == TYPE_DECL
-		  && DECL_NAME (field) != DECL_NAME (t)
-		  && TYPE_NAME (TREE_TYPE (field)) != TYPE_NAME (outer))))
+    case POINTER_TYPE:
+      tmp = TREE_TYPE (field_type);
+
+      if (TREE_CODE (tmp) == FUNCTION_TYPE)
+	for (tmp = TREE_TYPE (tmp);
+	     tmp && TREE_CODE (tmp) == POINTER_TYPE;
+	     tmp = TREE_TYPE (tmp))
+	  ;
+
+      decl = get_underlying_decl (tmp);
+      if (decl
+	  && !DECL_IS_BUILTIN (decl)
+	  && (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
+	      || TYPE_FIELDS (TREE_TYPE (decl)))
+	  && !TREE_VISITED (decl)
+	  && DECL_SOURCE_FILE (decl) == DECL_SOURCE_FILE (t)
+	  && decl_sloc (decl, true) > decl_sloc (t, true))
+	{
+	  /* Generate forward declaration.  */
+	  pp_string (buffer, "type ");
+	  dump_generic_ada_node (buffer, decl, 0, spc, false, true);
+	  pp_semicolon (buffer);
+	  newline_and_indent (buffer, spc);
+	  TREE_VISITED (decl) = 1;
+	}
+      break;
+
+    case ARRAY_TYPE:
+      tmp = TREE_TYPE (field_type);
+      while (TREE_CODE (tmp) == ARRAY_TYPE)
+	tmp = TREE_TYPE (tmp);
+      decl = get_underlying_decl (tmp);
+      if (decl && !DECL_NAME (decl) && !TREE_VISITED (decl))
 	{
-	  switch (TREE_CODE (TREE_TYPE (field)))
+	  /* Generate full declaration.  */
+	  dump_nested_type (buffer, decl, t, parent, spc);
+	  TREE_VISITED (decl) = 1;
+	}
+
+      /* Special case char arrays.  */
+      if (is_char_array (field))
+	pp_string (buffer, "sub");
+
+      pp_string (buffer, "type ");
+      dump_ada_double_name (buffer, parent, field);
+      pp_string (buffer, " is ");
+      dump_ada_array_type (buffer, field, parent, spc);
+      pp_semicolon (buffer);
+      newline_and_indent (buffer, spc);
+      break;
+
+    case RECORD_TYPE:
+    case UNION_TYPE:
+      if (TYPE_NAME (TREE_TYPE (t)) && !TREE_VISITED (t))
+	{
+	  pp_string (buffer, "type ");
+	  dump_generic_ada_node (buffer, t, parent, spc, false, true);
+	  pp_semicolon (buffer);
+	  newline_and_indent (buffer, spc);
+	}
+
+      TREE_VISITED (t) = 1;
+      dump_nested_types (buffer, field, t, false, spc);
+
+      pp_string (buffer, "type ");
+
+      if (TYPE_NAME (field_type))
+	{
+	  dump_generic_ada_node (buffer, field_type, 0, spc, false, true);
+	  if (TREE_CODE (field_type) == UNION_TYPE)
+	    pp_string (buffer, " (discr : unsigned := 0)");
+	  pp_string (buffer, " is ");
+	  dump_ada_struct_decl (buffer, field_type, t, spc, false);
+
+	  pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
+	  dump_generic_ada_node (buffer, field_type, 0, spc, false, true);
+	  pp_string (buffer, ");");
+	  newline_and_indent (buffer, spc);
+
+	  if (TREE_CODE (field_type) == UNION_TYPE)
 	    {
-	      case POINTER_TYPE:
-		decl = TREE_TYPE (TREE_TYPE (field));
-
-		if (TREE_CODE (decl) == FUNCTION_TYPE)
-		  for (decl = TREE_TYPE (decl);
-		       decl && TREE_CODE (decl) == POINTER_TYPE;
-		       decl = TREE_TYPE (decl));
-
-		decl = get_underlying_decl (decl);
-
-		if (decl
-		    && DECL_P (decl)
-		    && decl_sloc (decl, true) > decl_sloc (t, true)
-		    && DECL_SOURCE_FILE (decl) == DECL_SOURCE_FILE (t)
-		    && !TREE_VISITED (decl)
-		    && !DECL_IS_BUILTIN (decl)
-		    && (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
-			|| TYPE_FIELDS (TREE_TYPE (decl))))
-		  {
-		    /* Generate forward declaration.  */
-
-		    pp_string (buffer, "type ");
-		    dump_generic_ada_node
-		      (buffer, decl, 0, cpp_check, spc, false, true);
-		    pp_semicolon (buffer);
-		    newline_and_indent (buffer, spc);
-
-		    /* Ensure we do not generate duplicate forward
-		       declarations for this type.  */
-		    TREE_VISITED (decl) = 1;
-		  }
-		break;
-
-	      case ARRAY_TYPE:
-		/* Special case char arrays.  */
-		if (is_char_array (field))
-		  pp_string (buffer, "sub");
-
-		pp_string (buffer, "type ");
-		dump_ada_double_name (buffer, parent, field, "_array is ");
-		dump_ada_array_type (buffer, field, spc);
-		pp_semicolon (buffer);
-		newline_and_indent (buffer, spc);
-		break;
-
-	      case UNION_TYPE:
-		TREE_VISITED (t) = 1;
-		dump_nested_types (buffer, field, t, false, cpp_check, spc);
-
-		pp_string (buffer, "type ");
-
-		if (TYPE_NAME (TREE_TYPE (field)))
-		  {
-		    dump_generic_ada_node
-		      (buffer, TYPE_NAME (TREE_TYPE (field)), 0, cpp_check,
-		       spc, false, true);
-		    pp_string (buffer, " (discr : unsigned := 0) is ");
-		    print_ada_struct_decl
-		      (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
-
-		    pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
-		    dump_generic_ada_node
-		      (buffer, TREE_TYPE (field), 0, cpp_check,
-		       spc, false, true);
-		    pp_string (buffer, ");");
-		    newline_and_indent (buffer, spc);
-
-		    pp_string (buffer, "pragma Unchecked_Union (");
-		    dump_generic_ada_node
-		      (buffer, TREE_TYPE (field), 0, cpp_check,
-		       spc, false, true);
-		    pp_string (buffer, ");");
-		  }
-		else
-		  {
-		    dump_ada_double_name
-		      (buffer, parent, field,
-		       	"_union (discr : unsigned := 0) is ");
-		    print_ada_struct_decl
-		      (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
-		    pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
-		    dump_ada_double_name (buffer, parent, field, "_union);");
-		    newline_and_indent (buffer, spc);
-
-		    pp_string (buffer, "pragma Unchecked_Union (");
-		    dump_ada_double_name (buffer, parent, field, "_union);");
-		  }
-
-		newline_and_indent (buffer, spc);
-		break;
-
-	      case RECORD_TYPE:
-		if (TYPE_NAME (TREE_TYPE (t)) && !TREE_VISITED (t))
-		  {
-		    pp_string (buffer, "type ");
-		    dump_generic_ada_node
-		      (buffer, t, parent, 0, spc, false, true);
-		    pp_semicolon (buffer);
-		    newline_and_indent (buffer, spc);
-		  }
-
-		TREE_VISITED (t) = 1;
-		dump_nested_types (buffer, field, t, false, cpp_check, spc);
-		pp_string (buffer, "type ");
-
-		if (TYPE_NAME (TREE_TYPE (field)))
-		  {
-		    dump_generic_ada_node
-		      (buffer, TREE_TYPE (field), 0, cpp_check,
-		       spc, false, true);
-		    pp_string (buffer, " is ");
-		    print_ada_struct_decl
-		      (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
-		    pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
-		    dump_generic_ada_node
-		      (buffer, TREE_TYPE (field), 0, cpp_check,
-		       spc, false, true);
-		    pp_string (buffer, ");");
-		  }
-		else
-		  {
-		    dump_ada_double_name
-		      (buffer, parent, field, "_struct is ");
-		    print_ada_struct_decl
-		      (buffer, TREE_TYPE (field), t, cpp_check, spc, false);
-		    pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
-		    dump_ada_double_name (buffer, parent, field, "_struct);");
-		  }
-
-		newline_and_indent (buffer, spc);
-		break;
-
-	      default:
-		break;
+	      pp_string (buffer, "pragma Unchecked_Union (");
+	      dump_generic_ada_node (buffer, field_type, 0, spc, false, true);
+	      pp_string (buffer, ");");
 	    }
 	}
-      field = TREE_CHAIN (field);
+      else
+	{
+	  dump_ada_double_name (buffer, parent, field);
+	  if (TREE_CODE (field_type) == UNION_TYPE)
+	    pp_string (buffer, " (discr : unsigned := 0)");
+	  pp_string (buffer, " is ");
+	  dump_ada_struct_decl (buffer, field_type, t, spc, false);
+
+	  pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
+	  dump_ada_double_name (buffer, parent, field);
+	  pp_string (buffer, ");");
+	  newline_and_indent (buffer, spc);
+
+	  if (TREE_CODE (field_type) == UNION_TYPE)
+	    {
+	      pp_string (buffer, "pragma Unchecked_Union (");
+	      dump_ada_double_name (buffer, parent, field);
+	      pp_string (buffer, ");");
+	    }
+	}
+
+    default:
+      break;
     }
-
-  TREE_VISITED (t) = 1;
+}
+
+/* Dump in BUFFER constructor spec corresponding to T for TYPE.  */
+
+static void
+print_constructor (pretty_printer *buffer, tree t, tree type)
+{
+  tree decl_name = DECL_NAME (TYPE_NAME (type));
+
+  pp_string (buffer, "New_");
+  pp_ada_tree_identifier (buffer, decl_name, t, 0, false);
 }
 
 /* Dump in BUFFER destructor spec corresponding to T.  */
 
 static void
-print_destructor (pretty_printer *buffer, tree t)
+print_destructor (pretty_printer *buffer, tree t, tree type)
 {
-  const char *s = IDENTIFIER_POINTER (DECL_NAME (t));
-
-  if (*s == '_')
-    for (s += 2; *s != ' '; s++)
-      pp_character (buffer, *s);
-  else
-    {
-      pp_string (buffer, "Delete_");
-      pp_ada_tree_identifier (buffer, DECL_NAME (t), t, false);
-    }
+  tree decl_name = DECL_NAME (TYPE_NAME (type));
+
+  pp_string (buffer, "Delete_");
+  pp_ada_tree_identifier (buffer, decl_name, t, 0, false);
 }
 
 /* Return the name of type T.  */
@@ -2498,23 +2702,21 @@
     return IDENTIFIER_POINTER (DECL_NAME (n));
 }
 
-/* Print in BUFFER the declaration of a variable T of type TYPE in Ada syntax.
-   CPP_CHECK is used to perform C++ queries on nodes.  SPC is the indentation
-   level.  Return 1 if a declaration was printed, 0 otherwise.  */
+/* Dump in BUFFER the declaration of a variable T of type TYPE in Ada syntax.
+   SPC is the indentation level.  Return 1 if a declaration was printed,
+   0 otherwise.  */
 
 static int
-print_ada_declaration (pretty_printer *buffer, tree t, tree type,
-		       int (*cpp_check)(tree, cpp_operation), int spc)
+dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
 {
   int is_var = 0, need_indent = 0;
   int is_class = false;
   tree name = TYPE_NAME (TREE_TYPE (t));
   tree decl_name = DECL_NAME (t);
-  bool dump_internal = get_dump_file_info (TDI_ada)->flags & TDF_RAW;
   tree orig = NULL_TREE;
 
   if (cpp_check && cpp_check (t, IS_TEMPLATE))
-    return dump_ada_template (buffer, t, cpp_check, spc);
+    return dump_ada_template (buffer, t, spc);
 
   if (TREE_CODE (t) == CONST_DECL && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
     /* Skip enumeral values: will be handled as part of the type itself.  */
@@ -2535,71 +2737,49 @@
 		 casing), then ignore the second type.  */
 	      if (type_name (typ) == type_name (TREE_TYPE (t))
 		  || !strcasecmp (type_name (typ), type_name (TREE_TYPE (t))))
-		return 0;
+		{
+		  TREE_VISITED (t) = 1;
+		  return 0;
+		}
 
 	      INDENT (spc);
 
 	      if (RECORD_OR_UNION_TYPE_P (typ) && !TYPE_FIELDS (typ))
 		{
 		  pp_string (buffer, "--  skipped empty struct ");
-		  dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+		  dump_generic_ada_node (buffer, t, type, spc, false, true);
 		}
 	      else
 		{
-		  if (!TREE_VISITED (stub)
-		      && DECL_SOURCE_FILE (stub) == source_file_base)
-		    dump_nested_types
-		      (buffer, stub, stub, true, cpp_check, spc);
+		  if (RECORD_OR_UNION_TYPE_P (typ)
+		      && DECL_SOURCE_FILE (stub) == current_source_file)
+		    dump_nested_types (buffer, stub, stub, true, spc);
 
 		  pp_string (buffer, "subtype ");
-		  dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+		  dump_generic_ada_node (buffer, t, type, spc, false, true);
 		  pp_string (buffer, " is ");
-		  dump_generic_ada_node
-		    (buffer, typ, type, 0, spc, false, true);
-		  pp_semicolon (buffer);
+		  dump_generic_ada_node (buffer, typ, type, spc, false, true);
+		  pp_string (buffer, ";  -- ");
+		  dump_sloc (buffer, t);
 		}
+
+	      TREE_VISITED (t) = 1;
 	      return 1;
 	    }
 	}
 
       /* Skip unnamed or anonymous structs/unions/enum types.  */
-      if (!orig && !decl_name && !name)
-	{
-	  tree tmp;
-	  location_t sloc;
-
-	  if (cpp_check || TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
-	    return 0;
-
-	  if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
-	    {
-	      /* Search next items until finding a named type decl.  */
-	      sloc = decl_sloc_common (t, true, true);
-
-	      for (tmp = TREE_CHAIN (t); tmp; tmp = TREE_CHAIN (tmp))
-		{
-		  if (TREE_CODE (tmp) == TYPE_DECL
-		      && (DECL_NAME (tmp) || TYPE_NAME (TREE_TYPE (tmp))))
-		    {
-		      /* If same sloc, it means we can ignore the anonymous
-			 struct.  */
-		      if (decl_sloc_common (tmp, true, true) == sloc)
-			return 0;
-		      else
-			break;
-		    }
-		}
-	      if (tmp == NULL)
-		return 0;
-	    }
-	}
-
+      if (!orig && !decl_name && !name
+	  && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))
+	      || TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE))
+	return 0;
+
+	/* Skip anonymous enum types (duplicates of real types).  */
       if (!orig
 	  && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE
 	  && decl_name
 	  && (*IDENTIFIER_POINTER (decl_name) == '.'
 	      || *IDENTIFIER_POINTER (decl_name) == '$'))
-	/* Skip anonymous enum types (duplicates of real types).  */
 	return 0;
 
       INDENT (spc);
@@ -2608,13 +2788,12 @@
 	{
 	  case RECORD_TYPE:
 	  case UNION_TYPE:
-	  case QUAL_UNION_TYPE:
 	    /* Skip empty structs (typically forward references to real
 	       structs).  */
 	    if (!TYPE_FIELDS (TREE_TYPE (t)))
 	      {
 		pp_string (buffer, "--  skipped empty struct ");
-		dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+		dump_generic_ada_node (buffer, t, type, spc, false, true);
 		return 1;
 	      }
 
@@ -2623,7 +2802,7 @@
 		    || *IDENTIFIER_POINTER (decl_name) == '$'))
 	      {
 		pp_string (buffer, "--  skipped anonymous struct ");
-		dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+		dump_generic_ada_node (buffer, t, type, spc, false, true);
 		TREE_VISITED (t) = 1;
 		return 1;
 	      }
@@ -2632,14 +2811,13 @@
 	      pp_string (buffer, "subtype ");
 	    else
 	      {
-		dump_nested_types (buffer, t, t, false, cpp_check, spc);
+		dump_nested_types (buffer, t, t, false, spc);
 
                 if (separate_class_package (t))
 		  {
 		    is_class = true;
 		    pp_string (buffer, "package Class_");
-		    dump_generic_ada_node
-		      (buffer, t, type, 0, spc, false, true);
+		    dump_generic_ada_node (buffer, t, type, spc, false, true);
 		    pp_string (buffer, " is");
 		    spc += INDENT_INCR;
 		    newline_and_indent (buffer, spc);
@@ -2661,9 +2839,8 @@
 
 	  case FUNCTION_TYPE:
 	    pp_string (buffer, "--  skipped function type ");
-	    dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+	    dump_generic_ada_node (buffer, t, type, spc, false, true);
 	    return 1;
-	    break;
 
 	  case ENUMERAL_TYPE:
 	    if ((orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
@@ -2680,8 +2857,7 @@
     }
   else
     {
-      if (!dump_internal
-	  && TREE_CODE (t) == VAR_DECL
+      if (VAR_P (t)
 	  && decl_name
 	  && *IDENTIFIER_POINTER (decl_name) == '_')
 	return 0;
@@ -2696,7 +2872,7 @@
 	INDENT (spc);
 
       /* Print variable's name.  */
-      dump_generic_ada_node (buffer, t, type, cpp_check, spc, false, true);
+      dump_generic_ada_node (buffer, t, type, spc, false, true);
 
       if (TREE_CODE (t) == TYPE_DECL)
 	{
@@ -2704,10 +2880,9 @@
 
 	  if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
 	    dump_generic_ada_node
-	      (buffer, TYPE_NAME (orig), type,
-	       cpp_check, spc, false, true);
+	      (buffer, TYPE_NAME (orig), type, spc, false, true);
 	  else
-	    dump_ada_array_type (buffer, t, spc);
+	    dump_ada_array_type (buffer, t, type, spc);
 	}
       else
 	{
@@ -2718,34 +2893,27 @@
 
 	  pp_string (buffer, " : ");
 
+	  if (TREE_CODE (TREE_TYPE (TREE_TYPE (t))) != POINTER_TYPE)
+	    pp_string (buffer, "aliased ");
+
 	  if (tmp)
-	    {
-	      if (TREE_CODE (TREE_TYPE (tmp)) != POINTER_TYPE
-		  && TREE_CODE (tmp) != INTEGER_TYPE)
-		pp_string (buffer, "aliased ");
-
-	      dump_generic_ada_node (buffer, tmp, type, 0, spc, false, true);
-	    }
+	    dump_generic_ada_node (buffer, tmp, type, spc, false, true);
+	  else if (type)
+	    dump_ada_double_name (buffer, type, t);
 	  else
-	    {
-	      pp_string (buffer, "aliased ");
-
-	      if (!type)
-		dump_ada_array_type (buffer, t, spc);
-	      else
-		dump_ada_double_name (buffer, type, t, "_array");
-	    }
+	    dump_ada_array_type (buffer, t, type, spc);
 	}
     }
   else if (TREE_CODE (t) == FUNCTION_DECL)
     {
-      bool is_function = true, is_method, is_abstract_class = false;
+      bool is_abstract_class = false;
+      bool is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
       tree decl_name = DECL_NAME (t);
-      int prev_in_function = in_function;
       bool is_abstract = false;
       bool is_constructor = false;
       bool is_destructor = false;
       bool is_copy_constructor = false;
+      bool is_move_constructor = false;
 
       if (!decl_name)
 	return 0;
@@ -2756,27 +2924,29 @@
 	  is_constructor = cpp_check (t, IS_CONSTRUCTOR);
 	  is_destructor = cpp_check (t, IS_DESTRUCTOR);
 	  is_copy_constructor = cpp_check (t, IS_COPY_CONSTRUCTOR);
+	  is_move_constructor = cpp_check (t, IS_MOVE_CONSTRUCTOR);
 	}
 
-      /* Skip __comp_dtor destructor which is redundant with the '~class()'
-	 destructor.  */
-      if (is_destructor
-	  && !strncmp (IDENTIFIER_POINTER (decl_name), "__comp", 6))
+      /* Skip copy constructors and C++11 move constructors: some are internal
+	 only and those that are not cannot be called easily from Ada.  */
+      if (is_copy_constructor || is_move_constructor)
 	return 0;
 
-      /* Skip copy constructors: some are internal only, and those that are
-	 not cannot be called easily from Ada anyway.  */
-      if (is_copy_constructor)
-	return 0;
-
-      /* If this function has an entry in the dispatch table, we cannot
-	 omit it.  */
-      if (!dump_internal && !DECL_VINDEX (t)
-	  && *IDENTIFIER_POINTER (decl_name) == '_')
+      if (is_constructor || is_destructor)
 	{
-	  if (IDENTIFIER_POINTER (decl_name)[1] == '_')
+	  /* ??? Skip implicit constructors/destructors for now.  */
+	  if (DECL_ARTIFICIAL (t))
 	    return 0;
 
+	  /* Only consider constructors/destructors for complete objects.  */
+	  if (strncmp (IDENTIFIER_POINTER (decl_name), "__ct_comp", 9) != 0
+	      && strncmp (IDENTIFIER_POINTER (decl_name), "__dt_comp", 9) != 0)
+	    return 0;
+	}
+
+      /* If this function has an entry in the vtable, we cannot omit it.  */
+      else if (!DECL_VINDEX (t) && *IDENTIFIER_POINTER (decl_name) == '_')
+	{
 	  INDENT (spc);
 	  pp_string (buffer, "--  skipped func ");
 	  pp_string (buffer, IDENTIFIER_POINTER (decl_name));
@@ -2786,57 +2956,28 @@
       if (need_indent)
 	INDENT (spc);
 
-      if (is_constructor)
-	pp_string (buffer, "function New_");
-      else if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (t))))
-	{
-	  is_function = false;
-	  pp_string (buffer, "procedure ");
-	}
+      if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (t))) && !is_constructor)
+	pp_string (buffer, "procedure ");
       else
 	pp_string (buffer, "function ");
 
-      in_function = is_function;
-      is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
-
-      if (is_destructor)
-	print_destructor (buffer, t);
+      if (is_constructor)
+	print_constructor (buffer, t, type);
+      else if (is_destructor)
+	print_destructor (buffer, t, type);
       else
 	dump_ada_decl_name (buffer, t, false);
 
       dump_ada_function_declaration
 	(buffer, t, is_method, is_constructor, is_destructor, spc);
-      in_function = prev_in_function;
-
-      if (is_function)
-	{
-	  pp_string (buffer, " return ");
-
-	  if (is_constructor)
+
+      if (is_constructor && RECORD_OR_UNION_TYPE_P (type))
+	for (tree fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
+	  if (TREE_CODE (fld) == FUNCTION_DECL && cpp_check (fld, IS_ABSTRACT))
 	    {
-	      dump_ada_decl_name (buffer, t, false);
-	    }
-	  else
-	    {
-	      dump_generic_ada_node
-		(buffer, TREE_TYPE (TREE_TYPE (t)), type, cpp_check,
-		 spc, false, true);
+	      is_abstract_class = true;
+	      break;
 	    }
-	}
-
-      if (is_constructor && cpp_check && type
-	  && AGGREGATE_TYPE_P (type)
-	  && TYPE_METHODS (type))
-	{
-	  tree tmp = TYPE_METHODS (type);
-
-	  for (; tmp; tmp = TREE_CHAIN (tmp))
-	    if (cpp_check (tmp, IS_ABSTRACT))
-	      {
-		is_abstract_class = 1;
-		break;
-	      }
-	}
 
       if (is_abstract || is_abstract_class)
 	pp_string (buffer, " is abstract");
@@ -2845,15 +2986,15 @@
       pp_string (buffer, "  -- ");
       dump_sloc (buffer, t);
 
-      if (is_abstract)
+      if (is_abstract || !DECL_ASSEMBLER_NAME (t))
 	return 1;
 
       newline_and_indent (buffer, spc);
 
       if (is_constructor)
 	{
-	  pp_string (buffer, "pragma CPP_Constructor (New_");
-	  dump_ada_decl_name (buffer, t, false);
+	  pp_string (buffer, "pragma CPP_Constructor (");
+	  print_constructor (buffer, t, type);
 	  pp_string (buffer, ", \"");
 	  pp_asm_name (buffer, t);
 	  pp_string (buffer, "\");");
@@ -2861,15 +3002,13 @@
       else if (is_destructor)
 	{
 	  pp_string (buffer, "pragma Import (CPP, ");
-	  print_destructor (buffer, t);
+	  print_destructor (buffer, t, type);
 	  pp_string (buffer, ", \"");
 	  pp_asm_name (buffer, t);
 	  pp_string (buffer, "\");");
 	}
       else
-	{
-	  dump_ada_import (buffer, t);
-	}
+	dump_ada_import (buffer, t);
 
       return 1;
     }
@@ -2882,42 +3021,44 @@
 	INDENT (spc);
 
       /* Anonymous structs/unions */
-      dump_generic_ada_node
-	(buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
-
-      if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
-	  || TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE)
+      dump_generic_ada_node (buffer, TREE_TYPE (t), t, spc, false, true);
+
+      if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE)
 	{
 	  pp_string (buffer, " (discr : unsigned := 0)");
 	}
 
       pp_string (buffer, " is ");
 
-      /* Check whether we have an Ada interface compatible class.  */
-      if (cpp_check && AGGREGATE_TYPE_P (TREE_TYPE (t))
-	  && TYPE_METHODS (TREE_TYPE (t)))
+      /* Check whether we have an Ada interface compatible class.
+	 That is only have a vtable non-static data member and no
+	 non-abstract methods.  */
+      if (cpp_check
+	  && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
 	{
-	  int num_fields = 0;
-	  tree tmp = TYPE_FIELDS (TREE_TYPE (t));
+	  bool has_fields = false;
 
 	  /* Check that there are no fields other than the virtual table.  */
-	  for (; tmp; tmp = TREE_CHAIN (tmp))
+	  for (tree fld = TYPE_FIELDS (TREE_TYPE (t));
+	       fld;
+	       fld = TREE_CHAIN (fld))
 	    {
-	      if (TREE_CODE (tmp) == TYPE_DECL)
-		continue;
-	      num_fields++;
-	    }
-
-	  if (num_fields == 1)
-	    is_interface = 1;
-
-	  /* Also check that there are only virtual methods.  */
-	  for (tmp = TYPE_METHODS (TREE_TYPE (t)); tmp; tmp = TREE_CHAIN (tmp))
-	    {
-	      if (cpp_check (tmp, IS_ABSTRACT))
-		is_abstract_record = 1;
-	      else
-		is_interface = 0;
+	      if (TREE_CODE (fld) == FIELD_DECL)
+		{
+		  if (!has_fields && DECL_VIRTUAL_P (fld))
+		    is_interface = 1;
+		  else
+		    is_interface = 0;
+		  has_fields = true;
+		}
+	      else if (TREE_CODE (fld) == FUNCTION_DECL
+		       && !DECL_ARTIFICIAL (fld))
+		{
+		  if (cpp_check (fld, IS_ABSTRACT))
+		    is_abstract_record = 1;
+		  else
+		    is_interface = 0;
+		}
 	    }
 	}
 
@@ -2929,17 +3070,16 @@
 	  newline_and_indent (buffer, spc);
 	  pp_string (buffer, "pragma Import (CPP, ");
  	  dump_generic_ada_node
-	    (buffer, TYPE_NAME (TREE_TYPE (t)), type, cpp_check,
-	     spc, false, true);
-  	  pp_character (buffer, ')');
-
-	  print_ada_methods (buffer, TREE_TYPE (t), cpp_check, spc);
+	    (buffer, TYPE_NAME (TREE_TYPE (t)), type, spc, false, true);
+  	  pp_right_paren (buffer);
+
+	  dump_ada_methods (buffer, TREE_TYPE (t), spc);
 	}
       else
 	{
 	  if (is_abstract_record)
 	    pp_string (buffer, "abstract ");
-	  dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, false);
+	  dump_generic_ada_node (buffer, t, t, spc, false, false);
 	}
     }
   else
@@ -2951,22 +3091,19 @@
 	check_name (buffer, t);
 
       /* Print variable/type's name.  */
-      dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, true);
+      dump_generic_ada_node (buffer, t, t, spc, false, true);
 
       if (TREE_CODE (t) == TYPE_DECL)
 	{
 	  tree orig = DECL_ORIGINAL_TYPE (t);
 	  int is_subtype = orig && TYPE_NAME (orig) && orig != TREE_TYPE (t);
 
-	  if (!is_subtype
-	      && (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
-		  || TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE))
+	  if (!is_subtype && TREE_CODE (TREE_TYPE (t)) == UNION_TYPE)
 	    pp_string (buffer, " (discr : unsigned := 0)");
 
 	  pp_string (buffer, " is ");
 
-	  dump_generic_ada_node
-	    (buffer, orig, t, cpp_check, spc, false, is_subtype);
+	  dump_generic_ada_node (buffer, orig, t, spc, false, is_subtype);
 	}
       else
 	{
@@ -2975,20 +3112,18 @@
 
 	  pp_string (buffer, " : ");
 
-	  /* Print type declaration.  */
-
-	  if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
-	      && !TYPE_NAME (TREE_TYPE (t)))
+	  if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
 	    {
-	      dump_ada_double_name (buffer, type, t, "_union");
-	    }
-	  else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
-	    {
-	      if (TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE)
-		pp_string (buffer, "aliased ");
-
-	      dump_generic_ada_node
-		(buffer, TREE_TYPE (t), t, cpp_check, spc, false, true);
+	      pp_string (buffer, "aliased ");
+
+	      if (TREE_READONLY (t))
+		pp_string (buffer, "constant ");
+
+	      if (TYPE_NAME (TREE_TYPE (t)))
+		dump_generic_ada_node
+		  (buffer, TREE_TYPE (t), t, spc, false, true);
+	      else if (type)
+		dump_ada_double_name (buffer, type, t);
 	    }
 	  else
 	    {
@@ -2997,21 +3132,23 @@
 		      || TREE_CODE (TREE_TYPE (t)) != INTEGER_TYPE))
 		pp_string (buffer, "aliased ");
 
+	      if (TREE_READONLY (t))
+		pp_string (buffer, "constant ");
+
 	      dump_generic_ada_node
-		(buffer, TREE_TYPE (t), TREE_TYPE (t), cpp_check,
-		 spc, false, true);
+		(buffer, TREE_TYPE (t), TREE_TYPE (t), spc, false, true);
 	    }
 	}
     }
 
   if (is_class)
     {
-      spc -= 3;
+      spc -= INDENT_INCR;
       newline_and_indent (buffer, spc);
       pp_string (buffer, "end;");
       newline_and_indent (buffer, spc);
       pp_string (buffer, "use Class_");
-      dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+      dump_generic_ada_node (buffer, t, type, spc, false, true);
       pp_semicolon (buffer);
       pp_newline (buffer);
 
@@ -3033,34 +3170,28 @@
   return 1;
 }
 
-/* Prints in BUFFER a structure NODE of type TYPE: name, fields, and methods
-   with Ada syntax.  CPP_CHECK is used to perform C++ queries on nodes.  SPC
-   is the indentation level.  If DISPLAY_CONVENTION is true, also print the
-   pragma Convention for NODE.  */
+/* Dump in BUFFER a structure NODE of type TYPE: name, fields, and methods
+   with Ada syntax.  SPC is the indentation level.  If DISPLAY_CONVENTION is
+   true, also print the pragma Convention for NODE.  */
 
 static void
-print_ada_struct_decl (pretty_printer *buffer, tree node, tree type,
-		       int (*cpp_check)(tree, cpp_operation), int spc,
+dump_ada_struct_decl (pretty_printer *buffer, tree node, tree type, int spc,
 		       bool display_convention)
 {
   tree tmp;
-  int is_union =
-    TREE_CODE (node) == UNION_TYPE || TREE_CODE (node) == QUAL_UNION_TYPE;
-  char buf [16];
+  const bool is_union = (TREE_CODE (node) == UNION_TYPE);
+  char buf[32];
   int field_num = 0;
   int field_spc = spc + INDENT_INCR;
   int need_semicolon;
 
   bitfield_used = false;
 
-  if (!TYPE_FIELDS (node))
-    pp_string (buffer, "null record;");
-  else
+  if (TYPE_FIELDS (node))
     {
+      /* Print the contents of the structure.  */
       pp_string (buffer, "record");
 
-      /* Print the contents of the structure.  */
-
       if (is_union)
 	{
 	  newline_and_indent (buffer, spc + INDENT_INCR);
@@ -3079,17 +3210,16 @@
 	      if (!is_tagged_type (TREE_TYPE (tmp)))
 		{
 		  if (!TYPE_NAME (TREE_TYPE (tmp)))
-		    print_ada_declaration
-		      (buffer, tmp, type, cpp_check, field_spc);
+		    dump_ada_declaration (buffer, tmp, type, field_spc);
 		  else
 		    {
 		      INDENT (field_spc);
 
 		      if (field_num == 0)
-			pp_string (buffer, "parent : ");
+			pp_string (buffer, "parent : aliased ");
 		      else
 			{
-			  sprintf (buf, "field_%d : ", field_num + 1);
+			  sprintf (buf, "field_%d : aliased ", field_num + 1);
 			  pp_string (buffer, buf);
 			}
 		      dump_ada_decl_name
@@ -3100,15 +3230,10 @@
 		  field_num++;
 		}
 	    }
-	  /* Avoid printing the structure recursively.  */
-	  else if ((TREE_TYPE (tmp) != node
-		   || (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE
-		       && TREE_TYPE (TREE_TYPE (tmp)) != node))
-		   && TREE_CODE (tmp) != TYPE_DECL
-		   && !TREE_STATIC (tmp))
+	  else if (TREE_CODE (tmp) == FIELD_DECL)
 	    {
 	      /* Skip internal virtual table field.  */
-	      if (strncmp (IDENTIFIER_POINTER (DECL_NAME (tmp)), "_vptr", 5))
+	      if (!DECL_VIRTUAL_P (tmp))
 		{
 		  if (is_union)
 		    {
@@ -3124,8 +3249,7 @@
 		      pp_newline (buffer);
 		    }
 
-		  if (print_ada_declaration (buffer,
-					     tmp, type, cpp_check, field_spc))
+		  if (dump_ada_declaration (buffer, tmp, type, field_spc))
 		    {
 		      pp_newline (buffer);
 		      field_num++;
@@ -3151,6 +3275,8 @@
       INDENT (spc);
       pp_string (buffer, "end record;");
     }
+  else
+    pp_string (buffer, "null record;");
 
   newline_and_indent (buffer, spc);
 
@@ -3159,7 +3285,7 @@
 
   if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
     {
-      if (TYPE_METHODS (TREE_TYPE (type)))
+      if (has_nontrivial_methods (TREE_TYPE (type)))
 	pp_string (buffer, "pragma Import (CPP, ");
       else
 	pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
@@ -3168,10 +3294,9 @@
     pp_string (buffer, "pragma Convention (C, ");
 
   package_prefix = false;
-  dump_generic_ada_node
-    (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
+  dump_generic_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
   package_prefix = true;
-  pp_character (buffer, ')');
+  pp_right_paren (buffer);
 
   if (is_union)
     {
@@ -3179,9 +3304,8 @@
       newline_and_indent (buffer, spc);
       pp_string (buffer, "pragma Unchecked_Union (");
 
-      dump_generic_ada_node
-	(buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
-      pp_character (buffer, ')');
+      dump_generic_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
+      pp_right_paren (buffer);
     }
 
   if (bitfield_used)
@@ -3190,18 +3314,17 @@
       newline_and_indent (buffer, spc);
       pp_string (buffer, "pragma Pack (");
       dump_generic_ada_node
-	(buffer, TREE_TYPE (type), type, cpp_check, spc, false, true);
-      pp_character (buffer, ')');
+	(buffer, TREE_TYPE (type), type, spc, false, true);
+      pp_right_paren (buffer);
       bitfield_used = false;
     }
 
-  print_ada_methods (buffer, node, cpp_check, spc);
+  need_semicolon = !dump_ada_methods (buffer, node, spc);
 
   /* Print the static fields of the structure, if any.  */
-  need_semicolon = TYPE_METHODS (node) == NULL_TREE;
   for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
     {
-      if (DECL_NAME (tmp) && TREE_STATIC (tmp))
+      if (TREE_CODE (tmp) == VAR_DECL && DECL_NAME (tmp))
 	{
 	  if (need_semicolon)
 	    {
@@ -3210,20 +3333,19 @@
 	    }
 	  pp_newline (buffer);
 	  pp_newline (buffer);
-	  print_ada_declaration (buffer, tmp, type, cpp_check, spc);
+	  dump_ada_declaration (buffer, tmp, type, spc);
 	}
     }
 }
 
 /* Dump all the declarations in SOURCE_FILE to an Ada spec.
    COLLECT_ALL_REFS is a front-end callback used to collect all relevant
-   nodes for SOURCE_FILE.  CPP_CHECK is used to perform C++ queries on
-   nodes.  */
+   nodes for SOURCE_FILE.  CHECK is used to perform C++ queries on nodes.  */
 
 static void
 dump_ads (const char *source_file,
 	  void (*collect_all_refs)(const char *),
-	  int (*cpp_check)(tree, cpp_operation))
+	  int (*check)(tree, cpp_operation))
 {
   char *ads_name;
   char *pkg_name;
@@ -3232,11 +3354,14 @@
 
   pkg_name = get_ada_package (source_file);
 
-  /* Construct the the .ads filename and package name.  */
+  /* Construct the .ads filename and package name.  */
   ads_name = xstrdup (pkg_name);
 
   for (s = ads_name; *s; s++)
-    *s = TOLOWER (*s);
+    if (*s == '.')
+      *s = '-';
+    else
+      *s = TOLOWER (*s);
 
   ads_name = reconcat (ads_name, ads_name, ".ads", NULL);
 
@@ -3246,7 +3371,6 @@
     {
       pretty_printer pp;
 
-      pp_construct (&pp, NULL, 0);
       pp_needs_newline (&pp) = true;
       pp.buffer->stream = f;
 
@@ -3259,7 +3383,12 @@
       (*collect_all_refs) (source_file);
 
       /* Dump all references.  */
-      dump_ada_nodes (&pp, source_file, cpp_check);
+      cpp_check = check;
+      dump_ada_nodes (&pp, source_file);
+
+      /* Requires Ada 2005 syntax, so generate corresponding pragma.
+         Also, disable style checks since this file is auto-generated.  */
+      fprintf (f, "pragma Ada_2005;\npragma Style_Checks (Off);\n\n");
 
       /* Dump withs.  */
       dump_ada_withs (f);
@@ -3296,7 +3425,7 @@
     }
 
   for (i = 0; i < source_refs_used; i++)
-    if (filename == source_refs [i])
+    if (filename == source_refs[i])
       return;
 
   if (source_refs_used == source_refs_allocd)
@@ -3305,26 +3434,25 @@
       source_refs = XRESIZEVEC (const char *, source_refs, source_refs_allocd);
     }
 
-  source_refs [source_refs_used++] = filename;
+  source_refs[source_refs_used++] = filename;
 }
 
 /* Main entry point: dump all Ada specs corresponding to SOURCE_REFS
-   using callbacks COLLECT_ALL_REFS and CPP_CHECK.
+   using callbacks COLLECT_ALL_REFS and CHECK.
    COLLECT_ALL_REFS is a front-end callback used to collect all relevant
    nodes for a given source file.
-   CPP_CHECK is used to perform C++ queries on nodes, or NULL for the C
+   CHECK is used to perform C++ queries on nodes, or NULL for the C
    front-end.  */
 
 void
 dump_ada_specs (void (*collect_all_refs)(const char *),
-		int (*cpp_check)(tree, cpp_operation))
+		int (*check)(tree, cpp_operation))
 {
-  int i;
-
-  /* Iterate over the list of files to dump specs for */
-  for (i = 0; i < source_refs_used; i++)
-    dump_ads (source_refs [i], collect_all_refs, cpp_check);
-
-  /* Free files table.  */
+  /* Iterate over the list of files to dump specs for.  */
+  for (int i = 0; i < source_refs_used; i++)
+    dump_ads (source_refs[i], collect_all_refs, check);
+
+  /* Free various tables.  */
   free (source_refs);
+  delete overloaded_names;
 }