diff mbox

improve support for enums in -fdump-ada-spec

Message ID 20100615110506.GA29822@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet June 15, 2010, 11:05 a.m. UTC
This is a patch to c-ada-spec.c which does two things:

- remove the column info in the comments generated after each entity,
  since this information is not very useful, and this causes troubles
  when e.g. comparing output o -fdump-ada-spec between GCC versions
  since the column info isn't always the same

- more importantly, this patch recognizes common cases of C enums that
  can be mapped directly to an Ada enum (that is to say, when the C
  enum uses the default representation: 0, 1, 2, ... with no holes)

With the following code:
--
enum foo { FOO_, BAR_ };

typedef enum _bar { ONE = 0, TWO, THREE } bar;

enum bii { X = 1, Y };

Before this patch we had:
<<
with Interfaces.C; use Interfaces.C;

package enum_h is

   subtype foo is unsigned;
   FOO_u : constant foo := 0;
   BAR_u : constant foo := 1;  -- enum.h:1:6

   subtype u_bar is unsigned;
   ONE : constant u_bar := 0;
   TWO : constant u_bar := 1;
   THREE : constant u_bar := 2;  -- enum.h:3:14

   subtype bar is u_bar;

   subtype bii is unsigned;
   X : constant bii := 1;
   Y : constant bii := 2;  -- enum.h:5:6

end enum_h;
>>

and after:

<<
with Interfaces.C; use Interfaces.C;

package enum_h is
   
   type foo is
     (FOO_u,
      BAR_u);
   pragma Convention (C, foo);  -- enum.h:1
   
   type u_bar is
     (ONE,
      TWO,
      THREE);
   pragma Convention (C, u_bar);  -- enum.h:3
   
   subtype bar is u_bar;
   
   subtype bii is unsigned;
   X : constant bii := 1;
   Y : constant bii := 2;  -- enum.h:5

end enum_h;
>>

gcc/c-family

2010-06-15  Arnaud Charlet  <charlet@adacore.com>

	* c-ada-spec.c (dump_sloc): Remove column info.
	(is_simple_enum): New function.
	(dump_generic_ada_node, print_ada_declaration): Map C enum types to Ada
	enum types when relevant.

Tested on x86_64-linux, OK for trunk?

Arno

Comments

Joseph Myers June 15, 2010, 12:08 p.m. UTC | #1
On Tue, 15 Jun 2010, Arnaud Charlet wrote:

> +  unsigned count = 0;

Should be unsigned HOST_WIDE_INT.

> +      if (! host_integerp (int_val, 0))

No space after "!".

OK with those changes.
Arnaud Charlet June 15, 2010, 12:24 p.m. UTC | #2
> OK with those changes.

Thanks, corrected version committed at revision 160782.

Arno
diff mbox

Patch

--- c-ada-spec.c.new	2010-06-15 11:29:25.000000000 +0200
+++ c-ada-spec.c	2010-06-15 11:28:39.000000000 +0200
@@ -1676,7 +1676,7 @@  dump_ada_array_domains (pretty_printer *
   pp_character (buffer, ')');
 }
 
-/* Dump in BUFFER file:line:col information related to NODE.  */
+/* Dump in BUFFER file:line information related to NODE.  */
 
 static void
 dump_sloc (pretty_printer *buffer, tree node)
@@ -1695,8 +1695,6 @@  dump_sloc (pretty_printer *buffer, tree 
       pp_string (buffer, xloc.file);
       pp_string (buffer, ":");
       pp_decimal_int (buffer, xloc.line);
-      pp_string (buffer, ":");
-      pp_decimal_int (buffer, xloc.column);
     }
 }
 
@@ -1848,6 +1846,33 @@  dump_ada_template (pretty_printer *buffe
   return num_inst > 0;
 }
 
+/* Return true if NODE is a simple enum types, that can be mapped to an
+   Ada enum type directly.  */
+
+static bool
+is_simple_enum (tree node)
+{
+  unsigned count = 0;
+  tree value;
+
+  for (value = TYPE_VALUES (node); value; value = TREE_CHAIN (value))
+    {
+      tree int_val = TREE_VALUE (value);
+
+      if (TREE_CODE (int_val) != INTEGER_CST)
+	int_val = DECL_INITIAL (int_val);
+
+      if (! host_integerp (int_val, 0))
+	return false;
+      else if (TREE_INT_CST_LOW (int_val) != count)
+	return false;
+
+      count++;
+    }
+
+  return true;
+}
+
 static bool in_function = true;
 static bool bitfield_used = false;
 
@@ -1912,30 +1937,59 @@  dump_generic_ada_node (pretty_printer *b
 	  (buffer, TYPE_NAME (node), node, cpp_check, spc, 0, true);
       else
 	{
-	  tree value;
+	  tree value = TYPE_VALUES (node);
 
-	  pp_string (buffer, "unsigned");
-
-	  for (value = TYPE_VALUES (node); value; value = TREE_CHAIN (value))
+	  if (is_simple_enum (node))
 	    {
-	      pp_semicolon (buffer);
-	      newline_and_indent (buffer, spc);
-
-	      pp_ada_tree_identifier
-		(buffer, TREE_PURPOSE (value), node, false);
-	      pp_string (buffer, " : constant ");
+	      bool first = true;
+	      spc += INDENT_INCR;
+	      newline_and_indent (buffer, spc - 1);
+	      pp_string (buffer, "(");
+	      for (; value; value = TREE_CHAIN (value))
+		{
+		  if (first)
+		    first = false;
+		  else
+		    {
+		      pp_string (buffer, ",");
+		      newline_and_indent (buffer, spc);
+		    }
 
+		  pp_ada_tree_identifier
+		    (buffer, TREE_PURPOSE (value), node, false);
+		}
+	      pp_string (buffer, ");");
+	      spc -= INDENT_INCR;
+	      newline_and_indent (buffer, spc);
+	      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, ")");
+	    }
+	  else
+	    {
+	      pp_string (buffer, "unsigned");
+	      for (; value; value = TREE_CHAIN (value))
+		{
+		  pp_semicolon (buffer);
+		  newline_and_indent (buffer, spc);
 
-	      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);
+		  pp_ada_tree_identifier
+		    (buffer, TREE_PURPOSE (value), node, false);
+		  pp_string (buffer, " : constant ");
+
+		  dump_generic_ada_node
+		    (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
+		     cpp_check, 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);
+		}
 	    }
 	}
       break;
@@ -2702,6 +2756,11 @@  print_ada_declaration (pretty_printer *b
 	    return 1;
 	    break;
 
+	  case ENUMERAL_TYPE:
+	    pp_string
+	      (buffer, is_simple_enum (TREE_TYPE (t)) ? "type " : "subtype ");
+	    break;
+
 	  default:
 	    pp_string (buffer, "subtype ");
 	}