diff options
Diffstat (limited to 'gcc/ada/exp_ch7.adb')
-rw-r--r-- | gcc/ada/exp_ch7.adb | 843 |
1 files changed, 448 insertions, 395 deletions
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb index 5d8ad7d..f7807ac 100644 --- a/gcc/ada/exp_ch7.adb +++ b/gcc/ada/exp_ch7.adb @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 1992-2020, Free Software Foundation, Inc. -- +-- Copyright (C) 1992-2021, 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- -- @@ -27,43 +27,48 @@ -- - controlled types -- - transient scopes -with Atree; use Atree; -with Contracts; use Contracts; -with Debug; use Debug; -with Einfo; use Einfo; -with Elists; use Elists; -with Errout; use Errout; -with Exp_Ch6; use Exp_Ch6; -with Exp_Ch9; use Exp_Ch9; -with Exp_Ch11; use Exp_Ch11; -with Exp_Dbug; use Exp_Dbug; -with Exp_Dist; use Exp_Dist; -with Exp_Disp; use Exp_Disp; -with Exp_Prag; use Exp_Prag; -with Exp_Tss; use Exp_Tss; -with Exp_Util; use Exp_Util; -with Freeze; use Freeze; -with Lib; use Lib; -with Nlists; use Nlists; -with Nmake; use Nmake; -with Opt; use Opt; -with Output; use Output; -with Restrict; use Restrict; -with Rident; use Rident; -with Rtsfind; use Rtsfind; -with Sinfo; use Sinfo; -with Sem; use Sem; -with Sem_Aux; use Sem_Aux; -with Sem_Ch3; use Sem_Ch3; -with Sem_Ch7; use Sem_Ch7; -with Sem_Ch8; use Sem_Ch8; -with Sem_Res; use Sem_Res; -with Sem_Util; use Sem_Util; -with Snames; use Snames; -with Stand; use Stand; -with Tbuild; use Tbuild; -with Ttypes; use Ttypes; -with Uintp; use Uintp; +with Atree; use Atree; +with Contracts; use Contracts; +with Debug; use Debug; +with Einfo; use Einfo; +with Einfo.Entities; use Einfo.Entities; +with Einfo.Utils; use Einfo.Utils; +with Elists; use Elists; +with Errout; use Errout; +with Exp_Ch6; use Exp_Ch6; +with Exp_Ch9; use Exp_Ch9; +with Exp_Ch11; use Exp_Ch11; +with Exp_Dbug; use Exp_Dbug; +with Exp_Dist; use Exp_Dist; +with Exp_Disp; use Exp_Disp; +with Exp_Prag; use Exp_Prag; +with Exp_Tss; use Exp_Tss; +with Exp_Util; use Exp_Util; +with Freeze; use Freeze; +with GNAT_CUDA; use GNAT_CUDA; +with Lib; use Lib; +with Nlists; use Nlists; +with Nmake; use Nmake; +with Opt; use Opt; +with Output; use Output; +with Restrict; use Restrict; +with Rident; use Rident; +with Rtsfind; use Rtsfind; +with Sinfo; use Sinfo; +with Sinfo.Nodes; use Sinfo.Nodes; +with Sinfo.Utils; use Sinfo.Utils; +with Sem; use Sem; +with Sem_Aux; use Sem_Aux; +with Sem_Ch3; use Sem_Ch3; +with Sem_Ch7; use Sem_Ch7; +with Sem_Ch8; use Sem_Ch8; +with Sem_Res; use Sem_Res; +with Sem_Util; use Sem_Util; +with Snames; use Snames; +with Stand; use Stand; +with Tbuild; use Tbuild; +with Ttypes; use Ttypes; +with Uintp; use Uintp; package body Exp_Ch7 is @@ -126,11 +131,6 @@ package body Exp_Ch7 is -- Transient Blocks and Finalization Management -- -------------------------------------------------- - function Find_Transient_Context (N : Node_Id) return Node_Id; - -- Locate a suitable context for arbitrary node N which may need to be - -- serviced by a transient scope. Return Empty if no suitable context is - -- available. - procedure Insert_Actions_In_Scope_Around (N : Node_Id; Clean : Boolean; @@ -150,12 +150,6 @@ package body Exp_Ch7 is -- involves controlled objects or secondary stack usage, the corresponding -- cleanup actions are performed at the end of the block. - procedure Set_Node_To_Be_Wrapped (N : Node_Id); - -- Set the field Node_To_Be_Wrapped of the current scope - - -- ??? The entire comment needs to be rewritten - -- ??? which entire comment? - procedure Store_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id); -- Shared processing for Store_xxx_Actions_In_Scope @@ -486,7 +480,7 @@ package body Exp_Ch7 is Skip_Self : Boolean := False) return Node_Id; -- Subsidiary to Make_Adjust_Call and Make_Final_Call. Given the entity of -- routine [Deep_]Adjust or [Deep_]Finalize and an object parameter, create - -- an adjust or finalization call. Wnen flag Skip_Self is set, the related + -- an adjust or finalization call. When flag Skip_Self is set, the related -- action has an effect on the components only (if any). function Make_Deep_Proc @@ -1550,6 +1544,11 @@ package body Exp_Ch7 is -- Create the spec and body of the finalizer and insert them in the -- proper place in the tree depending on the context. + function New_Finalizer_Name + (Spec_Id : Node_Id; For_Spec : Boolean) return Name_Id; + -- Create a fully qualified name of a package spec or body finalizer. + -- The generated name is of the form: xx__yy__finalize_[spec|body]. + procedure Process_Declarations (Decls : List_Id; Preprocess : Boolean := False; @@ -1557,7 +1556,8 @@ package body Exp_Ch7 is -- Inspect a list of declarations or statements which may contain -- objects that need finalization. When flag Preprocess is set, the -- routine will simply count the total number of controlled objects in - -- Decls. Flag Top_Level denotes whether the processing is done for + -- Decls and set Counter_Val accordingly. Top_Level is only relevant + -- when Preprocess is set and if True, the processing is performed for -- objects in nested package declarations or instances. procedure Process_Object_Declaration @@ -1692,58 +1692,6 @@ package body Exp_Ch7 is ---------------------- procedure Create_Finalizer is - function New_Finalizer_Name return Name_Id; - -- Create a fully qualified name of a package spec or body finalizer. - -- The generated name is of the form: xx__yy__finalize_[spec|body]. - - ------------------------ - -- New_Finalizer_Name -- - ------------------------ - - function New_Finalizer_Name return Name_Id is - procedure New_Finalizer_Name (Id : Entity_Id); - -- Place "__<name-of-Id>" in the name buffer. If the identifier - -- has a non-standard scope, process the scope first. - - ------------------------ - -- New_Finalizer_Name -- - ------------------------ - - procedure New_Finalizer_Name (Id : Entity_Id) is - begin - if Scope (Id) = Standard_Standard then - Get_Name_String (Chars (Id)); - - else - New_Finalizer_Name (Scope (Id)); - Add_Str_To_Name_Buffer ("__"); - Add_Str_To_Name_Buffer (Get_Name_String (Chars (Id))); - end if; - end New_Finalizer_Name; - - -- Start of processing for New_Finalizer_Name - - begin - -- Create the fully qualified name of the enclosing scope - - New_Finalizer_Name (Spec_Id); - - -- Generate: - -- __finalize_[spec|body] - - Add_Str_To_Name_Buffer ("__finalize_"); - - if For_Package_Spec then - Add_Str_To_Name_Buffer ("spec"); - else - Add_Str_To_Name_Buffer ("body"); - end if; - - return Name_Find; - end New_Finalizer_Name; - - -- Local variables - Body_Id : Entity_Id; Fin_Body : Node_Id; Fin_Spec : Node_Id; @@ -1751,8 +1699,6 @@ package body Exp_Ch7 is Label : Node_Id; Label_Id : Entity_Id; - -- Start of processing for Create_Finalizer - begin -- Step 1: Creation of the finalizer name @@ -1763,7 +1709,8 @@ package body Exp_Ch7 is -- xx__yy__finalize_[spec|body] if For_Package then - Fin_Id := Make_Defining_Identifier (Loc, New_Finalizer_Name); + Fin_Id := Make_Defining_Identifier + (Loc, New_Finalizer_Name (Spec_Id, For_Package_Spec)); Set_Has_Qualified_Name (Fin_Id); Set_Has_Fully_Qualified_Name (Fin_Id); @@ -1839,10 +1786,22 @@ package body Exp_Ch7 is Make_Procedure_Specification (Loc, Defining_Unit_Name => Fin_Id)); + if For_Package then + Set_Is_Exported (Fin_Id); + Set_Interface_Name (Fin_Id, + Make_String_Literal (Loc, + Strval => Get_Name_String (Chars (Fin_Id)))); + end if; + -- Step 3: Creation of the finalizer body - if Has_Ctrl_Objs then + -- Has_Ctrl_Objs might be set because of a generic package body having + -- controlled objects. In this case, Jump_Alts may be empty and no + -- case nor goto statements are needed. + if Has_Ctrl_Objs + and then not Is_Empty_List (Jump_Alts) + then -- Add L0, the default destination to the jump block Label_Id := Make_Identifier (Loc, New_External_Name ('L', 0)); @@ -2164,6 +2123,54 @@ package body Exp_Ch7 is Set_Is_Checked_Ghost_Entity (Fin_Id, False); end Create_Finalizer; + ------------------------ + -- New_Finalizer_Name -- + ------------------------ + + function New_Finalizer_Name + (Spec_Id : Node_Id; For_Spec : Boolean) return Name_Id + is + procedure New_Finalizer_Name (Id : Entity_Id); + -- Place "__<name-of-Id>" in the name buffer. If the identifier + -- has a non-standard scope, process the scope first. + + ------------------------ + -- New_Finalizer_Name -- + ------------------------ + + procedure New_Finalizer_Name (Id : Entity_Id) is + begin + if Scope (Id) = Standard_Standard then + Get_Name_String (Chars (Id)); + + else + New_Finalizer_Name (Scope (Id)); + Add_Str_To_Name_Buffer ("__"); + Get_Name_String_And_Append (Chars (Id)); + end if; + end New_Finalizer_Name; + + -- Start of processing for New_Finalizer_Name + + begin + -- Create the fully qualified name of the enclosing scope + + New_Finalizer_Name (Spec_Id); + + -- Generate: + -- __finalize_[spec|body] + + Add_Str_To_Name_Buffer ("__finalize_"); + + if For_Spec then + Add_Str_To_Name_Buffer ("spec"); + else + Add_Str_To_Name_Buffer ("body"); + end if; + + return Name_Find; + end New_Finalizer_Name; + -------------------------- -- Process_Declarations -- -------------------------- @@ -2543,6 +2550,73 @@ package body Exp_Ch7 is end if; end if; + -- Call the xxx__finalize_body procedure of a library level + -- package instantiation if the body contains finalization + -- statements. + + if Present (Generic_Parent (Spec)) + and then Is_Library_Level_Entity (Pack_Id) + and then Present (Body_Entity (Generic_Parent (Spec))) + then + if Preprocess then + declare + P : Node_Id; + begin + P := Parent (Body_Entity (Generic_Parent (Spec))); + while Present (P) + and then Nkind (P) /= N_Package_Body + loop + P := Parent (P); + end loop; + + if Present (P) then + Old_Counter_Val := Counter_Val; + Process_Declarations (Declarations (P), Preprocess); + + -- Note that we are processing the generic body + -- template and not the actually instantiation + -- (which is generated too late for us to process + -- it), so there is no need to update in particular + -- to update Last_Top_Level_Ctrl_Construct here. + + if Counter_Val > Old_Counter_Val then + Counter_Val := Old_Counter_Val; + Set_Has_Controlled_Component (Pack_Id); + end if; + end if; + end; + + elsif Has_Controlled_Component (Pack_Id) then + + -- We import the xxx__finalize_body routine since the + -- generic body will be instantiated later. + + declare + Id : constant Node_Id := + Make_Defining_Identifier (Loc, + New_Finalizer_Name (Defining_Unit_Name (Spec), + For_Spec => False)); + + begin + Set_Has_Qualified_Name (Id); + Set_Has_Fully_Qualified_Name (Id); + Set_Is_Imported (Id); + Set_Has_Completion (Id); + Set_Interface_Name (Id, + Make_String_Literal (Loc, + Strval => Get_Name_String (Chars (Id)))); + + Append_New_To (Finalizer_Stmts, + Make_Subprogram_Declaration (Loc, + Make_Procedure_Specification (Loc, + Defining_Unit_Name => Id))); + Append_To (Finalizer_Stmts, + Make_Procedure_Call_Statement (Loc, + Name => New_Occurrence_Of (Id, Loc))); + end; + end if; + end if; + -- Nested package bodies, avoid generics elsif Nkind (Decl) = N_Package_Body then @@ -2553,8 +2627,7 @@ package body Exp_Ch7 is if Is_Ignored_Ghost_Entity (Defining_Entity (Decl)) then null; - elsif Ekind (Corresponding_Spec (Decl)) /= - E_Generic_Package + elsif Ekind (Corresponding_Spec (Decl)) /= E_Generic_Package then Old_Counter_Val := Counter_Val; Process_Declarations (Declarations (Decl), Preprocess); @@ -2729,7 +2802,7 @@ package body Exp_Ch7 is -- Perform minor decoration in order to set the master and the -- storage pool attributes. - Set_Ekind (Ptr_Typ, E_Access_Type); + Mutate_Ekind (Ptr_Typ, E_Access_Type); Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id); Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id); @@ -3044,6 +3117,8 @@ package body Exp_Ch7 is -- Otherwise the initialization calls follow the related object else + pragma Assert (Present (Stmt)); + Stmt_2 := Next_Suitable_Statement (Stmt); -- Check for an optional call to Deep_Initialize which may @@ -3545,6 +3620,14 @@ package body Exp_Ch7 is or else Scope_Depth_Value (Spec_Id) /= Uint_1 or else (Is_Generic_Instance (Spec_Id) and then Package_Instantiation (Spec_Id) /= N)) + + -- Still need to process package body instantiations which may + -- contain objects requiring finalization. + + and then not + (For_Package_Body + and then Is_Library_Level_Entity (Spec_Id) + and then Is_Generic_Instance (Spec_Id)) then return; end if; @@ -3626,7 +3709,7 @@ package body Exp_Ch7 is -- Step 3: Finalizer creation - if Acts_As_Clean or else Has_Ctrl_Objs or else Has_Tagged_Types then + if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then Create_Finalizer; end if; end Build_Finalizer_Helper; @@ -3798,7 +3881,9 @@ package body Exp_Ch7 is -- -- Perform postcondition checks after general finalization, but -- -- before finalization of 'Old related objects. -- - -- if not Raised_Finalization_Exception then + -- if not Raised_Finalization_Exception + -- and then Return_Success_For_Postcond + -- then -- begin -- -- Re-enable postconditions and check them -- @@ -3976,7 +4061,9 @@ package body Exp_Ch7 is -- Generate: -- - -- if not Raised_Finalization_Exception then + -- if not Raised_Finalization_Exception + -- and then Return_Success_For_Postcond + -- then -- begin -- Postcond_Enabled := True; -- _postconditions [(Result_Obj_For_Postcond[.all])]; @@ -3991,10 +4078,15 @@ package body Exp_Ch7 is Append_To (Fin_Controller_Stmts, Make_If_Statement (Loc, Condition => - Make_Op_Not (Loc, + Make_And_Then (Loc, + Left_Opnd => + Make_Op_Not (Loc, + Right_Opnd => + New_Occurrence_Of + (Raised_Finalization_Exception_Id, Loc)), Right_Opnd => New_Occurrence_Of - (Raised_Finalization_Exception_Id, Loc)), + (Get_Return_Success_For_Postcond (Def_Ent), Loc)), Then_Statements => New_List ( Make_Block_Statement (Loc, Handled_Statement_Sequence => @@ -5018,15 +5110,6 @@ package body Exp_Ch7 is end if; end Convert_View; - ------------------------------- - -- CW_Or_Has_Controlled_Part -- - ------------------------------- - - function CW_Or_Has_Controlled_Part (T : Entity_Id) return Boolean is - begin - return Is_Class_Wide_Type (T) or else Needs_Finalization (T); - end CW_Or_Has_Controlled_Part; - ------------------------ -- Enclosing_Function -- ------------------------ @@ -5060,37 +5143,47 @@ package body Exp_Ch7 is (N : Node_Id; Manage_Sec_Stack : Boolean) is - procedure Create_Transient_Scope (Constr : Node_Id); - -- Place a new scope on the scope stack in order to service construct - -- Constr. The new scope may also manage the secondary stack. + function Is_Package_Or_Subprogram (Id : Entity_Id) return Boolean; + -- Determine whether arbitrary Id denotes a package or subprogram [body] + + function Find_Enclosing_Transient_Scope return Entity_Id; + -- Examine the scope stack looking for the nearest enclosing transient + -- scope within the innermost enclosing package or subprogram. Return + -- Empty if no such scope exists. + + function Find_Transient_Context (N : Node_Id) return Node_Id; + -- Locate a suitable context for arbitrary node N which may need to be + -- serviced by a transient scope. Return Empty if no suitable context + -- is available. procedure Delegate_Sec_Stack_Management; -- Move the management of the secondary stack to the nearest enclosing -- suitable scope. - function Find_Enclosing_Transient_Scope return Entity_Id; - -- Examine the scope stack looking for the nearest enclosing transient - -- scope. Return Empty if no such scope exists. - - function Is_Package_Or_Subprogram (Id : Entity_Id) return Boolean; - -- Determine whether arbitrary Id denotes a package or subprogram [body] + procedure Create_Transient_Scope (Context : Node_Id); + -- Place a new scope on the scope stack in order to service construct + -- Context. Context is the node found by Find_Transient_Context. The + -- new scope may also manage the secondary stack. ---------------------------- -- Create_Transient_Scope -- ---------------------------- - procedure Create_Transient_Scope (Constr : Node_Id) is + procedure Create_Transient_Scope (Context : Node_Id) is Loc : constant Source_Ptr := Sloc (N); Iter_Loop : Entity_Id; - Trans_Scop : Entity_Id; + Trans_Scop : constant Entity_Id := + New_Internal_Entity (E_Block, Current_Scope, Loc, 'B'); begin - Trans_Scop := New_Internal_Entity (E_Block, Current_Scope, Loc, 'B'); Set_Etype (Trans_Scop, Standard_Void_Type); + -- Push a new scope, and set its Node_To_Be_Wrapped and Is_Transient + -- fields. + Push_Scope (Trans_Scop); - Set_Node_To_Be_Wrapped (Constr); + Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped := Context; Set_Scope_Is_Transient; -- The transient scope must also manage the secondary stack @@ -5141,37 +5234,34 @@ package body Exp_Ch7 is ----------------------------------- procedure Delegate_Sec_Stack_Management is - Scop_Id : Entity_Id; - Scop_Rec : Scope_Stack_Entry; - begin for Index in reverse Scope_Stack.First .. Scope_Stack.Last loop - Scop_Rec := Scope_Stack.Table (Index); - Scop_Id := Scop_Rec.Entity; - - -- Prevent the search from going too far or within the scope space - -- of another unit. + declare + Scope : Scope_Stack_Entry renames Scope_Stack.Table (Index); + begin + -- Prevent the search from going too far or within the scope + -- space of another unit. - if Scop_Id = Standard_Standard then - return; + if Scope.Entity = Standard_Standard then + return; - -- No transient scope should be encountered during the traversal - -- because Establish_Transient_Scope should have already handled - -- this case. + -- No transient scope should be encountered during the + -- traversal because Establish_Transient_Scope should have + -- already handled this case. - elsif Scop_Rec.Is_Transient then - pragma Assert (False); - return; + elsif Scope.Is_Transient then + raise Program_Error; - -- The construct which requires secondary stack management is - -- always enclosed by a package or subprogram scope. + -- The construct that requires secondary stack management is + -- always enclosed by a package or subprogram scope. - elsif Is_Package_Or_Subprogram (Scop_Id) then - Set_Uses_Sec_Stack (Scop_Id); - Check_Restriction (No_Secondary_Stack, N); + elsif Is_Package_Or_Subprogram (Scope.Entity) then + Set_Uses_Sec_Stack (Scope.Entity); + Check_Restriction (No_Secondary_Stack, N); - return; - end if; + return; + end if; + end; end loop; -- At this point no suitable scope was found. This should never occur @@ -5186,30 +5276,198 @@ package body Exp_Ch7 is ------------------------------------ function Find_Enclosing_Transient_Scope return Entity_Id is - Scop_Id : Entity_Id; - Scop_Rec : Scope_Stack_Entry; - begin for Index in reverse Scope_Stack.First .. Scope_Stack.Last loop - Scop_Rec := Scope_Stack.Table (Index); - Scop_Id := Scop_Rec.Entity; - - -- Prevent the search from going too far or within the scope space - -- of another unit. + declare + Scope : Scope_Stack_Entry renames Scope_Stack.Table (Index); + begin + -- Prevent the search from going too far or within the scope + -- space of another unit. - if Scop_Id = Standard_Standard - or else Is_Package_Or_Subprogram (Scop_Id) - then - exit; + if Scope.Entity = Standard_Standard + or else Is_Package_Or_Subprogram (Scope.Entity) + then + exit; - elsif Scop_Rec.Is_Transient then - return Scop_Id; - end if; + elsif Scope.Is_Transient then + return Scope.Entity; + end if; + end; end loop; return Empty; end Find_Enclosing_Transient_Scope; + ---------------------------- + -- Find_Transient_Context -- + ---------------------------- + + function Find_Transient_Context (N : Node_Id) return Node_Id is + Curr : Node_Id := N; + Prev : Node_Id := Empty; + + begin + while Present (Curr) loop + case Nkind (Curr) is + + -- Declarations + + -- Declarations act as a boundary for a transient scope even if + -- they are not wrapped, see Wrap_Transient_Declaration. + + when N_Object_Declaration + | N_Object_Renaming_Declaration + | N_Subtype_Declaration + => + return Curr; + + -- Statements + + -- Statements and statement-like constructs act as a boundary + -- for a transient scope. + + when N_Accept_Alternative + | N_Attribute_Definition_Clause + | N_Case_Statement + | N_Case_Statement_Alternative + | N_Code_Statement + | N_Delay_Alternative + | N_Delay_Until_Statement + | N_Delay_Relative_Statement + | N_Discriminant_Association + | N_Elsif_Part + | N_Entry_Body_Formal_Part + | N_Exit_Statement + | N_If_Statement + | N_Iteration_Scheme + | N_Terminate_Alternative + => + pragma Assert (Present (Prev)); + return Prev; + + when N_Assignment_Statement => + return Curr; + + when N_Entry_Call_Statement + | N_Procedure_Call_Statement + => + -- When an entry or procedure call acts as the alternative + -- of a conditional or timed entry call, the proper context + -- is that of the alternative. + + if Nkind (Parent (Curr)) = N_Entry_Call_Alternative + and then Nkind (Parent (Parent (Curr))) in + N_Conditional_Entry_Call | N_Timed_Entry_Call + then + return Parent (Parent (Curr)); + + -- General case for entry or procedure calls + + else + return Curr; + end if; + + when N_Pragma => + + -- Pragma Check is not a valid transient context in + -- GNATprove mode because the pragma must remain unchanged. + + if GNATprove_Mode + and then Get_Pragma_Id (Curr) = Pragma_Check + then + return Empty; + + -- General case for pragmas + + else + return Curr; + end if; + + when N_Raise_Statement => + return Curr; + + when N_Simple_Return_Statement => + + -- A return statement is not a valid transient context when + -- the function itself requires transient scope management + -- because the result will be reclaimed too early. + + if Requires_Transient_Scope (Etype + (Return_Applies_To (Return_Statement_Entity (Curr)))) + then + return Empty; + + -- General case for return statements + + else + return Curr; + end if; + + -- Special + + when N_Attribute_Reference => + if Is_Procedure_Attribute_Name (Attribute_Name (Curr)) then + return Curr; + end if; + + -- An Ada 2012 iterator specification is not a valid context + -- because Analyze_Iterator_Specification already employs + -- special processing for it. + + when N_Iterator_Specification => + return Empty; + + when N_Loop_Parameter_Specification => + + -- An iteration scheme is not a valid context because + -- routine Analyze_Iteration_Scheme already employs + -- special processing. + + if Nkind (Parent (Curr)) = N_Iteration_Scheme then + return Empty; + else + return Parent (Curr); + end if; + + -- Termination + + -- The following nodes represent "dummy contexts" which do not + -- need to be wrapped. + + when N_Component_Declaration + | N_Discriminant_Specification + | N_Parameter_Specification + => + return Empty; + + -- If the traversal leaves a scope without having been able to + -- find a construct to wrap, something is going wrong, but this + -- can happen in error situations that are not detected yet + -- (such as a dynamic string in a pragma Export). + + when N_Block_Statement + | N_Entry_Body + | N_Package_Body + | N_Package_Declaration + | N_Protected_Body + | N_Subprogram_Body + | N_Task_Body + => + return Empty; + + -- Default + + when others => + null; + end case; + + Prev := Curr; + Curr := Parent (Curr); + end loop; + + return Empty; + end Find_Transient_Context; + ------------------------------ -- Is_Package_Or_Subprogram -- ------------------------------ @@ -5232,8 +5490,8 @@ package body Exp_Ch7 is -- Start of processing for Establish_Transient_Scope begin - -- Do not create a new transient scope if there is an existing transient - -- scope on the stack. + -- Do not create a new transient scope if there is already an enclosing + -- transient scope within the innermost enclosing package or subprogram. if Present (Trans_Id) then @@ -5247,9 +5505,8 @@ package body Exp_Ch7 is return; end if; - -- At this point it is known that the scope stack is free of transient - -- scopes. Locate the proper construct which must be serviced by a new - -- transient scope. + -- Find the construct that must be serviced by a new transient scope, if + -- it exists. Context := Find_Transient_Context (N); @@ -5661,6 +5918,13 @@ package body Exp_Ch7 is Build_Static_Dispatch_Tables (N); end if; + -- If procedures marked with CUDA_Global have been defined within N, + -- we need to register them with the CUDA runtime at program startup. + -- This requires multiple declarations and function calls which need + -- to be appended to N's declarations. + + Build_And_Insert_CUDA_Initialization (N); + Build_Task_Activation_Call (N); -- Verify the run-time semantics of pragma Initial_Condition at the @@ -5852,208 +6116,6 @@ package body Exp_Ch7 is end if; end Expand_N_Package_Declaration; - ---------------------------- - -- Find_Transient_Context -- - ---------------------------- - - function Find_Transient_Context (N : Node_Id) return Node_Id is - Curr : Node_Id; - Prev : Node_Id; - - begin - Curr := N; - Prev := Empty; - while Present (Curr) loop - case Nkind (Curr) is - - -- Declarations - - -- Declarations act as a boundary for a transient scope even if - -- they are not wrapped, see Wrap_Transient_Declaration. - - when N_Object_Declaration - | N_Object_Renaming_Declaration - | N_Subtype_Declaration - => - return Curr; - - -- Statements - - -- Statements and statement-like constructs act as a boundary for - -- a transient scope. - - when N_Accept_Alternative - | N_Attribute_Definition_Clause - | N_Case_Statement - | N_Case_Statement_Alternative - | N_Code_Statement - | N_Delay_Alternative - | N_Delay_Until_Statement - | N_Delay_Relative_Statement - | N_Discriminant_Association - | N_Elsif_Part - | N_Entry_Body_Formal_Part - | N_Exit_Statement - | N_If_Statement - | N_Iteration_Scheme - | N_Terminate_Alternative - => - pragma Assert (Present (Prev)); - return Prev; - - when N_Assignment_Statement => - return Curr; - - when N_Entry_Call_Statement - | N_Procedure_Call_Statement - => - -- When an entry or procedure call acts as the alternative of a - -- conditional or timed entry call, the proper context is that - -- of the alternative. - - if Nkind (Parent (Curr)) = N_Entry_Call_Alternative - and then Nkind (Parent (Parent (Curr))) in - N_Conditional_Entry_Call | N_Timed_Entry_Call - then - return Parent (Parent (Curr)); - - -- General case for entry or procedure calls - - else - return Curr; - end if; - - when N_Pragma => - - -- Pragma Check is not a valid transient context in GNATprove - -- mode because the pragma must remain unchanged. - - if GNATprove_Mode - and then Get_Pragma_Id (Curr) = Pragma_Check - then - return Empty; - - -- General case for pragmas - - else - return Curr; - end if; - - when N_Raise_Statement => - return Curr; - - when N_Simple_Return_Statement => - - -- A return statement is not a valid transient context when the - -- function itself requires transient scope management because - -- the result will be reclaimed too early. - - if Requires_Transient_Scope (Etype - (Return_Applies_To (Return_Statement_Entity (Curr)))) - then - return Empty; - - -- General case for return statements - - else - return Curr; - end if; - - -- Special - - when N_Attribute_Reference => - if Is_Procedure_Attribute_Name (Attribute_Name (Curr)) then - return Curr; - end if; - - -- An Ada 2012 iterator specification is not a valid context - -- because Analyze_Iterator_Specification already employs special - -- processing for it. - - when N_Iterator_Specification => - return Empty; - - when N_Loop_Parameter_Specification => - - -- An iteration scheme is not a valid context because routine - -- Analyze_Iteration_Scheme already employs special processing. - - if Nkind (Parent (Curr)) = N_Iteration_Scheme then - return Empty; - else - return Parent (Curr); - end if; - - -- Termination - - -- The following nodes represent "dummy contexts" which do not - -- need to be wrapped. - - when N_Component_Declaration - | N_Discriminant_Specification - | N_Parameter_Specification - => - return Empty; - - -- If the traversal leaves a scope without having been able to - -- find a construct to wrap, something is going wrong, but this - -- can happen in error situations that are not detected yet (such - -- as a dynamic string in a pragma Export). - - when N_Block_Statement - | N_Entry_Body - | N_Package_Body - | N_Package_Declaration - | N_Protected_Body - | N_Subprogram_Body - | N_Task_Body - => - return Empty; - - -- Default - - when others => - null; - end case; - - Prev := Curr; - Curr := Parent (Curr); - end loop; - - return Empty; - end Find_Transient_Context; - - ---------------------------------- - -- Has_New_Controlled_Component -- - ---------------------------------- - - function Has_New_Controlled_Component (E : Entity_Id) return Boolean is - Comp : Entity_Id; - - begin - if not Is_Tagged_Type (E) then - return Has_Controlled_Component (E); - elsif not Is_Derived_Type (E) then - return Has_Controlled_Component (E); - end if; - - Comp := First_Component (E); - while Present (Comp) loop - if Chars (Comp) = Name_uParent then - null; - - elsif Scope (Original_Record_Component (Comp)) = E - and then Needs_Finalization (Etype (Comp)) - then - return True; - end if; - - Next_Component (Comp); - end loop; - - return False; - end Has_New_Controlled_Component; - --------------------------------- -- Has_Simple_Protected_Object -- --------------------------------- @@ -8064,7 +8126,7 @@ package body Exp_Ch7 is -- end if; -- ... - -- When Deep_Adjust is invokes for field _parent, a value of False is + -- When Deep_Adjust is invoked for field _parent, a value of False is -- provided for the flag: -- Deep_Adjust (Obj._parent, False); @@ -8219,7 +8281,7 @@ package body Exp_Ch7 is Loc : constant Source_Ptr := Sloc (Typ); Typ_Def : constant Node_Id := Type_Definition (Parent (Typ)); - Counter : Int := 0; + Counter : Nat := 0; Finalizer_Data : Finalization_Exception_Data; function Process_Component_List_For_Finalize @@ -9282,7 +9344,7 @@ package body Exp_Ch7 is Dope_Id : Entity_Id; begin - -- Ensure that Ptr_Typ a thin pointer, generate: + -- Ensure that Ptr_Typ is a thin pointer; generate: -- for Ptr_Typ'Size use System.Address'Size; Append_To (Decls, @@ -9824,15 +9886,6 @@ package body Exp_Ch7 is end Node_To_Be_Wrapped; ---------------------------- - -- Set_Node_To_Be_Wrapped -- - ---------------------------- - - procedure Set_Node_To_Be_Wrapped (N : Node_Id) is - begin - Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped := N; - end Set_Node_To_Be_Wrapped; - - ---------------------------- -- Store_Actions_In_Scope -- ---------------------------- @@ -9841,7 +9894,7 @@ package body Exp_Ch7 is Actions : List_Id renames SE.Actions_To_Be_Wrapped (AK); begin - if No (Actions) then + if Is_Empty_List (Actions) then Actions := L; if Is_List_Member (SE.Node_To_Be_Wrapped) then |