Index: c-ada-spec.c
===================================================================
--- c-ada-spec.c	(revision 161187)
+++ c-ada-spec.c	(working copy)
@@ -1815,6 +1815,7 @@ dump_ada_template (pretty_printer *buffe
       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);
       package_prefix = true;
@@ -2121,7 +2122,7 @@ dump_generic_ada_node (pretty_printer *b
 		  /* For now, handle all access-to-access or
 		     access-to-unknown-structs as opaque system.address.  */
 
-		  tree typ = TYPE_NAME (TREE_TYPE (node));
+		  tree type_name = TYPE_NAME (TREE_TYPE (node));
 		  const_tree typ2 = !type ||
 		    DECL_P (type) ? type : TYPE_NAME (type);
 		  const_tree underlying_type =
@@ -2135,7 +2136,13 @@ dump_generic_ada_node (pretty_printer *b
 			      || !TYPE_FIELDS (TREE_TYPE (underlying_type))))
 		      /* Pointer to opaque structure.  */
 
-		      || (typ && typ2
+		      || (!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)
@@ -2193,28 +2200,10 @@ dump_generic_ada_node (pretty_printer *b
 		    }
 
 		  if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
-		      && TYPE_NAME (TREE_TYPE (node)))
-		    {
-		      tree name = TYPE_NAME (TREE_TYPE (node));
-		      tree tmp;
-
-		      if (TREE_CODE (name) == TYPE_DECL
-			  && DECL_ORIGINAL_TYPE (name)
-			  && TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (name)))
-			{
-			  tmp = TYPE_NAME (TREE_TYPE (TYPE_STUB_DECL
-			    (DECL_ORIGINAL_TYPE (name))));
-
-			  if (tmp == NULL_TREE)
-			    tmp = TYPE_NAME (TREE_TYPE (node));
-			}
-		      else
-			tmp = TYPE_NAME (TREE_TYPE (node));
-
-		      dump_generic_ada_node
-			(buffer, tmp,
-			 TREE_TYPE (node), cpp_check, spc, is_access, true);
-		    }
+		      && type_name != NULL_TREE)
+		    dump_generic_ada_node
+		      (buffer, type_name,
+		       TREE_TYPE (node), cpp_check, spc, is_access, true);
 		  else
 		    dump_generic_ada_node
 		      (buffer, TREE_TYPE (node), TREE_TYPE (node),
@@ -2392,11 +2381,13 @@ print_ada_methods (pretty_printer *buffe
 }
 
 /* Dump in BUFFER anonymous types nested inside T's definition.
-   PARENT is the parent node of T.  CPP_CHECK is used to perform C++ queries on
+   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.  */
 
 static void
-dump_nested_types (pretty_printer *buffer, tree t, tree parent,
+dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward,
 		   int (*cpp_check)(tree, cpp_operation), int spc)
 {
   tree field, outer, decl;
@@ -2412,6 +2403,16 @@ dump_nested_types (pretty_printer *buffe
   if (outer == NULL_TREE)
     return;
 
+  if (forward)
+    {
+      pp_string (buffer, "type ");
+      dump_generic_ada_node
+	(buffer, t, t, cpp_check, spc, false, true);
+      pp_semicolon (buffer);
+      newline_and_indent (buffer, spc);
+      TREE_VISITED (t) = 1;
+    }
+
   field = TYPE_FIELDS (outer);
   while (field)
     {
@@ -2472,7 +2473,7 @@ dump_nested_types (pretty_printer *buffe
 
 	      case UNION_TYPE:
 		TREE_VISITED (t) = 1;
-		dump_nested_types (buffer, field, t, cpp_check, spc);
+		dump_nested_types (buffer, field, t, false, cpp_check, spc);
 
 		pp_string (buffer, "type ");
 
@@ -2527,7 +2528,7 @@ dump_nested_types (pretty_printer *buffe
 		  }
 
 		TREE_VISITED (t) = 1;
-		dump_nested_types (buffer, field, t, cpp_check, spc);
+		dump_nested_types (buffer, field, t, false, cpp_check, spc);
 		pp_string (buffer, "type ");
 
 		if (TYPE_NAME (TREE_TYPE (field)))
@@ -2563,6 +2564,8 @@ dump_nested_types (pretty_printer *buffe
 	}
       field = TREE_CHAIN (field);
     }
+
+  TREE_VISITED (t) = 1;
 }
 
 /* Dump in BUFFER destructor spec corresponding to T.  */
@@ -2623,7 +2626,8 @@ print_ada_declaration (pretty_printer *b
 
       if (orig && TYPE_STUB_DECL (orig))
 	{
-	  tree typ = TREE_TYPE (TYPE_STUB_DECL (orig));
+	  tree stub = TYPE_STUB_DECL (orig);
+	  tree typ = TREE_TYPE (stub);
 
 	  if (TYPE_NAME (typ))
 	    {
@@ -2642,6 +2646,11 @@ print_ada_declaration (pretty_printer *b
 		}
 	      else
 		{
+		  if (!TREE_VISITED (stub)
+		      && DECL_SOURCE_FILE (stub) == source_file_base)
+		    dump_nested_types
+		      (buffer, stub, stub, true, cpp_check, spc);
+
 		  pp_string (buffer, "subtype ");
 		  dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
 		  pp_string (buffer, " is ");
@@ -2715,6 +2724,7 @@ print_ada_declaration (pretty_printer *b
 	      {
 		pp_string (buffer, "--  skipped anonymous struct ");
 		dump_generic_ada_node (buffer, t, type, 0, spc, false, true);
+		TREE_VISITED (t) = 1;
 		return 1;
 	      }
 
@@ -2722,7 +2732,7 @@ print_ada_declaration (pretty_printer *b
 	      pp_string (buffer, "subtype ");
 	    else
 	      {
-		dump_nested_types (buffer, t, t, cpp_check, spc);
+		dump_nested_types (buffer, t, t, false, cpp_check, spc);
 
 		if (TYPE_METHODS (TREE_TYPE (t))
 		    || has_static_fields (TREE_TYPE (t)))
@@ -2767,6 +2777,7 @@ print_ada_declaration (pretty_printer *b
 	  default:
 	    pp_string (buffer, "subtype ");
 	}
+      TREE_VISITED (t) = 1;
     }
   else
     {
@@ -3011,6 +3022,7 @@ print_ada_declaration (pretty_printer *b
 	    }
 	}
 
+      TREE_VISITED (t) = 1; 
       if (is_interface)
 	{
 	  pp_string (buffer, "limited interface;  -- ");
