This is a regression present on the mainline: the compiler aborts on a deferred 
constant initialized with an aggregate and whose type is a discriminated 
record type with a variant part and which, ultimately, contains a component 
whose type is controlled or tagged.

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


2012-02-15  Eric Botcazou  <ebotca...@adacore.com>

        * gcc-interface/trans.c (Identifier_to_gnu): Move block retrieving the
        type of the result to the end and execute it for a deferred constant of
        a discriminated type whose full view can be elaborated statically.


2012-02-15  Eric Botcazou  <ebotca...@adacore.com>

        * gnat.dg/discr35.ad[sb]: New test.


-- 
Eric Botcazou
Index: gcc-interface/trans.c
===================================================================
--- gcc-interface/trans.c	(revision 184258)
+++ gcc-interface/trans.c	(working copy)
@@ -1077,17 +1077,6 @@ Identifier_to_gnu (Node_Id gnat_node, tr
 	}
     }
 
-  /* The GNAT tree has the type of a function as the type of its result.  Also
-     use the type of the result if the Etype is a subtype which is nominally
-     unconstrained.  But remove any padding from the resulting type.  */
-  if (TREE_CODE (TREE_TYPE (gnu_result)) == FUNCTION_TYPE
-      || Is_Constr_Subt_For_UN_Aliased (gnat_temp_type))
-    {
-      gnu_result_type = TREE_TYPE (gnu_result);
-      if (TYPE_IS_PADDING_P (gnu_result_type))
-	gnu_result_type = TREE_TYPE (TYPE_FIELDS (gnu_result_type));
-    }
-
   /* If we have a constant declaration and its initializer, try to return the
      latter to avoid the need to call fold in lots of places and the need for
      elaboration code if this identifier is used as an initializer itself.
@@ -1120,6 +1109,24 @@ Identifier_to_gnu (Node_Id gnat_node, tr
 	gnu_result = unshare_expr (DECL_INITIAL (gnu_result));
     }
 
+  /* The GNAT tree has the type of a function set to its result type, so we
+     adjust here.  Also use the type of the result if the Etype is a subtype
+     that is nominally unconstrained.  Likewise if this is a deferred constant
+     of a discriminated type whose full view can be elaborated statically, to
+     avoid problematic conversions to the nominal subtype.  But remove any
+     padding from the resulting type.  */
+  if (TREE_CODE (TREE_TYPE (gnu_result)) == FUNCTION_TYPE
+      || Is_Constr_Subt_For_UN_Aliased (gnat_temp_type)
+      || (Ekind (gnat_temp) == E_Constant
+	  && Present (Full_View (gnat_temp))
+	  && Has_Discriminants (gnat_temp_type)
+	  && TREE_CODE (gnu_result) == CONSTRUCTOR))
+    {
+      gnu_result_type = TREE_TYPE (gnu_result);
+      if (TYPE_IS_PADDING_P (gnu_result_type))
+	gnu_result_type = TREE_TYPE (TYPE_FIELDS (gnu_result_type));
+    }
+
   *gnu_result_type_p = gnu_result_type;
 
   return gnu_result;
-- { dg-do compile }

package body Discr35 is

   procedure Proc1 is
     R : Rec2 := Null_Rec2;
   begin
     null;
   end;

   procedure Proc2 is
     R : Rec2;
   begin
     R := Null_Rec2;
   end;

end Discr35;
package Discr35 is

  type Rec1 is tagged null record;

  type Enum is (One, Two);

  type Rec2 (D : Enum := One) is
  record
    case D is
      when One => null;
      when Two => R : Rec1;
    end case;
  end record;

   Null_Rec2 : Constant Rec2;

   procedure Proc1;

   procedure Proc2;

private

   Null_Rec2 : Constant Rec2 := (D => One);

end Discr35;

Reply via email to