This patch corrects the mechanism that inserts various generated constructs in the tree, in particular the interaction with expression_with_actions nodes. No test case applicable as this latent bug was found during code reading.
Tested on x86_64-pc-linux-gnu, committed on trunk 2013-01-29 Hristian Kirtchev <kirtc...@adacore.com> * exp_util.adb (Insert_Actions): When new actions come from the expression of the expression with actions, then they must be added to the list of existing actions.
Index: exp_util.adb =================================================================== --- exp_util.adb (revision 195533) +++ exp_util.adb (working copy) @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 1992-2012, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2013, Free Software Foundation, Inc. -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- @@ -3141,25 +3141,27 @@ -- N_Raise_xxx_Error is an annoying special case, it is a statement if -- it has type Standard_Void_Type, and a subexpression otherwise. - -- otherwise. Procedure attribute references are also statements. + -- otherwise. Procedure calls, and similarly procedure attribute + -- references, are also statements. if Nkind (Assoc_Node) in N_Subexpr - and then (Nkind (Assoc_Node) in N_Raise_xxx_Error + and then (Nkind (Assoc_Node) not in N_Raise_xxx_Error or else Etype (Assoc_Node) /= Standard_Void_Type) + and then Nkind (Assoc_Node) /= N_Procedure_Call_Statement and then (Nkind (Assoc_Node) /= N_Attribute_Reference or else not Is_Procedure_Attribute_Name (Attribute_Name (Assoc_Node))) then - P := Assoc_Node; -- ??? does not agree with above! - N := Parent (Assoc_Node); + N := Assoc_Node; + P := Parent (Assoc_Node); -- Non-subexpression case. Note that N is initially Empty in this case -- (N is only guaranteed Non-Empty in the subexpr case). else + N := Empty; P := Assoc_Node; - N := Empty; end if; -- Capture root of the transient scope @@ -3171,6 +3173,13 @@ loop pragma Assert (Present (P)); + -- Make sure that inserted actions stay in the transient scope + + if Present (Wrapped_Node) and then N = Wrapped_Node then + Store_Before_Actions_In_Scope (Ins_Actions); + return; + end if; + case Nkind (P) is -- Case of right operand of AND THEN or OR ELSE. Put the actions @@ -3282,14 +3291,17 @@ return; - -- Case of appearing within an Expressions_With_Actions node. We - -- append the actions to the list of actions already there, if - -- the node has not been analyzed yet. Otherwise find insertion - -- location further up the tree. + -- Case of appearing within an Expressions_With_Actions node. When + -- the new actions come from the expression of the expression with + -- actions, they must be added to the existing actions. The other + -- alternative is when the new actions are related to one of the + -- existing actions of the expression with actions. In that case + -- they must be inserted further up the tree. when N_Expression_With_Actions => - if not Analyzed (P) then - Append_List (Ins_Actions, Actions (P)); + if N = Expression (P) then + Insert_List_After_And_Analyze + (Last (Actions (P)), Ins_Actions); return; end if; @@ -3697,13 +3709,6 @@ end case; - -- Make sure that inserted actions stay in the transient scope - - if P = Wrapped_Node then - Store_Before_Actions_In_Scope (Ins_Actions); - return; - end if; - -- If we fall through above tests, keep climbing tree N := P;