diff options
author | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-08-03 14:36:26 +0000 |
---|---|---|
committer | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-08-03 14:36:26 +0000 |
commit | bb3b440a7d0e1aceaae97e58c98cbc7657ee03d2 (patch) | |
tree | 3a155e8b2ced397467e576bd84bd23e0fd58fd91 /gcc/ada/exp_util.adb | |
parent | 1fbb8a39e0bdd453d365a90bf36e9f266c570921 (diff) | |
download | gcc-bb3b440a7d0e1aceaae97e58c98cbc7657ee03d2.tar.gz |
2011-08-03 Hristian Kirtchev <kirtchev@adacore.com>
* a-except.adb, a-except-2005.adb (Raise_From_Controlled_Operation):
Rewritten to create the message strings when the exception is not
raised by an abort during finalization.
* a-except.ads, a-except-2005.ads: Add pragma Export for procedure
Raise_From_Controlled_Operation and update its associated comment.
* a-fihema.ads, a-fihema.adb: New GNAT unit.
Ada.Finalization.Heap_Management provides key functionality
associated with controlled objects on the heap, their creation,
finalization and reclamation. Type Finalization_Collection is
effectively a wrapper which sits ontop of a storage pool and performs
all necessary bookkeeping for all the objects it contains. Each
access-to-controlled or access-to-class-wide type receives a collection
as part of its expansion. The compiler generates buffer code and
invokes Allocate / Deallocate to create and destroy allocated
controlled objects.
* a-finali.adb ("="): Removed.
* a-finali.ads ("="): Removed. Controlled types no longer carry hidden
fields Prev and Next.
* ali.adb (Scan_ALI): Add parsing code to process PF / Has_Finalizer.
A library unit with at least one controlled object on the library level
has a special finalizer which is invoked by the binder. To signal this,
ali files carry field PF.
* ali.ads: New field in type Unit_Record called Has_Finalizer. Add
associated comment on field usage.
* a-tags.adb (Get_RC_Offset): Removed.
(Needs_Finalization): New routine.
* a-tags.ads: Update the structure of the GNAT dispatch tables.
Dispatch tables now carry field Needs_Finalization which provides
runtime indication whether a type is controlled or has controlled
components or both. Remove field RC_Offset.
(Get_RC_Offset): Removed along with its associated pragma Export.
Since tagged types with controlled components no longer carry hidden
field _controller, the special mechanism to retrieve its location is no
longer needed.
(Needs_Finalization): New routine.
* atree.ads, atree.adb (Elist24): New routine.
(Set_Elist24): New routine.
* atree.h: Add a define clause for Elist24.
* bindgen.adb New library-level variable Lib_Final_Built.
(Gen_Adafinal_Ada): Reimplemented. Depending on the restrictions or the
presence of a VM target, the routine generates calls to the proper
library finalization routine.
(Gen_Adainit_Ada): Import Finalize_Library_Objects only on non-VM
targets. Set the correct library finalization routine depending on
whether the library has controlled objects or this is a VM compilation.
(Gen_Finalize_Library_Ada): New routine. This procedure generates calls
to library-level finalizers of compiled units in reverse order of
elaboration. It also produces exception management code and reraises a
potential exception after all units have been finalized.
(Gen_Finalize_Library_C): New routine. This procedure generates calls to
library-level finalizers of compiled units in reverse order of
elaboration.
(Gen_Finalize_Library_Defs_C): New routine. This procedure generates the
definitions of all library-level finalizers available to the compilation
(Gen_Main_Ada): Directly call Adafinal which now contails all target
dependent code.
(Gen_Main_C): Add new local constant Needs_Library_Finalization. Call
System.Standard_Library.Adafinal directly. If the library needs
finalization actions, create the sequence of finalization calls.
(Gen_Output_File_Ada): Alphabetize local variables and constants.
Generate a with clause for System.Soft_Links when compiling for a VM.
Remove the code which imports System.Standard_Library.Adafinal as
Do_Finalize. Generate the library finalization routine.
(Gen_Output_File_C): Add new local constant Needs_Library_Finalization.
If the library needs finalization actions, create all the definitions
of library- level finalizers.
(Has_Finalizer): New routine. Determines whether at least one compiled
unit has a library-level finalizer.
Add type Qualification_Mode.
(Set_Unit_Name): Add a formal which controls the replacement of a dot.
* einfo.adb: New usage of field 15 as Return_Flag.
Remove Finalization_Chain_Entity from the usages of field 19.
Remove Associated_Final_Chain from the usages of field 23.
New usage of field 23 as Associated_Collection.
New usage of field 24 as Finalizer.
New usage of flag 252 as Is_Processed_Transient.
(Associated_Final_Chain): Removed.
(Associated_Collection): New routine.
(Finalization_Chain_Entity): Removed.
(Finalizer): New routine.
(Is_Finalizer): New routine.
(Is_Processed_Transient): New routine.
(Return_Flag): New routine.
(Set_Associated_Final_Chain): Removed.
(Set_Associated_Collection): New routine.
(Set_Finalization_Chain_Entity): Removed.
(Set_Finalizer): New routine.
(Set_Is_Processed_Transient): New routine.
(Set_Return_Flag): New routine.
(Write_Entity_Flags): Include Is_Processed_Transient to the list of
displayed flags.
(Write_Field8_Name): Alphabetize the output.
(Write_Field11_Name): Alphabetize the output.
(Write_Field12_Name): Alphabetize the output.
(Write_Field13_Name): Alphabetize the output.
(Write_Field14_Name): Alphabetize the output.
(Write_Field15_Name): Alphabetize the output.
(Write_Field16_Name): Alphabetize the output.
(Write_Field17_Name): Alphabetize the output.
(Write_Field18_Name): Alphabetize the output.
(Write_Field19_Name): Alphabetize the output. Remove the output of
Finalization_Chain_Entity.
(Write_Field20_Name): Alphabetize the output.
(Write_Field21_Name): Alphabetize the output.
(Write_Field22_Name): Alphabetize the output.
(Write_Field23_Name): Alphabetize the output. Remove the output of
Associated_Final_Chain. Add output for Associated_Collection.
(Write_Field24_Name): Alphabetize the output.
(Write_Field25_Name): Add output for Finalizer.
(Write_Field26_Name): Alphabetize the output.
(Write_Field27_Name): Alphabetize the output.
(Write_Field28_Name): Alphabetize the output.
* einfo.ads: Add new field description for Associated_Collection and
its uses in nodes.
Remove Associated_Final_Chain and its uses in nodes.
Remove Finalization_Chain_Entity and its uses in nodes.
Add new field description for Finalizer and its uses in nodes.
Add new synthesized attribute Is_Finalizer.
Add new flag description for Is_Processed_Transient and its uses in
nodes.
Add new field description for Return_Flag and its uses in nodes.
(Associated_Final_Chain): Removed along with its pragma Inline.
(Associated_Collection): New routine and pragma Inline.
(Finalization_Chain_Entity): Removed along with its pragma Inline.
(Finalizer): New routine and pragma Inline.
(Is_Finalizer): New routine and pragma Inline.
(Is_Processed_Transient): New routine and pragma Inline.
(Return_Flag): New routine and pragma Inline.
(Set_Associated_Final_Chain): Removed along with its pragma Inline.
(Set_Associated_Collection): New routine and pragma Inline.
(Set_Finalization_Chain_Entity): Removed along with its pragma Inline.
(Set_Finalizer): New routine and pragma Inline.
(Set_Is_Processed_Transient): New routine and pragma Inline.
(Set_Return_Flag): New routine and pragma Inline.
* exp_aggr.adb: Alphabetize subprograms.
(Build_Array_Aggr_Code): Remove formal Flist and its associated comment.
(Build_Record_Aggr_Code): Remove formals Flist and Obj along with their
associated comments. Remove local variables External_Final_List and
Attach.
Rename Ctrl_Stuff_Done to Finalization_Done. Rename local variable A to
Ancestor. Remove the retrieval of finalization lists. Update the call to
Make_Adjust_Call.
(Convert_Aggr_In_Allocator): Remove the retrieval of finalization
lists. Update the call to Late_Expansion.
(Convert_Aggr_In_Assignment): Update the call to Late_Expansion.
(Convert_Aggr_In_Object_Decl): Update the call to Late_Expansion.
(Gen_Assign): Remove the retrieval of the finalization list used to
build the assignment. Update the calls to Make_Init_Call and
Make_Adjust_Call.
(Gen_Ctrl_Actions_For_Aggr): Renamed to Generate_Finalization_Actions.
Remove the mechanism to determine attachment levels and finalization
list retrieval. Remove the processing for coextensions.
(Init_Controller): Removed. Controllers no longer exist.
(Late_Expansion): Remove formals Flist and Obj along with their
associated comments. Update the calls to Build_Record_Aggr_Code and
Build_Array_Aggr_Code.
* exp_ch13.adb (Expand_N_Free_Statement): New routine.
(Expand_N_Freeze_Entity): Add special processing for finalizers which
appear in entry bodies, protected subprograms and task bodies.
* exp_ch13.ads (Expand_N_Free_Statement): New routine.
* exp_ch3.adb (Add_Final_Chain): Removed.
(Build_Array_Init_Proc): Alphabetize local variables.
(Build_Assignment): Alphabetize local variables. Update the call to
Maked_Adjust_Call.
(Build_Class_Wide_Master): Rename local variables to better reflect
their role.
(Build_Discriminant_Assignments): Code reformatting.
(Build_Init_Call_Thru): Code reformatting.
(Build_Init_Procedure): Code reformatting. Generate a special version
of Deep_Finalize which is capable of finalizing all initialized
components and ignore the rest.
(Build_Init_Statements): Rename local variables to better reflect their
role.
Reimplement the mechanism to include the creation and update of an index
variable called a "counter". It is used as a bookmark for tracing
initialized and non-initialized components.
(Build_Initialization_Call): Remove local variable Controller_Typ.
Alphabetize all local variables. Remove the initialization of the
record controller and update the call to Make_Init_Call.
(Build_Record_Init_Proc): Rename formal Pe to Rec_Ent.
New local variable Counter.
(Constrain_Array): Alphabetize.
(Expand_Freeze_Array_Type): Create a collection instead of a
finalization list.
(Expand_Freeze_Class_Wide_Type): New routine. Creates TSS primitive
Finalize_Address which is used in conjunction with allocated controlled
objects.
(Expand_N_Object_Declaration): Remove the creation of a finalization
list for anonymous access types. Update the calls to Make_Init_Call and
Make_Adjust_Call.
(Expand_Freeze_Record_Type): Remove local variable Flist. Remove the
retrieval of finalization lists. Remove the expansion of the record
controller. Create TSS primitive Finalize_Address used in conjunction
with controlled objects on the heap. Create finalization collections
for access-to-controlled record components.
(Expand_Record_Controller): Removed.
(Freeze_Type): Remove the freezing of record controllers. Freezing of
class-wide types now requires additional processing. Create
finalization collections for access-to-controlled types.
(Increment_Counter): New routine.
(Make_Counter): New routine.
(Make_Eq_If): Remove the mention of Name_uController.
(Make_Predefined_Primitive_Specs): There is no longer need to skip
types coming from System.Finalization_Root.
(Predef_Deep_Spec): Reimplemented to reflect the new parameter profiles.
(Predefined_Primitive_Bodies): There is no longer need to skip types
coming from System.Finalization_Root.
(Stream_Operation_OK): Do not generate stream routines for
type Ada.Finalization.Heap_Management.Finalization_Collection.
* exp_ch3.ads: Alphabetize subprograms.
* exp_ch4.adb: Remove with and use clause for Sem_Ch8.
Add with and use clause for Lib.
(Complete_Coextension_Finalization): Removed.
(Complete_Controlled_Allocation): New routine. Create a finalization
collection for anonymous access-to-controlled types. Create a custom
Allocate which interfaces with the back end and the machinery in
Heap_Management.
(Expand_Allocator_Expression): Add necessary calls to
Complete_Controlled_Allocation. Remove the retrieval of finalization
lists. Update the calls to Make_Adjust_Call. Generate a call to
Ada.Finalization.Heap_Management.Set_Finalize_Address_Ptr to decorate
the associated collection.
(Expand_N_Allocator): Remove the processing for dynamic coextensions.
Code clean up. Remove the retrieval of finalization lists and
attachment levels.
Update the call to Make_Init_Call. Generate a call to
Ada.Finalization.Heap_Management.Set_Finalize_Address_Ptr to decorate
the associated collection.
(Get_Allocator_Final_List): Removed. Finalization lists are not
available.
(Suitable_Element): Remove the mention of Name_uController.
* exp_ch5.adb: Remove with and use clauses for Ttypes and Uintp.
(Make_Tag_Ctrl_Assignment): Rewritten to simply do a finalization of
the left hand side, carry out the assignment and adjust the left hand
side.
* exp_ch6.adb (Add_Final_List_Actual_To_Build_In_Place_Call): Removed.
(Add_Collection_Actual_To_Build_In_Place_Call): New routine.
(BIP_Formal_Suffix): Rename BIP_Final_List and BIPfinallist to
BIP_Collection and BIPcollection.
(Build_Heap_Allocator): New routine used to allocate the return object
of a build-in-place function onto a collection.
(Expand_Ctrl_Function_Call): Moved from Exp_Ch7.
(Expand_Call): Do not replace direct calls to Deep routines with their
aliases.
(Expand_N_Extended_Return_Statement): Give all variables shorter names
and update their occurrences. Add a special return flag to monitor the
[ab]normal execution of the function. The flag is set right before the
return statement.
Rewrite the mechanism used to allocate a build-in-place return object
on the heap or on a storage pool.
(Is_Direct_Deep_Call): New routine.
(Make_Build_In_Place_Call_In_Allocator): Add a collection to a
build-in-place function call instead of a final list. Build a call to
Set_Finalize_Address_Ptr to decorate the associated collection.
(Make_Build_In_Place_Call_In_Anonymous_Context): Create a temporary in
order to name the build-in-place function call's result for later
finalization. Add a collection to a build-in-place function call
instead of a final list.
(Make_Build_In_Place_Call_In_Assignment): Add a collection to a
build-in-place function call instead of a final list. Remove the code
which moves one final list and transforms it into the actual in a
nested build-in-place call.
(Make_Build_In_Place_Call_In_Object_Declaration): Add a collection to a
build-in-place function call instead of a final list.
(Move_Final_List): Removed.
(Needs_BIP_Collection): New routine.
(Needs_BIP_Final_List): Removed.
* exp_ch6.ads: Replace BIP_Final_List with BIP_Collection in
enumeration type BIP_Formal_Kind.
Update the related comment.
(Needs_BIP_Collection): New routine.
(Needs_BIP_Final_List): Removed.
* exp_ch7.adb: Add with and use clauses for Elists, Exp_Ch6, Stringt
and Ttypes. Remove with and use clauses for Sem_Type. Alphabetize the
majority of subprograms in this unit. Add Name_Finalize_Address to
array Name_Of and TSS_Finalize_Address to array Deep_Name_Of.
(Build_Adjust_Or_Finalize_Statements): Create the adjust or finalization
statements for an array type.
(Build_Adjust_Statements): Create the adjust statements for a record
type.
(Build_Cleanup_Statements): New routine. A procedure which given any
construct containing asynchronous calls, references to _master, or is a
task body, a task allocation or a protected body produces the necessary
runtime calls to clean up these constructs.
(Build_Exception_Handler): New routine.
(Build_Final_List): Removed.
(Build_Finalization_Collection): New routine. A core procedure which
creates a collection to service heap allocated controlled objects
associated with an access-to-controlled type.
(Build_Finalize_Statements): Create the finalization statements for a
record types.
(Build_Finalizer): New routine. A core procedure which given any
construct with declarations and/or statements detects all objects which
need any type of clean up (controlled objects, protected objects) and
generates all necessary code to clean up the said objects in the proper
order.
(Build_Finalizer_Call): New routine.
(Build_Initialize_Statements): Create the initialization statements for
an array type. The generated routine contains code to finalize partially
initialized arrays.
(Build_Object_Declarations): New routine.
(Build_Raise_Statement): New routine.
(Clean_Simple_Protected_Objects): Removed.
(Controller_Component): Removed.
(Enclosing_Function): New routine.
(Expand_Cleanup_Actions): Create a finalizer for a construct which has
either declarations or statements or both.
(Expand_N_Package_Body): Create a finalizer for a non-generic package.
(Expand_N_Package_Declaration): Create a finalizer for a non-generic
package.
(Find_Final_List): Removed.
(Global_Flist_Ref): Removed.
(In_Finalization_Root): Removed.
(Insert_Actions_In_Scope_Around): Determine the range of the transient
scope in terms of tree nodes. Process all transient variables within
that range.
(Make_Adjust_Call): Rewritten. There is no longer an attach call
generated after the adjust.
(Make_Attach_Call): Removed.
(Make_Call): New routine.
(Make_Clean): Removed.
(Make_Deep_Array_Body): Rewritten to simply invoke the appropriate
build routines.
(Make_Deep_Proc): Rewritten to generate the new profile signature used
in Deep routines.
(Make_Deep_Record_Body): Rewritten to simply invoke the appropriate
build routines.
(Make_Final_Call): Modified to simply create a call to either
Deep_Finalize or Finalize.
(Make_Finalize_Address_Body): New routine.
(Make_Finalize_Address_Stmts): New routine. A function which produces
TSS primitive Finalize_Address used in conjunction with heap allocated
controlled objects.
(Make_Handler_For_Ctrl_Operation): Add specialized code for .NET/JVM.
(Make_Init_Call): Rewritten. There is no longer an attach call
generated after initialization.
(Make_Local_Deep_Finalize): New routine.
(Make_Set_Finalize_Address_Ptr_Call): New routine.
(Make_Transient_Block): Remove the finalization list retrieval and
manipulation.
(Needs_Finalization): Moved to Exp_Util.
(Parent_Field_Type): New routine.
(Preprocess_Components): New routine.
(Process_Transient_Objects): New routine.
(Wrap_HSS_In_Block): New routine.
(Wrap_Transient_Declaration): Remove finalization list management and
controller insertion.
(Wrap_Transient_Expression): Code reformatting.
(Wrap_Transient_Statement): Code reformatting.
* exp_ch7.ads (Build_Final_List): Removed.
(Build_Finalization_Collection): New routine.
(Build_Raise_Statement): New routine.
(Controller_Component): Removed.
(Expand_Ctrl_Function_Call): Moved to Exp_Ch6.
(Find_Final_List): Removed.
(In_Finalization_Root): Removed.
(Is_Simple_Protected_Type): Update related comment.
(Make_Adjust_Call): New parameter profile and associated comments.
(Make_Attach_Call): Removed.
(Make_Final_Call): New parameter profile and associated comments.
(Make_Finalize_Address_Body): New routine.
(Make_Init_Call): New parameter profile and associated comments.
(Make_Local_Deep_Finalize): New routine.
(Make_Set_Finalize_Address_Ptr_Call): New routine.
(Needs_Finalization): Moved to Exp_Util.
* exp_ch9.adb (Add_Object_Pointer): Code reformatting.
(Expand_N_Protected_Body): Remove the handling of finalization lists.
(Find_Protection_Type): Moved to Exp_Util.
* exp_disp.adb: Remove with and use clauses for Exp_Ch7.
(Make_DT): Update sequence of dispatch table initialization. Remove the
initialization of field RC_Offset. Add initialization of field Needs_
Finalization.
* exp_intr.adb (Expand_Unc_Deallocation): Code reformatting.
Reimplement how an object is first finalized, then deallocated.
* exp_strm.adb (Build_Record_Or_Elementary_Input_Function):
Code reformatting.
* exp_tss.ads: Add special suffix for TSS primitive Finalize_Address.
Register TSS_Finalize_Address with type TSS_Names.
* exp_util.adb (Build_Allocate_Deallocate_Proc): New routine. This core
procedure provides the interface between an allocation / deallocation
and the support machinery in Ada.Finalization.Heap_Management.
(Find_Init_Call): Code reformatting.
(Find_Init_Call_In_List): Code reformatting.
(Find_Protection_Type): Moved from Exp_Ch9.
(Find_Prim_Op): Reimplement to add preference of recovered primitive.
(Has_Controlled_Coextensions): Removed.
(Has_Controlled_Objects): New routine.
(In_Library_Level_Package_Body): New routine.
(Insert_Action_After): New routine.
(Is_Finalizable_Transient): New routine. This predicate determines
whether an object declaration is one of the many variants of controlled
transients.
(Is_Null_Access_BIP_Func_Call): New routine.
(Is_Non_BIP_Func_Call): New routine.
(Is_Related_To_Func_Return): New routine.
(Needs_Finalization): Moved from Exp_Ch7.
* exp_util.ads (Build_Allocate_Deallocate_Proc): New routine.
(Find_Protection_Type): Moved from Exp_Ch9.
(Has_Controlled_Coextensions): Removed.
(Has_Controlled_Objects): New routine.
(In_Library_Level_Package_Body): New routine.
(Insert_Action_After): New routine.
(Is_Finalizable_Transient): New routine.
(Is_Null_Access_BIP_Func_Call): New routine.
(Is_Non_BIP_Func_Call): New routine.
(Is_Related_To_Func_Return): New routine.
(Needs_Finalization): Moved from Exp_ch7.
* expander.adb (Expand): Add a case for N_Free_Statement.
* freeze.adb (Freeze_All): Replace the generation of a finalization
list with a collection for access-to-controlled types.
(Freeze_Entity): Code reformatting.
(Freeze_Record_Type): Remove the freezing of a record controller
component.
(Freeze_Subprogram): Code reformatting.
* inline.adb (Cleanup_Scopes): Remove the reset of the scope
finalization list.
* lib-writ.adb (Write_Unit_Information): Output "PF" when a package
has a library-level finalizer.
* lib-writ.ads: Add "PF" to the sequence of unit attributes.
* a-filico.ads, a-filico.adb, s-finimp.ads, s-finimp.adb: Removed.
* Makefile.rtl: Remove a-filico and s-finimp from the list of object
files. Add a-fihema to the list of object files.
* par-ch4.adb:
Alphabetize the associations in type Is_Parameterless_Attribute.
* rtsfind.ads: Ada.Finalization_List.Controller and
System.Finalization_Implementation are no longer a GNAT unit.
Update the range of type Ada_Finalization_Child. Remove the following
recoverable entities:
RE_Attach_To_Final_List
RE_Deep_Tag_Attach
RE_Finalize_List
RE_Finalize_One
RE_Finalizable_Ptr_Ptr
RE_Global_Final_List
RE_Limited_Record_Controller
RE_List_Controller
RE_Move_Final_List
RE_Record_Controller
RE_Simple_List_Controller
Add the following recoverable entities:
RE_Add_Offset_To_Address
RE_Allocate
RE_Base_Pool
RE_Deallocate
RE_Exception_Identity
RE_Finalization_Collection
RE_Finalization_Collection_Ptr
RE_Needs_Finalization
RE_Save_Library_Occurrence
RE_Set_Finalize_Address_Ptr
RE_Set_Storage_Pool_Ptr
RE_Storage_Count
* sem_aggr.adb (Resolve_Record_Aggregate): Remove mention of
Name_uController.
* sem_aux.adb (First_Discriminant): Remove mention of Name_uController.
(First_Stored_Discriminant): Remove the mention of Name_uController.
* sem_aux.ads: Comment reformatting.
* sem_ch10.adb (Build_Chain): Signal the class-wide creation machinery
to redecorate an already existing class-wide type.
(Decorate_Tagged_Type): New parameter profile and associated comment.
Create a "shadow class-wide type" for a shadow entity.
* sem_ch11.adb (Analyze_Exception_Handlers): Remove the dubious setting
of the final chain along with the associated comment.
* sem_ch3.adb (Access_Type_Declaration): Add new local variable
Full_Desig and set it to the full view of the designated type.
Initialize the finalization collection to empty.
(Build_Derived_Record_Type): Alphabetize local variables. Code
reformatting.
(Collect_Fixed_Components): Remove the mention of Name_uController.
(Create_Constrained_Components): Remove the mention of Name_uController.
(Make_Class_Wide_Type): Add specialized code to redecorate an existing
class-wide type of a shadow entity.
(Process_Full_View): Update the machinery which marks type
Limited_Controlled's entity as limited.
* sem_ch4.adb (Analyze_One_Call): Code reformatting.
* sem_ch6.adb (Create_Extra_Formals): Do not generate a finalization
list, instead make a collection build-in-place formal.
* sem_ch8.adb (Analyze_Object_Renaming): Look at the available view of
a designated type in order to establish a match between the renaming
and the renamed entity.
(Find_Selected_Component): Add guard to prevent spurious exceptions
from being raised on .NET/JVM.
* sem_disp.adb (Check_Dispatching_Operation): Include Finalize_Address
to the list of primitive that need special processing. Update arrays
C_Names and D_Names.
(Replace_Types): Handle class-wide types.
* sem_elab.adb (Check_A_Call): Since Deep_Initialize now has a
different parameter profile, look at the first formal.
* sem_prag.adb: Remove with and use clauses for Exp_Ch7. Add with and
use clauses for Exp_Util.
* sem_res.adb: Remove with and use clauses for Elists.
(Propagate_Coextensions): Removed.
(Resolve_Allocator): Do not propagate the list of coextensions from one
allocator to another.
* sem_util.adb (Build_Actual_Subtype_Of_Component): Rename variable
Deaccessed_T to Desig_Typ.
(Enter_Name): Remove the mention of Name_uController.
(Gather_Components): Remove the mention of Name_uController.
(Incomplete_Or_Private_View): New routine.
(Is_Coextension_Root): Removed.
(Is_Fully_Initialized_Type): Remove the mention of Name_uController.
* sem_util.ads (Incomplete_Or_Private_View): New routine.
(Is_Coextension_Root): Removed.
* s-finroo.ads: Remove with clause for Ada.Unchecked_Conversion.
Controlled types are now derived from a null tagged record. Remove
types Finalizable_Ptr, Finalizable and Empty_Root_Controlled.
* sinfo.adb (Coextensions): Removed.
(Set_Coextensions): Removed.
* sinfo.ads: Remove Coextensions from the explanation of node fields
and its uses in nodes.
Update the field usage of N_Allocator.
(Coextensions): Removed along with its pragma Inline.
(Set_Coextensions): Removed along with its pragma Inline.
* snames.ads-tmpl: Remove names
Name_uClean
Name_uController
Name_uFinal_List
Name_uLocal_Final_List
Name_Finalization_Root
Name_Next
Name_Prev
Add names
Name_uFinalizer
Name_Finalize_Address
* s-pooglo.adb (Allocate): Add overriding indicator.
(Deallocate): Add overriding indicator.
(Storage_Size): Add overriding indicator.
* s-soflin.adb (Adafinal_NT): Invoke Finalize_Library_Objects rather
than Finalize_Global_List.
(Null_Finalize_Global_List): Removed.
(Save_Library_Occurrence): New routine.
* s-soflin.ads: Remove variable Finalize_Global_List along with its
initialization. Add variable Finalize_Library_Objects along with its
pragma Export. Add variables Library_Exception and
Library_Exception_Set along with their pragma Export.
(Null_Finalize_Global_List): Removed.
(Save_Library_Occurrence): New routine.
* s-tassta.adb (Finalize_Global_Tasks): Call Finalize_Library_Objects
rather than Finalize_Global_List.
* tbuild.adb (Unchecked_Convert_To): Capture and set the parent field
of the constructed node.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@177275 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/exp_util.adb')
-rw-r--r-- | gcc/ada/exp_util.adb | 1117 |
1 files changed, 1079 insertions, 38 deletions
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb index 7557a125a2a..9388e664a0c 100644 --- a/gcc/ada/exp_util.adb +++ b/gcc/ada/exp_util.adb @@ -312,6 +312,320 @@ package body Exp_Util is end if; end Append_Freeze_Actions; + ------------------------------------ + -- Build_Allocate_Deallocate_Proc -- + ------------------------------------ + + procedure Build_Allocate_Deallocate_Proc + (N : Node_Id; + Is_Allocate : Boolean) + is + Expr : constant Node_Id := Expression (N); + Ptr_Typ : constant Entity_Id := Etype (Expr); + Desig_Typ : constant Entity_Id := + Available_View (Designated_Type (Ptr_Typ)); + + function Find_Object (E : Node_Id) return Node_Id; + -- Given an arbitrary expression of an allocator, try to find an object + -- reference in it, otherwise return the original expression. + + function Is_Allocate_Deallocate_Proc (Subp : Entity_Id) return Boolean; + -- Determine whether subprogram Subp denotes a custom allocate or + -- deallocate. + + ----------------- + -- Find_Object -- + ----------------- + + function Find_Object (E : Node_Id) return Node_Id is + Expr : Node_Id := E; + Change : Boolean := True; + + begin + pragma Assert (Is_Allocate); + + while Change loop + Change := False; + + if Nkind_In (Expr, N_Qualified_Expression, + N_Unchecked_Type_Conversion) + then + Expr := Expression (Expr); + Change := True; + + elsif Nkind (Expr) = N_Explicit_Dereference then + Expr := Prefix (Expr); + Change := True; + end if; + end loop; + + return Expr; + end Find_Object; + + --------------------------------- + -- Is_Allocate_Deallocate_Proc -- + --------------------------------- + + function Is_Allocate_Deallocate_Proc (Subp : Entity_Id) return Boolean is + begin + -- Look for a subprogram body with only one statement which is a + -- call to one of the Allocate / Deallocate routines in package + -- Ada.Finalization.Heap_Management. + + if Ekind (Subp) = E_Procedure + and then Nkind (Parent (Parent (Subp))) = N_Subprogram_Body + then + declare + HSS : constant Node_Id := + Handled_Statement_Sequence (Parent (Parent (Subp))); + Proc : Entity_Id; + + begin + if Present (Statements (HSS)) + and then Nkind (First (Statements (HSS))) = + N_Procedure_Call_Statement + then + Proc := Entity (Name (First (Statements (HSS)))); + + return + Is_RTE (Proc, RE_Allocate) + or else Is_RTE (Proc, RE_Deallocate); + end if; + end; + end if; + + return False; + end Is_Allocate_Deallocate_Proc; + + -- Start of processing for Build_Allocate_Deallocate_Proc + + begin + -- The allocation / deallocation of a non-controlled object does not + -- need the machinery created by this routine. + + if not Needs_Finalization (Desig_Typ) then + return; + + -- The allocator or free statmenet has already been expanded and already + -- has a custom Allocate / Deallocate routine. + + elsif Nkind (Expr) = N_Allocator + and then Present (Procedure_To_Call (Expr)) + and then Is_Allocate_Deallocate_Proc (Procedure_To_Call (Expr)) + then + return; + end if; + + declare + Loc : constant Source_Ptr := Sloc (N); + Addr_Id : constant Entity_Id := Make_Temporary (Loc, 'A'); + Alig_Id : constant Entity_Id := Make_Temporary (Loc, 'L'); + Proc_Id : constant Entity_Id := Make_Temporary (Loc, 'P'); + Size_Id : constant Entity_Id := Make_Temporary (Loc, 'S'); + + Actuals : List_Id; + Collect_Act : Node_Id; + Collect_Id : Entity_Id; + Collect_Typ : Entity_Id; + Proc_To_Call : Entity_Id; + + begin + -- When dealing with an access subtype, use the collection of the + -- base type. + + if Ekind (Ptr_Typ) = E_Access_Subtype then + Collect_Typ := Base_Type (Ptr_Typ); + else + Collect_Typ := Ptr_Typ; + end if; + + Collect_Id := Associated_Collection (Collect_Typ); + Collect_Act := New_Reference_To (Collect_Id, Loc); + + -- Handle the case where the collection is actually a pointer to a + -- collection. This case arises in build-in-place functions. + + if Is_Access_Type (Etype (Collect_Id)) then + Collect_Act := + Make_Explicit_Dereference (Loc, + Prefix => Collect_Act); + end if; + + -- Create the actuals for the call to Allocate / Deallocate + + Actuals := New_List ( + Collect_Act, + New_Reference_To (Addr_Id, Loc), + New_Reference_To (Size_Id, Loc), + New_Reference_To (Alig_Id, Loc)); + + -- Generate a run-time check to determine whether a class-wide object + -- is truly controlled. + + if Is_Class_Wide_Type (Desig_Typ) + or else Is_Generic_Actual_Type (Desig_Typ) + then + declare + Flag_Id : constant Entity_Id := Make_Temporary (Loc, 'F'); + Flag_Expr : Node_Id; + Param : Node_Id; + Temp : Node_Id; + + begin + if Is_Allocate then + Temp := Find_Object (Expression (Expr)); + else + Temp := Expr; + end if; + + -- Processing for generic actuals + + if Is_Generic_Actual_Type (Desig_Typ) then + Flag_Expr := + New_Reference_To (Boolean_Literals + (Needs_Finalization (Base_Type (Desig_Typ))), Loc); + + -- Processing for subtype indications + + elsif Nkind (Temp) in N_Has_Entity + and then Is_Type (Entity (Temp)) + then + Flag_Expr := + New_Reference_To (Boolean_Literals + (Needs_Finalization (Entity (Temp))), Loc); + + -- Generate a runtime check to test the controlled state of an + -- object for the purposes of allocation / deallocation. + + else + -- The following case arises when allocating through an + -- interface class-wide type, generate: + -- + -- Temp.all + + if Is_RTE (Etype (Temp), RE_Tag_Ptr) then + Param := + Make_Explicit_Dereference (Loc, + Prefix => + Relocate_Node (Temp)); + + -- Generate: + -- Temp'Tag + + else + Param := + Make_Attribute_Reference (Loc, + Prefix => + Relocate_Node (Temp), + Attribute_Name => Name_Tag); + end if; + + -- Generate: + -- Needs_Finalization (Param) + + Flag_Expr := + Make_Function_Call (Loc, + Name => + New_Reference_To (RTE (RE_Needs_Finalization), Loc), + Parameter_Associations => New_List (Param)); + end if; + + -- Create the temporary which represents the finalization state + -- of the expression. Generate: + -- + -- F : constant Boolean := <Flag_Expr>; + + Insert_Action (N, + Make_Object_Declaration (Loc, + Defining_Identifier => Flag_Id, + Constant_Present => True, + Object_Definition => + New_Reference_To (Standard_Boolean, Loc), + Expression => Flag_Expr)); + + -- The flag acts as the fifth actual + + Append_To (Actuals, New_Reference_To (Flag_Id, Loc)); + end; + end if; + + -- Select the proper routine to call + + if Is_Allocate then + Proc_To_Call := RTE (RE_Allocate); + else + Proc_To_Call := RTE (RE_Deallocate); + end if; + + -- Create a custom Allocate / Deallocate routine which has identical + -- profile to that of System.Storage_Pools. + + Insert_Action (N, + Make_Subprogram_Body (Loc, + Specification => + + -- procedure Pnn + + Make_Procedure_Specification (Loc, + Defining_Unit_Name => Proc_Id, + Parameter_Specifications => New_List ( + + -- P : Root_Storage_Pool + + Make_Parameter_Specification (Loc, + Defining_Identifier => + Make_Temporary (Loc, 'P'), + Parameter_Type => + New_Reference_To (RTE (RE_Root_Storage_Pool), Loc)), + + -- A : [out] Address + + Make_Parameter_Specification (Loc, + Defining_Identifier => Addr_Id, + Out_Present => Is_Allocate, + Parameter_Type => + New_Reference_To (RTE (RE_Address), Loc)), + + -- S : Storage_Count + + Make_Parameter_Specification (Loc, + Defining_Identifier => Size_Id, + Parameter_Type => + New_Reference_To (RTE (RE_Storage_Count), Loc)), + + -- L : Storage_Count + + Make_Parameter_Specification (Loc, + Defining_Identifier => Alig_Id, + Parameter_Type => + New_Reference_To (RTE (RE_Storage_Count), Loc)))), + + Declarations => No_List, + + Handled_Statement_Sequence => + Make_Handled_Sequence_Of_Statements (Loc, + Statements => New_List ( + + -- Allocate / Deallocate + -- (<Ptr_Typ collection>, A, S, L[, F]); + + Make_Procedure_Call_Statement (Loc, + Name => + New_Reference_To (Proc_To_Call, Loc), + Parameter_Associations => Actuals))))); + + -- The newly generated Allocate / Deallocate becomes the default + -- procedure to call when the back end processes the allocation / + -- deallocation. + + if Is_Allocate then + Set_Procedure_To_Call (Expr, Proc_Id); + else + Set_Procedure_To_Call (N, Proc_Id); + end if; + end; + end Build_Allocate_Deallocate_Proc; + ------------------------ -- Build_Runtime_Call -- ------------------------ @@ -1351,13 +1665,17 @@ package body Exp_Util is -- Renamings of class-wide interface types require no equivalent -- constrained type declarations because we only need to reference - -- the tag component associated with the interface. + -- the tag component associated with the interface. The same is + -- presumably true for class-wide types in general, so this test + -- is broadened to include all class-wide renamings, which also + -- avoids cases of unbounded recursion in Remove_Side_Effects. + -- (Is this really correct, or are there some cases of class-wide + -- renamings that require action in this procedure???) elsif Present (N) and then Nkind (N) = N_Object_Renaming_Declaration - and then Is_Interface (Unc_Type) + and then Is_Class_Wide_Type (Unc_Type) then - pragma Assert (Is_Class_Wide_Type (Unc_Type)); null; -- In Ada95 nothing to be done if the type of the expression is limited, @@ -1428,11 +1746,12 @@ package body Exp_Util is while Present (Init_Call) and then Init_Call /= Rep_Clause loop if Nkind (Init_Call) = N_Procedure_Call_Statement - and then Is_Entity_Name (Name (Init_Call)) - and then Entity (Name (Init_Call)) = Init_Proc + and then Is_Entity_Name (Name (Init_Call)) + and then Entity (Name (Init_Call)) = Init_Proc then return Init_Call; end if; + Next (Init_Call); end loop; @@ -1461,8 +1780,8 @@ package body Exp_Util is -- applying to Var). if No (Init_Call) and then Present (Freeze_Node (Var)) then - Init_Call := Find_Init_Call_In_List - (First (Actions (Freeze_Node (Var)))); + Init_Call := + Find_Init_Call_In_List (First (Actions (Freeze_Node (Var)))); end if; return Init_Call; @@ -1701,8 +2020,11 @@ package body Exp_Util is (T : Entity_Id; Name : TSS_Name_Type) return Entity_Id is - Prim : Elmt_Id; - Typ : Entity_Id := T; + Inher_Op : Entity_Id := Empty; + Own_Op : Entity_Id := Empty; + Prim_Elmt : Elmt_Id; + Prim_Id : Entity_Id; + Typ : Entity_Id := T; begin if Is_Class_Wide_Type (Typ) then @@ -1711,18 +2033,31 @@ package body Exp_Util is Typ := Underlying_Type (Typ); - Prim := First_Elmt (Primitive_Operations (Typ)); - while not Is_TSS (Node (Prim), Name) loop - Next_Elmt (Prim); + -- This search is based on the assertion that the dispatching version + -- of the TSS routine always precedes the real primitive. - -- Raise program error if no primitive found + Prim_Elmt := First_Elmt (Primitive_Operations (Typ)); + while Present (Prim_Elmt) loop + Prim_Id := Node (Prim_Elmt); - if No (Prim) then - raise Program_Error; + if Is_TSS (Prim_Id, Name) then + if Present (Alias (Prim_Id)) then + Inher_Op := Prim_Id; + else + Own_Op := Prim_Id; + end if; end if; + + Next_Elmt (Prim_Elmt); end loop; - return Node (Prim); + if Present (Own_Op) then + return Own_Op; + elsif Present (Inher_Op) then + return Inher_Op; + else + raise Program_Error; + end if; end Find_Prim_Op; ---------------------------- @@ -1753,6 +2088,34 @@ package body Exp_Util is raise Program_Error; end Find_Protection_Object; + -------------------------- + -- Find_Protection_Type -- + -------------------------- + + function Find_Protection_Type (Conc_Typ : Entity_Id) return Entity_Id is + Comp : Entity_Id; + Typ : Entity_Id := Conc_Typ; + + begin + if Is_Concurrent_Type (Typ) then + Typ := Corresponding_Record_Type (Typ); + end if; + + Comp := First_Component (Typ); + while Present (Comp) loop + if Chars (Comp) = Name_uObject then + return Base_Type (Etype (Comp)); + end if; + + Next_Component (Comp); + end loop; + + -- The corresponding record of a protected type should always have an + -- _object field. + + raise Program_Error; + end Find_Protection_Type; + ---------------------- -- Force_Evaluation -- ---------------------- @@ -2190,45 +2553,254 @@ package body Exp_Util is end if; end Get_Stream_Size; - --------------------------------- - -- Has_Controlled_Coextensions -- - --------------------------------- + --------------------------- + -- Has_Access_Constraint -- + --------------------------- - function Has_Controlled_Coextensions (Typ : Entity_Id) return Boolean is - D_Typ : Entity_Id; - Discr : Entity_Id; + function Has_Access_Constraint (E : Entity_Id) return Boolean is + Disc : Entity_Id; + T : constant Entity_Id := Etype (E); begin - -- Only consider record types + if Has_Per_Object_Constraint (E) + and then Has_Discriminants (T) + then + Disc := First_Discriminant (T); + while Present (Disc) loop + if Is_Access_Type (Etype (Disc)) then + return True; + end if; + + Next_Discriminant (Disc); + end loop; - if not Ekind_In (Typ, E_Record_Type, E_Record_Subtype) then + return False; + else return False; end if; + end Has_Access_Constraint; + + ---------------------------- + -- Has_Controlled_Objects -- + ---------------------------- - if Has_Discriminants (Typ) then - Discr := First_Discriminant (Typ); - while Present (Discr) loop - D_Typ := Etype (Discr); + function Has_Controlled_Objects (N : Node_Id) return Boolean is + For_Pkg : constant Boolean := + Nkind_In (N, N_Package_Body, N_Package_Specification); - if Ekind (D_Typ) = E_Anonymous_Access_Type + begin + case Nkind (N) is + when N_Accept_Statement | + N_Block_Statement | + N_Entry_Body | + N_Package_Body | + N_Protected_Body | + N_Subprogram_Body | + N_Task_Body => + return Has_Controlled_Objects (Declarations (N), For_Pkg) + or else + + -- An expanded sequence of statements may introduce + -- controlled objects. + + (Present (Handled_Statement_Sequence (N)) + and then + Has_Controlled_Objects + (Statements (Handled_Statement_Sequence (N)), For_Pkg)); + + when N_Package_Specification => + return Has_Controlled_Objects (Visible_Declarations (N), For_Pkg) + or else + Has_Controlled_Objects (Private_Declarations (N), For_Pkg); + + when others => + return False; + end case; + end Has_Controlled_Objects; + + ---------------------------- + -- Has_Controlled_Objects -- + ---------------------------- + + function Has_Controlled_Objects + (L : List_Id; + For_Package : Boolean) return Boolean + is + Decl : Node_Id; + Expr : Node_Id; + Obj_Id : Entity_Id; + Obj_Typ : Entity_Id; + Pack_Id : Entity_Id; + Typ : Entity_Id; + + begin + if No (L) + or else Is_Empty_List (L) + then + return False; + end if; + + Decl := First (L); + while Present (Decl) loop + + -- Regular object declarations + + if Nkind (Decl) = N_Object_Declaration then + Obj_Id := Defining_Identifier (Decl); + Obj_Typ := Base_Type (Etype (Obj_Id)); + Expr := Expression (Decl); + + -- Bypass any form of processing for objects which have their + -- finalization disabled. This applies only to objects at the + -- library level. + + if For_Package + and then Finalize_Storage_Only (Obj_Typ) + then + null; + + -- Transient variables are treated separately in order to minimize + -- the size of the generated code. See Exp_Ch7.Process_Transient_ + -- Objects. + + elsif Is_Processed_Transient (Obj_Id) then + null; + + -- The object is of the form: + -- Obj : Typ [:= Expr]; + -- + -- Do not process the incomplete view of a deferred constant + + elsif not Is_Imported (Obj_Id) + and then Needs_Finalization (Obj_Typ) + and then not (Ekind (Obj_Id) = E_Constant + and then not Has_Completion (Obj_Id)) + then + return True; + + -- The object is of the form: + -- Obj : Access_Typ := Non_BIP_Function_Call'reference; + -- + -- Obj : Access_Typ := + -- BIP_Function_Call + -- (..., BIPaccess => null, ...)'reference; + + elsif Is_Access_Type (Obj_Typ) + and then Needs_Finalization + (Available_View (Designated_Type (Obj_Typ))) + and then Present (Expr) and then - (Is_Controlled (Designated_Type (D_Typ)) + (Is_Null_Access_BIP_Func_Call (Expr) or else - Is_Concurrent_Type (Designated_Type (D_Typ))) + (Is_Non_BIP_Func_Call (Expr) + and then not Is_Related_To_Func_Return (Obj_Id))) + then + return True; + + -- Simple protected objects which use type System.Tasking. + -- Protected_Objects.Protection to manage their locks should be + -- treated as controlled since they require manual cleanup. + + elsif Ekind (Obj_Id) = E_Variable + and then + (Is_Simple_Protected_Type (Obj_Typ) + or else Has_Simple_Protected_Object (Obj_Typ)) then return True; end if; - Next_Discriminant (Discr); - end loop; - end if; + -- Specific cases of object renamings + + elsif Nkind (Decl) = N_Object_Renaming_Declaration + and then Nkind (Name (Decl)) = N_Explicit_Dereference + and then Nkind (Prefix (Name (Decl))) = N_Identifier + then + Obj_Id := Defining_Identifier (Decl); + Obj_Typ := Base_Type (Etype (Obj_Id)); + + -- Bypass any form of processing for objects which have their + -- finalization disabled. This applies only to objects at the + -- library level. + + if For_Package + and then Finalize_Storage_Only (Obj_Typ) + then + null; + + -- Return object of a build-in-place function. This case is + -- recognized and marked by the expansion of an extended return + -- statement (see Expand_N_Extended_Return_Statement). + + elsif Needs_Finalization (Obj_Typ) + and then Is_Return_Object (Obj_Id) + and then Present (Return_Flag (Obj_Id)) + then + return True; + end if; + + -- Inspect the freeze node of an access-to-controlled type and + -- look for a delayed finalization collection. This case arises + -- when the freeze actions are inserted at a later time than the + -- expansion of the context. Since Build_Finalizer is never called + -- on a single construct twice, the collection will be ultimately + -- left out and never finalized. This is also needed for freeze + -- actions of designated types themselves, since in some cases the + -- finalization collection is associated with a designated type's + -- freeze node rather than that of the access type (see handling + -- for freeze actions in Build_Finalization_Collection). + + elsif Nkind (Decl) = N_Freeze_Entity + and then Present (Actions (Decl)) + then + Typ := Entity (Decl); + + if (Is_Access_Type (Typ) + and then not Is_Access_Subprogram_Type (Typ) + and then Needs_Finalization + (Available_View (Designated_Type (Typ)))) + or else + (Is_Type (Typ) + and then Needs_Finalization (Typ)) + then + return True; + end if; + + -- Nested package declarations + + elsif Nkind (Decl) = N_Package_Declaration then + Pack_Id := Defining_Unit_Name (Specification (Decl)); + + if Nkind (Pack_Id) = N_Defining_Program_Unit_Name then + Pack_Id := Defining_Identifier (Pack_Id); + end if; + + if Ekind (Pack_Id) /= E_Generic_Package + and then Has_Controlled_Objects (Specification (Decl)) + then + return True; + end if; + + -- Nested package bodies + + elsif Nkind (Decl) = N_Package_Body then + Pack_Id := Corresponding_Spec (Decl); + + if Ekind (Pack_Id) /= E_Generic_Package + and then Has_Controlled_Objects (Decl) + then + return True; + end if; + end if; + + Next (Decl); + end loop; return False; - end Has_Controlled_Coextensions; + end Has_Controlled_Objects; - ------------------------ - -- Has_Address_Clause -- - ------------------------ + ---------------------------------- + -- Has_Following_Address_Clause -- + ---------------------------------- -- Should this function check the private part in a package ??? @@ -2279,6 +2851,27 @@ package body Exp_Util is return Count; end Homonym_Number; + ----------------------------------- + -- In_Library_Level_Package_Body -- + ----------------------------------- + + function In_Library_Level_Package_Body (Id : Entity_Id) return Boolean is + begin + -- First determine whether the entity appears at the library level, then + -- look at the containing unit. + + if Is_Library_Level_Entity (Id) then + declare + Container : constant Node_Id := Cunit (Get_Source_Unit (Id)); + + begin + return Nkind (Unit (Container)) = N_Package_Body; + end; + end if; + + return False; + end In_Library_Level_Package_Body; + ------------------------------ -- In_Unconditional_Context -- ------------------------------ @@ -2330,6 +2923,18 @@ package body Exp_Util is Insert_Actions (Assoc_Node, New_List (Ins_Action), Suppress); end Insert_Action; + ------------------------- + -- Insert_Action_After -- + ------------------------- + + procedure Insert_Action_After + (Assoc_Node : Node_Id; + Ins_Action : Node_Id) + is + begin + Insert_Actions_After (Assoc_Node, New_List (Ins_Action)); + end Insert_Action_After; + -------------------- -- Insert_Actions -- -------------------- @@ -3098,6 +3703,277 @@ package body Exp_Util is return True; end Is_All_Null_Statements; + ------------------------------ + -- Is_Finalizable_Transient -- + ------------------------------ + + function Is_Finalizable_Transient + (Decl : Node_Id; + Rel_Node : Node_Id) return Boolean + is + Obj_Id : constant Entity_Id := Defining_Identifier (Decl); + Obj_Typ : constant Entity_Id := Base_Type (Etype (Obj_Id)); + Desig : Entity_Id := Obj_Typ; + Has_Rens : Boolean := True; + Ren_Obj : Entity_Id; + + function Initialized_By_Access (Trans_Id : Entity_Id) return Boolean; + -- Determine whether transient object Trans_Id is initialized either + -- by a function call which returns an access type or simply renames + -- another pointer. + + function Initialized_By_Aliased_BIP_Func_Call + (Trans_Id : Entity_Id) return Boolean; + -- Determine whether transient object Trans_Id is initialized by a + -- build-in-place function call where the BIPalloc parameter is of + -- value 1 and BIPaccess is not null. This case creates an aliasing + -- between the returned value and the value denoted by BIPaccess. + + function Is_Allocated (Trans_Id : Entity_Id) return Boolean; + -- Determine whether transient object Trans_Id is allocated on the heap + + function Is_Renamed + (Trans_Id : Entity_Id; + First_Stmt : Node_Id) return Boolean; + -- Determine whether transient object Trans_Id has been renamed in the + -- statement list starting from First_Stmt. + + --------------------------- + -- Initialized_By_Access -- + --------------------------- + + function Initialized_By_Access (Trans_Id : Entity_Id) return Boolean is + Expr : constant Node_Id := Expression (Parent (Trans_Id)); + + begin + return + Present (Expr) + and then Nkind (Expr) /= N_Reference + and then Is_Access_Type (Etype (Expr)); + end Initialized_By_Access; + + ------------------------------------------ + -- Initialized_By_Aliased_BIP_Func_Call -- + ------------------------------------------ + + function Initialized_By_Aliased_BIP_Func_Call + (Trans_Id : Entity_Id) return Boolean + is + Call : Node_Id := Expression (Parent (Trans_Id)); + + begin + -- Build-in-place calls usually appear in 'reference format + + if Nkind (Call) = N_Reference then + Call := Prefix (Call); + end if; + + if Is_Build_In_Place_Function_Call (Call) then + declare + Access_Nam : Name_Id := No_Name; + Access_OK : Boolean := False; + Actual : Node_Id; + Alloc_Nam : Name_Id := No_Name; + Alloc_OK : Boolean := False; + Formal : Node_Id; + Func_Id : Entity_Id; + Param : Node_Id; + + begin + -- Examine all parameter associations of the function call + + Param := First (Parameter_Associations (Call)); + while Present (Param) loop + if Nkind (Param) = N_Parameter_Association + and then Nkind (Selector_Name (Param)) = N_Identifier + then + Actual := Explicit_Actual_Parameter (Param); + Formal := Selector_Name (Param); + + -- Construct the names of formals BIPaccess and BIPalloc + -- using the function name retrieved from an arbitrary + -- formal. + + if Access_Nam = No_Name + and then Alloc_Nam = No_Name + and then Present (Entity (Formal)) + then + Func_Id := Scope (Entity (Formal)); + + Access_Nam := + New_External_Name (Chars (Func_Id), + BIP_Formal_Suffix (BIP_Object_Access)); + + Alloc_Nam := + New_External_Name (Chars (Func_Id), + BIP_Formal_Suffix (BIP_Alloc_Form)); + end if; + + -- A match for BIPaccess => Temp has been found + + if Chars (Formal) = Access_Nam + and then Nkind (Actual) /= N_Null + then + Access_OK := True; + end if; + + -- A match for BIPalloc => 1 has been found + + if Chars (Formal) = Alloc_Nam + and then Nkind (Actual) = N_Integer_Literal + and then Intval (Actual) = Uint_1 + then + Alloc_OK := True; + end if; + end if; + + Next (Param); + end loop; + + return Access_OK and then Alloc_OK; + end; + end if; + + return False; + end Initialized_By_Aliased_BIP_Func_Call; + + ------------------ + -- Is_Allocated -- + ------------------ + + function Is_Allocated (Trans_Id : Entity_Id) return Boolean is + Expr : constant Node_Id := Expression (Parent (Trans_Id)); + + begin + return + Is_Access_Type (Etype (Trans_Id)) + and then Present (Expr) + and then Nkind (Expr) = N_Allocator; + end Is_Allocated; + + ---------------- + -- Is_Renamed -- + ---------------- + + function Is_Renamed + (Trans_Id : Entity_Id; + First_Stmt : Node_Id) return Boolean + is + Stmt : Node_Id; + + function Extract_Renamed_Object + (Ren_Decl : Node_Id) return Entity_Id; + -- Given an object renaming declaration, retrieve the entity of the + -- renamed name. Return Empty if the renamed name is anything other + -- than a variable or a constant. + + ---------------------------- + -- Extract_Renamed_Object -- + ---------------------------- + + function Extract_Renamed_Object + (Ren_Decl : Node_Id) return Entity_Id + is + Change : Boolean; + Ren_Obj : Node_Id; + + begin + Change := True; + Ren_Obj := Renamed_Object (Defining_Identifier (Ren_Decl)); + + while Change loop + Change := False; + + if Nkind_In (Ren_Obj, N_Explicit_Dereference, + N_Indexed_Component, + N_Selected_Component) + then + Ren_Obj := Prefix (Ren_Obj); + Change := True; + end if; + end loop; + + if Nkind (Ren_Obj) in N_Has_Entity then + return Entity (Ren_Obj); + end if; + + return Empty; + end Extract_Renamed_Object; + + -- Start of processing for Is_Renamed + + begin + -- If a previous invocation of this routine has determined that a + -- list has no renamings, there is no point in repeating the same + -- scan. + + if not Has_Rens then + return False; + end if; + + -- Assume that the statement list does not have a renaming. This is a + -- minor optimization. + + Has_Rens := False; + + Stmt := First_Stmt; + while Present (Stmt) loop + if Nkind (Stmt) = N_Object_Renaming_Declaration then + Has_Rens := True; + Ren_Obj := Extract_Renamed_Object (Stmt); + + if Present (Ren_Obj) + and then Ren_Obj = Trans_Id + then + return True; + end if; + end if; + + Next (Stmt); + end loop; + + return False; + end Is_Renamed; + + -- Start of processing for Is_Finalizable_Transient + + begin + -- Handle access types + + if Is_Access_Type (Desig) then + Desig := Available_View (Designated_Type (Desig)); + end if; + + return + Ekind_In (Obj_Id, E_Constant, E_Variable) + and then Needs_Finalization (Desig) + and then Requires_Transient_Scope (Desig) + and then Nkind (Rel_Node) /= N_Simple_Return_Statement + + -- Do not consider transient objects allocated on the heap since they + -- are attached to a finalization collection. + + and then not Is_Allocated (Obj_Id) + + -- Do not consider renamed transient objects because the act of + -- renaming extends the object's lifetime. + + and then not Is_Renamed (Obj_Id, Decl) + + -- If the transient object is a pointer, check that it is not + -- initialized by a function which returns a pointer or acts as a + -- renaming of another pointer. + + and then + (not Is_Access_Type (Obj_Typ) + or else not Initialized_By_Access (Obj_Id)) + + -- Do not consider transient objects which act as indirect aliases of + -- build-in-place function results. + + and then not Initialized_By_Aliased_BIP_Func_Call (Obj_Id); + end Is_Finalizable_Transient; + --------------------------------- -- Is_Fully_Repped_Tagged_Type -- --------------------------------- @@ -3146,6 +4022,90 @@ package body Exp_Util is end Is_Library_Level_Tagged_Type; ---------------------------------- + -- Is_Null_Access_BIP_Func_Call -- + ---------------------------------- + + function Is_Null_Access_BIP_Func_Call (Expr : Node_Id) return Boolean is + Call : Node_Id := Expr; + + begin + -- Build-in-place calls usually appear in 'reference format + + if Nkind (Call) = N_Reference then + Call := Prefix (Call); + end if; + + if Nkind_In (Call, N_Qualified_Expression, + N_Unchecked_Type_Conversion) + then + Call := Expression (Call); + end if; + + if Is_Build_In_Place_Function_Call (Call) then + declare + Access_Nam : Name_Id := No_Name; + Actual : Node_Id; + Param : Node_Id; + Formal : Node_Id; + + begin + -- Examine all parameter associations of the function call + + Param := First (Parameter_Associations (Call)); + while Present (Param) loop + if Nkind (Param) = N_Parameter_Association + and then Nkind (Selector_Name (Param)) = N_Identifier + then + Formal := Selector_Name (Param); + Actual := Explicit_Actual_Parameter (Param); + + -- Construct the name of formal BIPaccess. It is much easier + -- to extract the name of the function using an arbitrary + -- formal's scope rather than the Name field of Call. + + if Access_Nam = No_Name + and then Present (Entity (Formal)) + then + Access_Nam := + New_External_Name + (Chars (Scope (Entity (Formal))), + BIP_Formal_Suffix (BIP_Object_Access)); + end if; + + -- A match for BIPaccess => null has been found + + if Chars (Formal) = Access_Nam + and then Nkind (Actual) = N_Null + then + return True; + end if; + end if; + + Next (Param); + end loop; + end; + end if; + + return False; + end Is_Null_Access_BIP_Func_Call; + + -------------------------- + -- Is_Non_BIP_Func_Call -- + -------------------------- + + function Is_Non_BIP_Func_Call (Expr : Node_Id) return Boolean is + begin + -- The expected call is of the format + -- + -- Func_Call'reference + + return + Nkind (Expr) = N_Reference + and then Nkind (Prefix (Expr)) = N_Function_Call + and then not Is_Build_In_Place_Function_Call (Prefix (Expr)); + end Is_Non_BIP_Func_Call; + + ---------------------------------- -- Is_Possibly_Unaligned_Object -- ---------------------------------- @@ -3427,6 +4387,20 @@ package body Exp_Util is end; end Is_Possibly_Unaligned_Slice; + ------------------------------- + -- Is_Related_To_Func_Return -- + ------------------------------- + + function Is_Related_To_Func_Return (Id : Entity_Id) return Boolean is + Expr : constant Node_Id := Related_Expression (Id); + + begin + return + Present (Expr) + and then Nkind (Expr) = N_Explicit_Dereference + and then Nkind (Parent (Expr)) = N_Simple_Return_Statement; + end Is_Related_To_Func_Return; + -------------------------------- -- Is_Ref_To_Bit_Packed_Array -- -------------------------------- @@ -4341,6 +5315,73 @@ package body Exp_Util is end if; end May_Generate_Large_Temp; + ------------------------ + -- Needs_Finalization -- + ------------------------ + + function Needs_Finalization (T : Entity_Id) return Boolean is + function Has_Some_Controlled_Component (Rec : Entity_Id) return Boolean; + -- If type is not frozen yet, check explicitly among its components, + -- because the Has_Controlled_Component flag is not necessarily set. + + ----------------------------------- + -- Has_Some_Controlled_Component -- + ----------------------------------- + + function Has_Some_Controlled_Component + (Rec : Entity_Id) return Boolean + is + Comp : Entity_Id; + + begin + if Has_Controlled_Component (Rec) then + return True; + + elsif not Is_Frozen (Rec) then + if Is_Record_Type (Rec) then + Comp := First_Entity (Rec); + + while Present (Comp) loop + if not Is_Type (Comp) + and then Needs_Finalization (Etype (Comp)) + then + return True; + end if; + + Next_Entity (Comp); + end loop; + + return False; + + elsif Is_Array_Type (Rec) then + return Needs_Finalization (Component_Type (Rec)); + + else + return Has_Controlled_Component (Rec); + end if; + else + return False; + end if; + end Has_Some_Controlled_Component; + + -- Start of processing for Needs_Finalization + + begin + -- Class-wide types must be treated as controlled because they may + -- contain an extension that has controlled components + + -- We can skip this if finalization is not available + + return (Is_Class_Wide_Type (T) + and then not Restriction_Active (No_Finalization)) + or else Is_Controlled (T) + or else Has_Controlled_Component (T) + or else Has_Some_Controlled_Component (T) + or else (Is_Concurrent_Type (T) + and then Present (Corresponding_Record_Type (T)) + and then Needs_Finalization (Corresponding_Record_Type (T))); + end Needs_Finalization; + ---------------------------- -- Needs_Constant_Address -- ---------------------------- |