This change reorganizes expansion of object initialization statements, which need to be captured under a single node id. Previously these were represented as a (malformed) N_Expression_With_Actions with a NULL statement as its expression. This irregularity is fixed by instead introducing a separate N_Compound_Statement node kind.
Tested on x86_64-pc-linux-gnu, committed on trunk 2014-07-16 Thomas Quinot <qui...@adacore.com> * sinfo.ads, sinfo.adb (N_Compound_Statement): New node kind. * sem.adb (Analyze): Handle N_Compound_Statement. * sprint.adb (Sprint_Node_Actual): Ditto. * cprint.adb (Cprint_Node): Ditto. * sem_ch5.ads, sem_ch5.adb (Analyze_Compound_Statement): New procedure to handle N_Compound_Statement. * exp_aggr.adb (Collect_Initialization_Statements): Use a proper compound statement node, instead of a bogus expression-with-actions with a NULL statement as its expression, to wrap collected initialization statements. * freeze.ads, freeze.adb (Explode_Initialization_Compound_Statement): New public procedure, lifted from Freeze_Entity. (Freeze_Entity): When freezing an object with captured initialization statements and without delayed freezing, explode compount statement. * sem_ch4.adb (Analyze_Expression_With_Actions): Remove special case that used to handle bogus EWAs with NULL statement as the expression. * exp_ch13.adb (Expand_N_Freeze_Entity): For an object with delayed freezing and captured initialization statements, explode compound statement.
Index: sem_ch5.adb =================================================================== --- sem_ch5.adb (revision 212640) +++ sem_ch5.adb (working copy) @@ -1016,6 +1016,15 @@ end; end Analyze_Block_Statement; + -------------------------------- + -- Analyze_Compound_Statement -- + -------------------------------- + + procedure Analyze_Compound_Statement (N : Node_Id) is + begin + Analyze_List (Actions (N)); + end Analyze_Compound_Statement; + ---------------------------- -- Analyze_Case_Statement -- ---------------------------- Index: sem_ch5.ads =================================================================== --- sem_ch5.ads (revision 212640) +++ sem_ch5.ads (working copy) @@ -6,7 +6,7 @@ -- -- -- S p e c -- -- -- --- Copyright (C) 1992-2012, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2014, 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- -- @@ -30,6 +30,7 @@ procedure Analyze_Assignment (N : Node_Id); procedure Analyze_Block_Statement (N : Node_Id); procedure Analyze_Case_Statement (N : Node_Id); + procedure Analyze_Compound_Statement (N : Node_Id); procedure Analyze_Exit_Statement (N : Node_Id); procedure Analyze_Goto_Statement (N : Node_Id); procedure Analyze_If_Statement (N : Node_Id); Index: sinfo.adb =================================================================== --- sinfo.adb (revision 212655) +++ sinfo.adb (working copy) @@ -148,6 +148,7 @@ or else NT (N).Nkind = N_And_Then or else NT (N).Nkind = N_Case_Expression_Alternative or else NT (N).Nkind = N_Compilation_Unit_Aux + or else NT (N).Nkind = N_Compound_Statement or else NT (N).Nkind = N_Expression_With_Actions or else NT (N).Nkind = N_Freeze_Entity or else NT (N).Nkind = N_Or_Else); @@ -3314,6 +3315,7 @@ or else NT (N).Nkind = N_And_Then or else NT (N).Nkind = N_Case_Expression_Alternative or else NT (N).Nkind = N_Compilation_Unit_Aux + or else NT (N).Nkind = N_Compound_Statement or else NT (N).Nkind = N_Expression_With_Actions or else NT (N).Nkind = N_Freeze_Entity or else NT (N).Nkind = N_Or_Else); Index: sinfo.ads =================================================================== --- sinfo.ads (revision 212655) +++ sinfo.ads (working copy) @@ -86,6 +86,7 @@ -- Add it to the documentation in the appropriate place -- Add its fields to this documentation section -- Define it in the appropriate classification in Node_Kind + -- Add an entry in Is_Syntactic_Field -- In the body (sinfo), add entries to the access functions for all -- its fields (except standard expression fields) to include the new -- node in the checks. @@ -98,6 +99,8 @@ -- For a subexpression, add an appropriate section to the case -- statement in sem_res.adb + -- All back ends must be made aware of the new node kind. + -- Finally, four utility programs must be run: -- (Optional.) Run CSinfo to check that you have made the changes @@ -7310,6 +7313,39 @@ -- reconstructed tree printed by Sprint, and the node descriptions here -- show this syntax. + ------------------------ + -- Compound Statement -- + ------------------------ + + -- This node is created by the analyzer/expander to handle some + -- expansion cases where a sequence of actions needs to be captured + -- within a single node (which acts as a container and allows the + -- entire list of actions to be moved around as a whole) appearing + -- in a sequence of statements. + + -- This is the statement counterpart to expression node N_Expression_ + -- With_Actions. + + -- The required semantics is that the set of actions is executed in + -- the order in which it appears, as though they appeared by themselves + -- in the enclosing list of declarations of statements. Unlike what + -- happens when using an N_Block_Statement, no new scope is introduced. + + -- Note: for the time being, this is used only as a transient + -- representation during expansion, and all compound statement nodes + -- must be exploded back to their constituent statements before handing + -- the tree to the back end. + + -- Sprint syntax: do + -- action; + -- action; + -- ... + -- action; + -- end; + + -- N_Compound_Statement + -- Actions (List1) + -------------- -- Contract -- -------------- @@ -7375,7 +7411,7 @@ -- The ordering is in LIFO fashion. ------------------- - -- Expanded_Name -- + -- Expanded Name -- ------------------- -- The N_Expanded_Name node is used to represent a selected component @@ -7404,7 +7440,7 @@ -- plus fields for expression ----------------------------- - -- Expression with Actions -- + -- Expression With Actions -- ----------------------------- -- This node is created by the analyzer/expander to handle some @@ -7449,16 +7485,6 @@ -- the expression of the node is fully analyzed and expanded, at which -- point it is safe to remove it, since no more actions can be inserted. - -- Note: Expression may be a Null_Statement, in which case the - -- N_Expression_With_Actions has type Standard_Void_Type. However some - -- backends do not support such expression-with-actions occurring - -- outside of a proper (non-void) expression, so this should just be - -- used as an intermediate representation within the front end. Also - -- note that this is really an irregularity (expressions and statements - -- are not interchangeable, and in particular an N_Null_Statement is - -- not a proper expression), and in the long term all cases of this - -- idiom should instead use a new node kind N_Compound_Statement. - -- Note: In Modify_Tree_For_C, we never generate any declarations in -- the action list, which can contain only non-declarative statements. @@ -7526,7 +7552,7 @@ -- for this node points to the FREEZE keyword in the Sprint file output. --------------------------- - -- Freeze_Generic_Entity -- + -- Freeze Generic Entity -- --------------------------- -- The freeze point of an entity indicates the point at which the @@ -7585,7 +7611,7 @@ -- for this node points to the label name in the generated declaration. --------------------- - -- Itype_Reference -- + -- Itype Reference -- --------------------- -- This node is used to create a reference to an Itype. The only purpose @@ -7609,7 +7635,7 @@ -- for this node points to the REFERENCE keyword in the file output. --------------------- - -- Raise_xxx_Error -- + -- Raise xxx Error -- --------------------- -- One of these nodes is created during semantic analysis to replace @@ -8197,6 +8223,7 @@ N_Block_Statement, N_Case_Statement, N_Code_Statement, + N_Compound_Statement, N_Conditional_Entry_Call, -- N_Statement_Other_Than_Procedure_Call, N_Delay_Statement @@ -12078,6 +12105,13 @@ 4 => False, -- unused 5 => False), -- Etype (Node5-Sem) + N_Compound_Statement => + (1 => True, -- Actions (List1) + 2 => False, -- unused + 3 => False, -- unused + 4 => False, -- unused + 5 => False), -- unused + N_Contract => (1 => False, -- Pre_Post_Conditions (Node1) 2 => False, -- Contract_Test_Cases (Node2) Index: sem.adb =================================================================== --- sem.adb (revision 212640) +++ sem.adb (working copy) @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 1992-2013, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2014, 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- -- @@ -166,6 +166,9 @@ when N_Component_Declaration => Analyze_Component_Declaration (N); + when N_Compound_Statement => + Analyze_Compound_Statement (N); + when N_Conditional_Entry_Call => Analyze_Conditional_Entry_Call (N); Index: freeze.adb =================================================================== --- freeze.adb (revision 212656) +++ freeze.adb (working copy) @@ -1366,6 +1366,29 @@ end if; end Is_Atomic_Aggregate; + ----------------------------------------------- + -- Explode_Initialization_Compound_Statement -- + ----------------------------------------------- + + procedure Explode_Initialization_Compound_Statement (E : Entity_Id) is + Init_Stmts : constant Node_Id := Initialization_Statements (E); + begin + if Present (Init_Stmts) + and then Nkind (Init_Stmts) = N_Compound_Statement + then + Insert_List_Before (Init_Stmts, Actions (Init_Stmts)); + + -- Note that we rewrite Init_Stmts into a NULL statement, rather than + -- just removing it, because Freeze_All may rely on this particular + -- Node_Id still being present in the enclosing list to know where to + -- stop freezing. + + Rewrite (Init_Stmts, Make_Null_Statement (Sloc (Init_Stmts))); + + Set_Initialization_Statements (E, Empty); + end if; + end Explode_Initialization_Compound_Statement; + ---------------- -- Freeze_All -- ---------------- @@ -4314,36 +4337,15 @@ Layout_Object (E); end if; - -- If initialization statements were captured in an expression - -- with actions with null expression, and the object does not - -- have delayed freezing, move them back now directly within the - -- enclosing statement sequence. + -- For an object that does not have delayed freezing, and whose + -- initialization actions have been captured in a compound + -- statement, move them back now directly within the enclosing + -- statement sequence. if Ekind_In (E, E_Constant, E_Variable) and then not Has_Delayed_Freeze (E) then - declare - Init_Stmts : constant Node_Id := - Initialization_Statements (E); - begin - if Present (Init_Stmts) - and then Nkind (Init_Stmts) = N_Expression_With_Actions - and then Nkind (Expression (Init_Stmts)) = N_Null_Statement - then - Insert_List_Before (Init_Stmts, Actions (Init_Stmts)); - - -- Note that we rewrite Init_Stmts into a NULL statement, - -- rather than just removing it, because Freeze_All may - -- depend on this particular Node_Id still being present - -- in the enclosing list to signal where to stop - -- freezing. - - Rewrite (Init_Stmts, - Make_Null_Statement (Sloc (Init_Stmts))); - - Set_Initialization_Statements (E, Empty); - end if; - end; + Explode_Initialization_Compound_Statement (E); end if; end if; Index: freeze.ads =================================================================== --- freeze.ads (revision 212640) +++ freeze.ads (working copy) @@ -186,6 +186,10 @@ -- of an object declaration or an assignment. Function is a noop and -- returns false in other contexts. + procedure Explode_Initialization_Compound_Statement (E : Entity_Id); + -- If Initialization_Statements (E) is an N_Compound_Statement, insert its + -- actions in the enclosing list and reset the attribute. + function Freeze_Entity (E : Entity_Id; N : Node_Id) return List_Id; -- Freeze an entity, and return Freeze nodes, to be inserted at the point -- of call. N is a node whose source location corresponds to the freeze Index: sem_ch4.adb =================================================================== --- sem_ch4.adb (revision 212640) +++ sem_ch4.adb (working copy) @@ -2040,17 +2040,8 @@ Next (A); end loop; - -- We currently hijack Expression_With_Actions with a VOID type and - -- a NULL statement in the Expression. This will ultimately be replaced - -- by a proper separate N_Compound_Statement node, at which point the - -- test below can go away??? - - if Nkind (Expression (N)) = N_Null_Statement then - Set_Etype (N, Standard_Void_Type); - else - Analyze_Expression (Expression (N)); - Set_Etype (N, Etype (Expression (N))); - end if; + Analyze_Expression (Expression (N)); + Set_Etype (N, Etype (Expression (N))); end Analyze_Expression_With_Actions; --------------------------- Index: exp_ch13.adb =================================================================== --- exp_ch13.adb (revision 212640) +++ exp_ch13.adb (working copy) @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 1992-2013, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2014, 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- -- @@ -31,6 +31,7 @@ with Exp_Imgv; use Exp_Imgv; with Exp_Tss; use Exp_Tss; with Exp_Util; use Exp_Util; +with Freeze; use Freeze; with Namet; use Namet; with Nlists; use Nlists; with Nmake; use Nmake; @@ -410,10 +411,18 @@ end; end if; - -- Processing for objects with address clauses + -- Processing for objects - if Is_Object (E) and then Present (Address_Clause (E)) then - Apply_Address_Clause_Check (E, N); + if Is_Object (E) then + if Present (Address_Clause (E)) then + Apply_Address_Clause_Check (E, N); + end if; + + -- If initialization statements have been captured in a compound + -- statement, insert them back into the tree now. + + Explode_Initialization_Compound_Statement (E); + return; -- Only other items requiring any front end action are types and Index: exp_aggr.adb =================================================================== --- exp_aggr.adb (revision 212640) +++ exp_aggr.adb (working copy) @@ -3033,7 +3033,7 @@ Loc : constant Source_Ptr := Sloc (N); Init_Actions : constant List_Id := New_List; Init_Node : Node_Id; - EA : Node_Id; + Comp_Stmt : Node_Id; begin -- Nothing to do if Obj is already frozen, as in this case we known we @@ -3049,12 +3049,10 @@ end loop; if not Is_Empty_List (Init_Actions) then - EA := - Make_Expression_With_Actions (Loc, - Actions => Init_Actions, - Expression => Make_Null_Statement (Loc)); - Insert_Action_After (Init_Node, EA); - Set_Initialization_Statements (Obj, EA); + Comp_Stmt := Make_Compound_Statement (Loc, + Actions => Init_Actions); + Insert_Action_After (Init_Node, Comp_Stmt); + Set_Initialization_Statements (Obj, Comp_Stmt); end if; end Collect_Initialization_Statements; Index: sprint.adb =================================================================== --- sprint.adb (revision 212640) +++ sprint.adb (working copy) @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 1992-2013, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2014, 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- -- @@ -1326,6 +1326,13 @@ Sprint_Node (Variant_Part (Node)); end if; + when N_Compound_Statement => + Write_Indent_Str ("do"); + Indent_Begin; + Sprint_Node_List (Actions (Node)); + Indent_End; + Write_Indent_Str ("end;"); + when N_Conditional_Entry_Call => Write_Indent_Str_Sloc ("select"); Indent_Begin;