decl.c (gnat_to_gnu_entity): Process renamings before converting the expression to...
authorEric Botcazou <ebotcazou@adacore.com>
Mon, 14 Jan 2008 19:32:10 +0000 (19:32 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Mon, 14 Jan 2008 19:32:10 +0000 (19:32 +0000)
* decl.c (gnat_to_gnu_entity) <object>: Process renamings
before converting the expression to the type of the object.
* trans.c (maybe_stabilize_reference) <CONSTRUCTOR>: New case.
Stabilize constructors for special wrapping types.

From-SVN: r131531

gcc/ada/ChangeLog
gcc/ada/decl.c
gcc/ada/trans.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/rep_clause1.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/rep_clause2.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/rep_clause2.ads [new file with mode: 0644]

index 563124c341452c3096e8530c521c9c80e0cbaf34..1dd2fc5625ecf98ecc37cb273b84d8116a3a5d95 100644 (file)
@@ -1,3 +1,10 @@
+2008-01-14  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * decl.c (gnat_to_gnu_entity) <object>: Process renamings
+       before converting the expression to the type of the object.
+       * trans.c (maybe_stabilize_reference) <CONSTRUCTOR>: New case.
+       Stabilize constructors for special wrapping types.
+
 2008-01-13  Eric Botcazou  <ebotcazou@adacore.com>
 
        * trans.c (call_to_gnu):Invoke the addressable_p predicate only
index b61afceb3ade6b6b31916098bcae841deb74c009..2ddfe5a89c0ec05725e7c312433be4ace869ae5a 100644 (file)
@@ -740,23 +740,10 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
                                           (TYPE_QUALS (gnu_type)
                                            | TYPE_QUAL_VOLATILE));
 
-       /* Convert the expression to the type of the object except in the
-          case where the object's type is unconstrained or the object's type
-          is a padded record whose field is of self-referential size.  In
-          the former case, converting will generate unnecessary evaluations
-          of the CONSTRUCTOR to compute the size and in the latter case, we
-          want to only copy the actual data.  */
-       if (gnu_expr
-           && TREE_CODE (gnu_type) != UNCONSTRAINED_ARRAY_TYPE
-           && !CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_type))
-           && !(TREE_CODE (gnu_type) == RECORD_TYPE
-                && TYPE_IS_PADDING_P (gnu_type)
-                && (CONTAINS_PLACEHOLDER_P
-                    (TYPE_SIZE (TREE_TYPE (TYPE_FIELDS (gnu_type)))))))
-         gnu_expr = convert (gnu_type, gnu_expr);
-
        /* If this is a renaming, avoid as much as possible to create a new
-          object.  However, in several cases, creating it is required.  */
+          object.  However, in several cases, creating it is required.
+          This processing needs to be applied to the raw expression so
+          as to make it more likely to rename the underlying object.  */
        if (Present (Renamed_Object (gnat_entity)))
          {
            bool create_normal_object = false;
@@ -905,7 +892,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
           the object.  If there is an initializer, it will have already
           been converted to the right type, but we need to create the
           template if there is no initializer.  */
-       else if (definition && TREE_CODE (gnu_type) == RECORD_TYPE
+       else if (definition
+                && TREE_CODE (gnu_type) == RECORD_TYPE
                 && (TYPE_CONTAINS_TEMPLATE_P (gnu_type)
                     /* Beware that padding might have been introduced
                        via maybe_pad_type above.  */
@@ -932,6 +920,21 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
                NULL_TREE));
          }
 
+       /* Convert the expression to the type of the object except in the
+          case where the object's type is unconstrained or the object's type
+          is a padded record whose field is of self-referential size.  In
+          the former case, converting will generate unnecessary evaluations
+          of the CONSTRUCTOR to compute the size and in the latter case, we
+          want to only copy the actual data.  */
+       if (gnu_expr
+           && TREE_CODE (gnu_type) != UNCONSTRAINED_ARRAY_TYPE
+           && !CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_type))
+           && !(TREE_CODE (gnu_type) == RECORD_TYPE
+                && TYPE_IS_PADDING_P (gnu_type)
+                && (CONTAINS_PLACEHOLDER_P
+                    (TYPE_SIZE (TREE_TYPE (TYPE_FIELDS (gnu_type)))))))
+         gnu_expr = convert (gnu_type, gnu_expr);
+
        /* If this is a pointer and it does not have an initializing
           expression, initialize it to NULL, unless the object is
           imported.  */
index c5828d79d177faaef4186849002b4185e2fc3131..5b04972b2d235c50cc28b77318643685cb179170 100644 (file)
@@ -6503,6 +6503,28 @@ maybe_stabilize_reference (tree ref, bool force, bool *success)
       result = gnat_stabilize_reference_1 (ref, force);
       break;
 
+    case CONSTRUCTOR:
+      /* Constructors with 1 element are used extensively to formally
+        convert objects to special wrapping types.  */
+      if (TREE_CODE (type) == RECORD_TYPE
+         && VEC_length (constructor_elt, CONSTRUCTOR_ELTS (ref)) == 1)
+       {
+         tree index
+           = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (ref), 0)->index;
+         tree value
+           = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (ref), 0)->value;
+         result
+           = build_constructor_single (type, index,
+                                       gnat_stabilize_reference_1 (value,
+                                                                   force));
+       }
+      else
+       {
+         *success = false;
+         return ref;
+       }
+      break;
+
     case ERROR_MARK:
       ref = error_mark_node;
 
index f4bb665a415dee9e8a843c8fb53d077ace02175f..ac27643aeea6c68f47dc080e0eb939c59b1a3143 100644 (file)
@@ -1,3 +1,8 @@
+2008-01-14  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/rep_clause2.ad[sb]: New test.
+       * gnat.dg/rep_problem2.adb: Rename to rep_clause1.adb.
+
 2008-01-14  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>
 
        PR c++/24924
diff --git a/gcc/testsuite/gnat.dg/rep_clause1.adb b/gcc/testsuite/gnat.dg/rep_clause1.adb
new file mode 100644 (file)
index 0000000..b7f5c7d
--- /dev/null
@@ -0,0 +1,101 @@
+--  { dg-do compile }
+
+with Ada.Text_IO; use Ada.Text_IO;
+
+procedure Rep_Clause1 is
+   
+   type Int_16 is range 0 .. 65535;
+   for Int_16'Size use 16;
+   
+   ----------------------------------------------
+      
+   type Rec_A is
+      record
+         Int_1 : Int_16;
+         Int_2 : Int_16;
+         Int_3 : Int_16;
+         Int_4 : Int_16;
+      end record;
+      
+      
+   for Rec_A use record
+      Int_1 at 0 range  0 .. 15;
+      Int_2 at 2 range  0 .. 15;
+      Int_3 at 4 range  0 .. 15;
+      Int_4 at 6 range  0 .. 15;
+   end record;
+   
+   Rec_A_Size : constant := 4 * 16;
+   
+   for Rec_A'Size use Rec_A_Size;
+   
+   ----------------------------------------------
+   
+   type Rec_B_Version_1 is
+      record
+         Rec_1 : Rec_A;
+         Rec_2 : Rec_A;
+         Int_1 : Int_16;
+      end record;
+  
+   for Rec_B_Version_1 use record
+      Rec_1 at  0 range  0 .. 63;
+      Rec_2 at  8 range  0 .. 63;
+      Int_1 at 16 range  0 .. 15;
+   end record;
+  
+   Rec_B_Size : constant := 2 * Rec_A_Size + 16;
+   
+   for Rec_B_Version_1'Size use Rec_B_Size;
+   for Rec_B_Version_1'Alignment use 2;
+
+   ----------------------------------------------
+
+   type Rec_B_Version_2 is
+      record
+         Int_1 : Int_16;
+         Rec_1 : Rec_A;
+         Rec_2 : Rec_A;
+      end record;
+   
+   for Rec_B_Version_2 use record
+      Int_1 at  0 range  0 .. 15;
+      Rec_1 at  2 range  0 .. 63;
+      Rec_2 at 10 range  0 .. 63;
+   end record;
+
+   for Rec_B_Version_2'Size use Rec_B_Size;
+   
+   ----------------------------------------------
+   
+   Arr_A_Length : constant := 2;
+   Arr_A_Size   : constant := Arr_A_Length * Rec_B_Size;
+   
+   type Arr_A_Version_1 is array (1 .. Arr_A_Length) of Rec_B_Version_1;
+   type Arr_A_Version_2 is array (1 .. Arr_A_Length) of Rec_B_Version_2;
+   
+   pragma Pack (Arr_A_Version_1);
+   pragma Pack (Arr_A_Version_2);
+   
+   for Arr_A_Version_1'Size use Arr_A_Size;
+   for Arr_A_Version_2'Size use Arr_A_Size;
+   
+   ----------------------------------------------
+
+begin
+   --  Put_Line ("Arr_A_Size =" & Arr_A_Size'Img);
+   
+   if Arr_A_Version_1'Size /= Arr_A_Size then
+      Ada.Text_IO.Put_Line
+        ("Version 1 Size mismatch! " &
+         "Arr_A_Version_1'Size =" & Arr_A_Version_1'Size'Img);
+   end if;
+   
+   if Arr_A_Version_2'Size /= Arr_A_Size then
+      Ada.Text_IO.Put_Line
+        ("Version 2 Size mismatch! " &
+         "Arr_A_Version_2'Size =" & Arr_A_Version_2'Size'Img);
+   
+   end if;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/rep_clause2.adb b/gcc/testsuite/gnat.dg/rep_clause2.adb
new file mode 100644 (file)
index 0000000..b6cd49f
--- /dev/null
@@ -0,0 +1,10 @@
+-- { dg-do compile }\r
+\r
+package body Rep_Clause2 is\r
+\r
+   procedure Assign (From : Data; Offset : Positive; I : Index; To : out Bit_Array) is\r
+   begin\r
+     To (Offset .. Offset + 7) := Bit_Array (Conv (From.D(I).S.N));\r
+   end;\r
+\r
+end Rep_Clause2;\r
diff --git a/gcc/testsuite/gnat.dg/rep_clause2.ads b/gcc/testsuite/gnat.dg/rep_clause2.ads
new file mode 100644 (file)
index 0000000..cc8b33e
--- /dev/null
@@ -0,0 +1,53 @@
+with Unchecked_Conversion;\r
+\r
+package Rep_Clause2 is\r
+\r
+   type Tiny is range 0 .. 3;\r
+   for Tiny'Size use 2;\r
+\r
+   type Small is range 0 .. 255;\r
+   for Small'Size use 8;\r
+\r
+   type Small_Data is record\r
+      D : Tiny;\r
+      N : Small;\r
+   end record;\r
+   pragma Pack (Small_Data);\r
+\r
+   type Chunk is\r
+   record\r
+      S : Small_Data;\r
+      C : Character;\r
+   end record;\r
+\r
+   for Chunk use record\r
+      S at 0 range  0 .. 15;\r
+      C at 2 range  0 .. 7;\r
+   end record;\r
+\r
+   type Index is range 1 .. 10;\r
+\r
+   type Data_Array is array (Index) of Chunk;\r
+   for Data_Array'Alignment use 2;\r
+   pragma Pack (Data_Array);\r
+\r
+   type Data is record\r
+     D : Data_Array;\r
+   end record;\r
+\r
+   type Bit is range 0 .. 1;\r
+   for Bit'Size use 1;\r
+\r
+   type Bit_Array is array (Positive range <>) of Bit;\r
+   pragma Pack (Bit_Array);\r
+\r
+   type Byte is new Bit_Array (1 .. 8);\r
+   for  Byte'Size use 8;\r
+   for  Byte'Alignment use 1;\r
+\r
+   function Conv\r
+     is new Unchecked_Conversion(Source => Small, Target => Byte);\r
+\r
+   procedure Assign (From : Data; Offset : Positive; I : Index; To : out Bit_Array);\r
+\r
+end Rep_Clause2;\r