A case expression is rewritten as an Expression_With_Actions, whose main
component is a case statement that mirrors the structure of the case expression.
The actions created for the expression in a given case alterantive must be
attached to the statement list of the ccrresponding case statement alternative
They cannot be propagated ahead of the case statement, because the validity of
the expression that generated the action may hold only for that alternative.
No short example available.

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

2011-09-06  Ed Schonberg  <schonb...@adacore.com>

        * exp_ch4.adb (Expand_N_Case_Expression): Actions created for the
        expression in a given case alternative must be attached to the
        statement list of the ccrresponding case statement alternative
        They cannot be propagated ahead of the case statement, because
        the validity of the expression that generated the action may
        hold only for that alternative.

Index: exp_ch4.adb
===================================================================
--- exp_ch4.adb (revision 178569)
+++ exp_ch4.adb (working copy)
@@ -4149,15 +4149,14 @@
       Alt := First (Alternatives (N));
       while Present (Alt) loop
          declare
-            Aexp : Node_Id             := Expression (Alt);
-            Aloc : constant Source_Ptr := Sloc (Aexp);
+            Aexp  : Node_Id             := Expression (Alt);
+            Aloc  : constant Source_Ptr := Sloc (Aexp);
+            Stats : List_Id;
 
          begin
-            --  Propagate declarations inserted in the node by Insert_Actions
-            --  (for example, temporaries generated to remove side effects).
+            --  As described above, take Unrestricted_Access for case of non-
+            --  scalar types, to avoid big copies, and special cases.
 
-            Append_List_To (Actions, Sinfo.Actions (Alt));
-
             if not Is_Scalar_Type (Typ) then
                Aexp :=
                  Make_Attribute_Reference (Aloc,
@@ -4165,14 +4164,25 @@
                    Attribute_Name => Name_Unrestricted_Access);
             end if;
 
+            Stats := New_List (
+              Make_Assignment_Statement (Aloc,
+                Name       => New_Occurrence_Of (Tnn, Loc),
+                Expression => Aexp));
+
+            --  Propagate declarations inserted in the node by Insert_Actions
+            --  (for example, temporaries generated to remove side effects).
+            --  These actions must remain attached to the alternative, given
+            --  that they are generated by the corresponding expression.
+
+            if Present (Sinfo.Actions (Alt)) then
+               Prepend_List (Sinfo.Actions (Alt), Stats);
+            end if;
+
             Append_To
               (Alternatives (Cstmt),
                Make_Case_Statement_Alternative (Sloc (Alt),
                  Discrete_Choices => Discrete_Choices (Alt),
-                 Statements       => New_List (
-                   Make_Assignment_Statement (Aloc,
-                     Name       => New_Occurrence_Of (Tnn, Loc),
-                     Expression => Aexp))));
+                 Statements       => Stats));
          end;
 
          Next (Alt);

Reply via email to