This patch corrects an issue whereby objects of a record type with a
representation clause which are overlain by address would fail to get
assigned values properly when one or both of said objects were marked
volatile.

Tested on x86_64-pc-linux-gnu, committed on trunk

2018-07-31  Justin Squirek  <squi...@adacore.com>

gcc/ada/

        * exp_ch5.adb (Make_Field_Assign): Force temporarily generated
        objects for assignment of overlaid user objects to be renamings
        instead of constant declarations.

gcc/testsuite/

        * gnat.dg/addr11.adb: New testcase.
--- gcc/ada/exp_ch5.adb
+++ gcc/ada/exp_ch5.adb
@@ -1531,11 +1531,22 @@ package body Exp_Ch5 is
                    Selector_Name => New_Occurrence_Of (Disc, Loc));
             end if;
 
+            --  Generate the assignment statement. When the left-hand side
+            --  is an object with an address clause present, force generated
+            --  temporaries to be renamings so as to correctly assign to any
+            --  overlaid objects.
+
             A :=
               Make_Assignment_Statement (Loc,
                 Name       =>
                   Make_Selected_Component (Loc,
-                    Prefix        => Duplicate_Subexpr (Lhs),
+                    Prefix        =>
+                      Duplicate_Subexpr
+                        (Exp          => Lhs,
+                         Name_Req     => False,
+                         Renaming_Req =>
+                           Is_Entity_Name (Lhs)
+                             and then Present (Address_Clause (Entity (Lhs)))),
                     Selector_Name =>
                       New_Occurrence_Of (Find_Component (L_Typ, C), Loc)),
                 Expression => Expr);

--- /dev/null
new file mode 100644
+++ gcc/testsuite/gnat.dg/addr11.adb
@@ -0,0 +1,28 @@
+--  { dg-do run }
+
+procedure Addr11 is
+
+  type Rec is record
+    I : Short_Integer;
+    C : Character;
+  end record;
+
+  type Derived is new Rec;
+  for Derived use record
+    I at 1 range 0 .. 15;
+    C at 0 range 0 .. 7;
+  end record;
+
+  Init : constant Rec := ( 1515, 'A' );
+
+  D1 : Derived;
+  D2 : Derived;
+  pragma Volatile (D2);
+  for D2'Address use D1'Address;
+
+begin
+  D2 := Derived (Init);
+  if D1 /= Derived (Init) then
+    raise Program_Error;
+  end if;
+end;

Reply via email to