diff options
author | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-07-18 11:02:42 +0000 |
---|---|---|
committer | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-07-18 11:02:42 +0000 |
commit | 0adbccedb7aa45321ef1d4f870278fc0cba6aefb (patch) | |
tree | 03c3c732e2769e977e4aa9e687237e1734f097e8 /gcc/ada/exp_ch7.adb | |
parent | d7740b707e445ee8bdf6158854a050d62258a5da (diff) | |
download | gcc-0adbccedb7aa45321ef1d4f870278fc0cba6aefb.tar.gz |
2014-07-18 Hristian Kirtchev <kirtchev@adacore.com>
* einfo.adb Last_Aggregate_Assignment is now Node 30.
(Last_Aggregate_Assignment): Include
constants in the assertion. Update the underlying node.
(Set_Last_Aggregate_Assignment): Include constants in the
assertion. Update the underlying node. (Write_Field11_Name):
Remove the entry for Last_Aggregate_Assignment.
(Write_Field30_Name): Add an entry for Last_Aggregate_Assignment.
* einfo.ads Update the node designation and usage of attribute
Last_Aggregate_Assignment.
* exp_aggr.adb (Expand_Array_Aggregate): Store the last
assignment statement used to initialize a controlled object.
(Late_Expansion): Store the last assignment statement used to
initialize a controlled record or an array of controlled objects.
* exp_ch3.adb (Expand_N_Object_Declaration): Default
initialization of objects is now performed in a separate routine.
(Default_Initialize_Object): New routine.
* exp_ch7.adb (Build_BIP_Cleanup_Stmts): Add formal parameter
Obj_Id. Update the comment on usage.
(Find_Last_Init): Remove formal parameter Typ. Update comment on usage.
Reimplement the logic. (Find_Last_Init_In_Block): New routine.
(Is_Init_Call): Add formal parameter Init_Typ. Update the
comment on usage. Account for the type init proc when trying
to determine whether a statement is an initialization call.
(Make_Adjust_Call): Rename formal parameter For_Parent to
Skip_Self. Update all occurrences of For_Parent. Account for
non-tagged types. Update the call to Make_Call.
(Make_Call): Rename formal parameter For_Parent to Skip_Self. Update
comment on usage. Update all occurrences of For_Parent.
(Make_Final_Call): Rename formal parameter For_Parent to
Skip_Self. Update all occurrences of For_Parent. Account
for non-tagged types. Update the call to Make_Call.
(Process_Object_Declaration): Most variables and constants are
now local to the routine.
* exp_ch7.ads (Make_Adjust_Call): Rename formal parameter
For_Parent to Skip_Self. Update the comment on usage.
(Make_Final_Call): Rename formal parameter For_Parent to
Skip_Self. Update the comment on usage.
2014-07-18 Ed Schonberg <schonberg@adacore.com>
* sem_ch9.adb (Analyze_Requeue): The entry being referenced
can be a procedure that is implemented by entry, and have a
formal that is a synchronized interface. It does not have to
be declared as a protected operation.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@212814 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/exp_ch7.adb')
-rw-r--r-- | gcc/ada/exp_ch7.adb | 401 |
1 files changed, 241 insertions, 160 deletions
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index b98362fc70e..c6bec4b1fa8 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -380,14 +380,14 @@ package body Exp_Ch7 is -- Initial_Condition. N denotes the package spec or body. function Make_Call - (Loc : Source_Ptr; - Proc_Id : Entity_Id; - Param : Node_Id; - For_Parent : Boolean := False) return Node_Id; + (Loc : Source_Ptr; + Proc_Id : Entity_Id; + Param : Node_Id; + Skip_Self : Boolean := False) return Node_Id; -- Subsidiary to Make_Adjust_Call and Make_Final_Call. Given the entity of - -- routine [Deep_]Adjust / Finalize and an object parameter, create an - -- adjust / finalization call. Flag For_Parent should be set when field - -- _parent is being processed. + -- routine [Deep_]Adjust or [Deep_]Finalize and an object parameter, create + -- an adjust or finalization call. Wnen flag Skip_Self is set, the related + -- action has an effect on the components only (if any). function Make_Deep_Proc (Prim : Final_Primitives; @@ -2066,22 +2066,13 @@ package body Exp_Ch7 is Has_No_Init : Boolean := False; Is_Protected : Boolean := False) is - Obj_Id : constant Entity_Id := Defining_Identifier (Decl); - Loc : constant Source_Ptr := Sloc (Decl); - Body_Ins : Node_Id; - Count_Ins : Node_Id; - Fin_Call : Node_Id; - Fin_Stmts : List_Id; - Inc_Decl : Node_Id; - Label : Node_Id; - Label_Id : Entity_Id; - Obj_Ref : Node_Id; - Obj_Typ : Entity_Id; + Loc : constant Source_Ptr := Sloc (Decl); - function Build_BIP_Cleanup_Stmts (Func_Id : Entity_Id) return Node_Id; - -- Once it has been established that the current object is in fact a - -- return object of build-in-place function Func_Id, generate the - -- following cleanup code: + function Build_BIP_Cleanup_Stmts + (Func_Id : Entity_Id; + Obj_Id : Entity_Id) return Node_Id; + -- Func_Id denotes a build-in-place function. Obj_Id is the return + -- object of Func_Id. Generate the following cleanup code: -- -- if BIPallocfrom > Secondary_Stack'Pos -- and then BIPfinalizationmaster /= null @@ -2100,21 +2091,20 @@ package body Exp_Ch7 is procedure Find_Last_Init (Decl : Node_Id; - Typ : Entity_Id; Last_Init : out Node_Id; Body_Insert : out Node_Id); - -- An object declaration has at least one and at most two init calls: - -- that of the type and the user-defined initialize. Given an object - -- declaration, Last_Init denotes the last initialization call which - -- follows the declaration. Body_Insert denotes the place where the - -- finalizer body could be potentially inserted. + -- Find the last initialization call related to object declaration + -- Decl. Last_Init denotes the last initialization call which follows + -- Decl. Body_Insert denotes the finalizer body could be potentially + -- inserted. ----------------------------- -- Build_BIP_Cleanup_Stmts -- ----------------------------- function Build_BIP_Cleanup_Stmts - (Func_Id : Entity_Id) return Node_Id + (Func_Id : Entity_Id; + Obj_Id : Entity_Id) return Node_Id is Decls : constant List_Id := New_List; Fin_Mas_Id : constant Entity_Id := @@ -2255,58 +2245,109 @@ package body Exp_Ch7 is procedure Find_Last_Init (Decl : Node_Id; - Typ : Entity_Id; Last_Init : out Node_Id; Body_Insert : out Node_Id) is + function Find_Last_Init_In_Block + (Blk : Node_Id; + Init_Typ : Entity_Id) return Node_Id; + -- Find the last initialization call within the statements of + -- block Blk. Init_Typ is type of the object being initialized. + function Is_Init_Call - (N : Node_Id; - Typ : Entity_Id) return Boolean; - -- Given an arbitrary node, determine whether N is a procedure - -- call and if it is, try to match the name of the call with the - -- [Deep_]Initialize proc of Typ. + (N : Node_Id; + Init_Typ : Entity_Id) return Boolean; + -- Determine whether node N denotes one of the initialization + -- procedures of type Init_Typ. function Next_Suitable_Statement (Stmt : Node_Id) return Node_Id; -- Given a statement which is part of a list, return the next - -- real statement while skipping over dynamic elab checks. + -- statement while skipping over dynamic elab checks. + + ----------------------------- + -- Find_Last_Init_In_Block -- + ----------------------------- + + function Find_Last_Init_In_Block + (Blk : Node_Id; + Init_Typ : Entity_Id) return Node_Id + is + HSS : constant Node_Id := Handled_Statement_Sequence (Blk); + Stmt : Node_Id; + + begin + -- Examine the individual statements of the block in reverse to + -- locate the last initialization call. + + if Present (HSS) and then Present (Statements (HSS)) then + Stmt := Last (Statements (HSS)); + while Present (Stmt) loop + + -- Peek inside nested blocks in case aborts are allowed + + if Nkind (Stmt) = N_Block_Statement then + return Find_Last_Init_In_Block (Stmt, Init_Typ); + + elsif Is_Init_Call (Stmt, Init_Typ) then + return Stmt; + end if; + + Prev (Stmt); + end loop; + end if; + + return Empty; + end Find_Last_Init_In_Block; ------------------ -- Is_Init_Call -- ------------------ function Is_Init_Call - (N : Node_Id; - Typ : Entity_Id) return Boolean + (N : Node_Id; + Init_Typ : Entity_Id) return Boolean is - begin - -- A call to [Deep_]Initialize is always direct + Call_Id : Entity_Id; + Deep_Init : Entity_Id := Empty; + Prim_Init : Entity_Id := Empty; + Type_Init : Entity_Id := Empty; + begin if Nkind (N) = N_Procedure_Call_Statement and then Nkind (Name (N)) = N_Identifier then - declare - Call_Ent : constant Entity_Id := Entity (Name (N)); - Deep_Init : constant Entity_Id := - TSS (Typ, TSS_Deep_Initialize); - Init : Entity_Id := Empty; + Call_Id := Entity (Name (N)); - begin - -- A type may have controlled components but not be - -- controlled. + -- Obtain all possible initialization routines of the object + -- type and try to match the procedure call against one of + -- them. + + -- Deep_Initialize + + Deep_Init := TSS (Init_Typ, TSS_Deep_Initialize); + + -- Primitive Initialize - if Is_Controlled (Typ) then - Init := Find_Prim_Op (Typ, Name_Initialize); + if Is_Controlled (Init_Typ) then + Prim_Init := Find_Prim_Op (Init_Typ, Name_Initialize); - if Present (Init) then - Init := Ultimate_Alias (Init); - end if; + if Present (Prim_Init) then + Prim_Init := Ultimate_Alias (Prim_Init); end if; + end if; - return - (Present (Deep_Init) and then Call_Ent = Deep_Init) - or else - (Present (Init) and then Call_Ent = Init); - end; + -- Type initialization routine + + if Has_Non_Null_Base_Init_Proc (Init_Typ) then + Type_Init := Base_Init_Proc (Init_Typ); + end if; + + return + (Present (Deep_Init) and then Call_Id = Deep_Init) + or else + (Present (Prim_Init) and then Call_Id = Prim_Init) + or else + (Present (Type_Init) and then Call_Id = Type_Init); end if; return False; @@ -2333,11 +2374,13 @@ package body Exp_Ch7 is -- Local variables - Obj_Id : constant Entity_Id := Defining_Entity (Decl); - Nod_1 : Node_Id := Empty; - Nod_2 : Node_Id := Empty; - Stmt : Node_Id; - Utyp : Entity_Id; + Obj_Id : constant Entity_Id := Defining_Entity (Decl); + Obj_Typ : constant Entity_Id := Base_Type (Etype (Obj_Id)); + Call : Node_Id; + Init_Typ : Entity_Id := Obj_Typ; + Is_Conc : Boolean := False; + Stmt : Node_Id; + Stmt_2 : Node_Id; -- Start of processing for Find_Last_Init @@ -2346,24 +2389,42 @@ package body Exp_Ch7 is Body_Insert := Empty; -- Object renamings and objects associated with controlled - -- function results do not have initialization calls. + -- function results do not require initialization. if Has_No_Init then return; end if; - if Is_Concurrent_Type (Typ) then - Utyp := Corresponding_Record_Type (Typ); - else - Utyp := Typ; - end if; + -- Obtain the proper type of the object being initialized - if Is_Private_Type (Utyp) - and then Present (Full_View (Utyp)) - then - Utyp := Full_View (Utyp); + loop + if Is_Concurrent_Type (Init_Typ) + and then Present (Corresponding_Record_Type (Init_Typ)) + then + Is_Conc := True; + Init_Typ := Corresponding_Record_Type (Init_Typ); + + elsif Is_Private_Type (Init_Typ) + and then Present (Full_View (Init_Typ)) + then + Init_Typ := Full_View (Init_Typ); + + elsif Is_Untagged_Derivation (Init_Typ) + and then not Is_Conc + then + Init_Typ := Root_Type (Init_Typ); + + else + exit; + end if; + end loop; + + if Init_Typ /= Base_Type (Init_Typ) then + Init_Typ := Base_Type (Init_Typ); end if; + Stmt := Next_Suitable_Statement (Decl); + -- A limited controlled object initialized by a function call uses -- the build-in-place machinery to obtain its value. @@ -2381,11 +2442,10 @@ package body Exp_Ch7 is -- In this scenario the declaration of the temporary acts as the -- last initialization statement. - if Is_Limited_Type (Utyp) + if Is_Limited_Type (Init_Typ) and then Has_Init_Expression (Decl) and then No (Expression (Decl)) then - Stmt := Next (Decl); while Present (Stmt) loop if Nkind (Stmt) = N_Object_Declaration and then Present (Expression (Stmt)) @@ -2400,68 +2460,77 @@ package body Exp_Ch7 is Next (Stmt); end loop; - -- The init procedures are arranged as follows: - - -- Object : Controlled_Type; - -- Controlled_TypeIP (Object); - -- [[Deep_]Initialize (Object);] - - -- where the user-defined initialize may be optional or may appear - -- inside a block when abort deferral is needed. + -- In all other cases the initialization calls follow the related + -- object. The general structure of object initialization built by + -- routine Default_Initialize_Object is as follows: + + -- [begin -- aborts allowed + -- Abort_Defer;] + -- Type_Init_Proc (Obj); + -- [begin] -- exceptions allowed + -- Deep_Initialize (Obj); + -- [exception -- exceptions allowed + -- when others => + -- Deep_Finalize (Obj, Self => False); + -- raise; + -- end;] + -- [at end -- aborts allowed + -- Abort_Undefer; + -- end;] + + -- When aborts are allowed, the initialization calls are housed + -- within a block. + + elsif Nkind (Stmt) = N_Block_Statement then + Last_Init := Find_Last_Init_In_Block (Stmt, Init_Typ); + Body_Insert := Stmt; + + -- Otherwise the initialization calls follow the related object else - Nod_1 := Next_Suitable_Statement (Decl); - - if Present (Nod_1) then - Nod_2 := Next_Suitable_Statement (Nod_1); + Stmt_2 := Next_Suitable_Statement (Stmt); - -- The statement following an object declaration is always a - -- call to the type init proc. + -- Check for an optional call to Deep_Initialize which may + -- appear within a block depending on whether the object has + -- controlled components. - Last_Init := Nod_1; - end if; - - -- Optional user-defined init or deep init processing - - if Present (Nod_2) then - - -- The statement following the type init proc may be a block - -- statement in cases where abort deferral is required. - - if Nkind (Nod_2) = N_Block_Statement then - declare - HSS : constant Node_Id := - Handled_Statement_Sequence (Nod_2); - Stmt : Node_Id; - - begin - if Present (HSS) - and then Present (Statements (HSS)) - then - -- Examine individual block statements and locate - -- the call to [Deep_]Initialze. + if Present (Stmt_2) then + if Nkind (Stmt_2) = N_Block_Statement then + Call := Find_Last_Init_In_Block (Stmt_2, Init_Typ); - Stmt := First (Statements (HSS)); - while Present (Stmt) loop - if Is_Init_Call (Stmt, Utyp) then - Last_Init := Stmt; - Body_Insert := Nod_2; + if Present (Call) then + Last_Init := Call; + Body_Insert := Stmt_2; + end if; - exit; - end if; + elsif Is_Init_Call (Stmt_2, Init_Typ) then + Last_Init := Stmt_2; + Body_Insert := Last_Init; + end if; - Next (Stmt); - end loop; - end if; - end; + -- If the object lacks a call to Deep_Initialize, then it must + -- have a call to its related type init proc. - elsif Is_Init_Call (Nod_2, Utyp) then - Last_Init := Nod_2; - end if; + elsif Is_Init_Call (Stmt, Init_Typ) then + Last_Init := Stmt; + Body_Insert := Last_Init; end if; end if; end Find_Last_Init; + -- Local variables + + Obj_Id : constant Entity_Id := Defining_Identifier (Decl); + Body_Ins : Node_Id; + Count_Ins : Node_Id; + Fin_Call : Node_Id; + Fin_Stmts : List_Id; + Inc_Decl : Node_Id; + Label : Node_Id; + Label_Id : Entity_Id; + Obj_Ref : Node_Id; + Obj_Typ : Entity_Id; + -- Start of processing for Process_Object_Declaration begin @@ -2492,7 +2561,7 @@ package body Exp_Ch7 is -- initialized via an aggregate, then the counter must be inserted -- after the last aggregate assignment. - if Ekind (Obj_Id) = E_Variable + if Ekind_In (Obj_Id, E_Constant, E_Variable) and then Present (Last_Aggregate_Assignment (Obj_Id)) then Count_Ins := Last_Aggregate_Assignment (Obj_Id); @@ -2502,7 +2571,7 @@ package body Exp_Ch7 is -- either [Deep_]Initialize or the type specific init proc. else - Find_Last_Init (Decl, Obj_Typ, Count_Ins, Body_Ins); + Find_Last_Init (Decl, Count_Ins, Body_Ins); end if; Insert_After (Count_Ins, Inc_Decl); @@ -2526,7 +2595,7 @@ package body Exp_Ch7 is end if; -- Create the associated label with this object, generate: - -- + -- L<counter> : label; Label_Id := @@ -2541,7 +2610,7 @@ package body Exp_Ch7 is Label_Construct => Label)); -- Create the associated jump with this object, generate: - + -- -- when <counter> => -- goto L<counter>; @@ -2685,7 +2754,8 @@ package body Exp_Ch7 is if Is_Build_In_Place_Function (Func_Id) and then Needs_BIP_Finalization_Master (Func_Id) then - Append_To (Fin_Stmts, Build_BIP_Cleanup_Stmts (Func_Id)); + Append_To + (Fin_Stmts, Build_BIP_Cleanup_Stmts (Func_Id, Obj_Id)); end if; end; end if; @@ -4933,9 +5003,9 @@ package body Exp_Ch7 is ----------------------- function Make_Adjust_Call - (Obj_Ref : Node_Id; - Typ : Entity_Id; - For_Parent : Boolean := False) return Node_Id + (Obj_Ref : Node_Id; + Typ : Entity_Id; + Skip_Self : Boolean := False) return Node_Id is Loc : constant Source_Ptr := Sloc (Obj_Ref); Adj_Id : Entity_Id := Empty; @@ -4972,11 +5042,13 @@ package body Exp_Ch7 is Ref := Unchecked_Convert_To (Utyp, Ref); end if; - -- Select the appropriate version of adjust - - if For_Parent then + if Skip_Self then if Has_Controlled_Component (Utyp) then - Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust); + if Is_Tagged_Type (Utyp) then + Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust); + else + Adj_Id := TSS (Utyp, TSS_Deep_Adjust); + end if; end if; -- Class-wide types, interfaces and types with controlled components @@ -5027,7 +5099,11 @@ package body Exp_Ch7 is Ref := Convert_View (Adj_Id, Ref); end if; - return Make_Call (Loc, Adj_Id, New_Copy_Tree (Ref), For_Parent); + return + Make_Call (Loc, + Proc_Id => Adj_Id, + Param => New_Copy_Tree (Ref), + Skip_Self => Skip_Self); else return Empty; end if; @@ -5075,19 +5151,18 @@ package body Exp_Ch7 is --------------- function Make_Call - (Loc : Source_Ptr; - Proc_Id : Entity_Id; - Param : Node_Id; - For_Parent : Boolean := False) return Node_Id + (Loc : Source_Ptr; + Proc_Id : Entity_Id; + Param : Node_Id; + Skip_Self : Boolean := False) return Node_Id is Params : constant List_Id := New_List (Param); begin - -- When creating a call to Deep_Finalize for a _parent field of a - -- derived type, disable the invocation of the nested Finalize by giving - -- the corresponding flag a False value. + -- Do not apply the controlled action to the object itself by signaling + -- the related routine to avoid self. - if For_Parent then + if Skip_Self then Append_To (Params, New_Occurrence_Of (Standard_False, Loc)); end if; @@ -6307,13 +6382,13 @@ package body Exp_Ch7 is if Needs_Finalization (Par_Typ) then Call := Make_Adjust_Call - (Obj_Ref => + (Obj_Ref => Make_Selected_Component (Loc, Prefix => Make_Identifier (Loc, Name_V), Selector_Name => Make_Identifier (Loc, Name_uParent)), - Typ => Par_Typ, - For_Parent => True); + Typ => Par_Typ, + Skip_Self => True); -- Generate: -- Deep_Adjust (V._parent, False); -- No_Except_Propagat @@ -6882,13 +6957,13 @@ package body Exp_Ch7 is if Needs_Finalization (Par_Typ) then Call := Make_Final_Call - (Obj_Ref => + (Obj_Ref => Make_Selected_Component (Loc, Prefix => Make_Identifier (Loc, Name_V), Selector_Name => Make_Identifier (Loc, Name_uParent)), - Typ => Par_Typ, - For_Parent => True); + Typ => Par_Typ, + Skip_Self => True); -- Generate: -- Deep_Finalize (V._parent, False); -- No_Except_Propag @@ -7118,9 +7193,9 @@ package body Exp_Ch7 is ---------------------- function Make_Final_Call - (Obj_Ref : Node_Id; - Typ : Entity_Id; - For_Parent : Boolean := False) return Node_Id + (Obj_Ref : Node_Id; + Typ : Entity_Id; + Skip_Self : Boolean := False) return Node_Id is Loc : constant Source_Ptr := Sloc (Obj_Ref); Atyp : Entity_Id; @@ -7203,11 +7278,13 @@ package body Exp_Ch7 is Set_Assignment_OK (Ref); end if; - -- Select the appropriate version of Finalize - - if For_Parent then + if Skip_Self then if Has_Controlled_Component (Utyp) then - Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize); + if Is_Tagged_Type (Utyp) then + Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize); + else + Fin_Id := TSS (Utyp, TSS_Deep_Finalize); + end if; end if; -- Class-wide types, interfaces and types with controlled components @@ -7278,7 +7355,11 @@ package body Exp_Ch7 is Ref := Convert_View (Fin_Id, Ref); end if; - return Make_Call (Loc, Fin_Id, New_Copy_Tree (Ref), For_Parent); + return + Make_Call (Loc, + Proc_Id => Fin_Id, + Param => New_Copy_Tree (Ref), + Skip_Self => Skip_Self); else return Empty; end if; |