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);