Patchwork improve support for nested types in -fdump-ada-spec

login
register
mail settings
Submitter Arnaud Charlet
Date Aug. 4, 2010, 1:49 p.m.
Message ID <20100804134959.GA16132@adacore.com>
Download mbox | patch
Permalink /patch/60853/
State New
Headers show

Comments

Arnaud Charlet - Aug. 4, 2010, 1:49 p.m.
This is a patch to c-ada-spec.c which performs two things:

- fix generate of reference to struct by using the proper type reference,
  for instance consider the following code:

typedef struct _some_internal_name {
   int field;
} my_real_type;

void my_function (my_real_type *t);

Before this patch, we would generate:

   procedure my_function (arg1 : access u_some_internal_name);  -- struct.h:5:6
   pragma Import (C, my_function, "my_function");

instead of:

   procedure my_function (arg1 : access my_real_type);  -- struct.h:5
   pragma Import (C, my_function, "my_function");

as done with this patch.

- also, this patch fixes some cases where we would not generate a forward
  reference to a type before using it, as in:

--
struct _cairo_path_data_t;

typedef struct _cairo_path_data_t cairo_path_data_t;
struct _cairo_path_data_t {
   int x;
};

typedef struct _cairo_path_data_t struct2;
--

where we would generate:
   subtype cairo_path_data_t is u_cairo_path_data_t;
instead of:
   type u_cairo_path_data_t;
   subtype cairo_path_data_t is u_cairo_path_data_t;

In order to decide when to generate forward references, we make additional
use of the TREE_VISITED flag in c-ada-spec.c.

Tested on x86_64-linux-gnu, OK for trunk?

	* c-ada-spec.c (dump_ada_template): Mark underlying instance type as
	visited.
	(dump_generic_ada_node): Code clean up. Use TREE_VISITED flag to
	decide whether a type has already been declared/seen.
	Do not go to the original type.
	(dump_nested_types): New parameter forward.
	Generate forward declaration if needed and mark type as visited.
	(print_ada_declaration): Call dump_nested_types if not already done.
	Mark types as visited.
Joseph S. Myers - Aug. 4, 2010, 3:39 p.m.
On Wed, 4 Aug 2010, Arnaud Charlet wrote:

> Tested on x86_64-linux-gnu, OK for trunk?
> 
> 	* c-ada-spec.c (dump_ada_template): Mark underlying instance type as
> 	visited.
> 	(dump_generic_ada_node): Code clean up. Use TREE_VISITED flag to
> 	decide whether a type has already been declared/seen.
> 	Do not go to the original type.
> 	(dump_nested_types): New parameter forward.
> 	Generate forward declaration if needed and mark type as visited.
> 	(print_ada_declaration): Call dump_nested_types if not already done.
> 	Mark types as visited.

OK.

Patch

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;  -- ");