This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Ada] Fix wrong size for full rep-ed unchecked union


The compiler gives a null size to the type

  type Bit is (Zero, One);

  type U (X : Bit := Zero) is record
    case X is
      when Zero => I: Integer;
      when One => F : Float;
    end case;
  end record;
  for U use record
    I at 0 range  0 .. 31;
    F at 0 range  0 .. 31;
  end record;
  pragma Unchecked_Union(U);

because of the optimization in components_to_record that reuses the empty 
union type and early returns when there are no non-rep components.  But
early returning is wrong since the rep-ed components are not laid out yet.

Tested on i586-suse-linux, applied on the mainline.


2008-01-22  Eric Botcazou  <ebotcazou@adacore.com>

        * decl.c (components_to_record): Do not reuse the empty union type
        if there is a representation clause on the record.
	* trans.c (addressable_p): Return true for INTEGER_CST.


2008-01-22  Eric Botcazou  <ebotcazou@adacore.com>

	* gnat.dg/unchecked_union1.adb: New test.


-- 
Eric Botcazou
Index: decl.c
===================================================================
--- decl.c	(revision 131696)
+++ decl.c	(working copy)
@@ -6007,11 +6007,15 @@ components_to_record (tree gnu_record_ty
       gnu_union_name = concat_id_with_name (gnu_name,
 					    IDENTIFIER_POINTER (gnu_var_name));
 
-      if (!gnu_field_list && TREE_CODE (gnu_record_type) == UNION_TYPE)
+      /* Reuse an enclosing union if all fields are in the variant part
+	 and there is no representation clause on the record, to match
+	 the layout of C unions.  There is an associated check below.  */
+      if (!gnu_field_list
+	  && TREE_CODE (gnu_record_type) == UNION_TYPE
+	  && !TYPE_PACKED (gnu_record_type))
 	gnu_union_type = gnu_record_type;
       else
 	{
-
 	  gnu_union_type
 	    = make_node (unchecked_union ? UNION_TYPE : QUAL_UNION_TYPE);
 
@@ -6116,7 +6120,9 @@ components_to_record (tree gnu_record_ty
 	     return.  */
 	  if (gnu_union_type == gnu_record_type)
 	    {
-	      gcc_assert (!gnu_field_list && unchecked_union);
+	      gcc_assert (unchecked_union
+			  && !gnu_field_list
+			  && !gnu_our_rep_list);
 	      return;
 	    }
 
Index: trans.c
===================================================================
--- trans.c	(revision 131696)
+++ trans.c	(working copy)
@@ -6070,6 +6070,7 @@ addressable_p (tree gnu_expr)
     case INDIRECT_REF:
     case CONSTRUCTOR:
     case STRING_CST:
+    case INTEGER_CST:
     case NULL_EXPR:
     case SAVE_EXPR:
     case CALL_EXPR:
-- { dg-do run }

procedure Unchecked_Union1 is

  type Bit is (Zero, One);

  type U (X : Bit := Zero) is record
    case X is
      when Zero => I: Integer;
      when One => F : Float;
    end case;
  end record;
  for U use record
    I at 0 range  0 .. 31;
    F at 0 range  0 .. 31;
  end record;
  pragma Unchecked_Union(U);

begin
  if U'Object_Size /= 32 then
    raise Program_Error;
  end if;
end;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]