aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ada/doc/gnat_rm/gnat_language_extensions.rst3
-rw-r--r--gcc/ada/einfo.ads18
-rw-r--r--gcc/ada/exp_ch4.adb6
-rw-r--r--gcc/ada/exp_ch5.adb39
-rw-r--r--gcc/ada/exp_ch7.adb260
-rw-r--r--gcc/ada/exp_ch7.ads5
-rw-r--r--gcc/ada/gnat_rm.texi5
-rw-r--r--gcc/ada/gnat_ugn.texi4
-rw-r--r--gcc/ada/libgnat/s-finpri.adb24
-rw-r--r--gcc/ada/libgnat/s-finpri.ads14
-rw-r--r--gcc/ada/sem_ch6.adb4
11 files changed, 287 insertions, 95 deletions
diff --git a/gcc/ada/doc/gnat_rm/gnat_language_extensions.rst b/gcc/ada/doc/gnat_rm/gnat_language_extensions.rst
index fc3ca5f..feceff2 100644
--- a/gcc/ada/doc/gnat_rm/gnat_language_extensions.rst
+++ b/gcc/ada/doc/gnat_rm/gnat_language_extensions.rst
@@ -590,8 +590,7 @@ Example:
procedure Finalize (Obj : in out Ctrl);
procedure Initialize (Obj : in out Ctrl);
-As of this writing, the relaxed semantics for finalization operations are
-only implemented for dynamically allocated objects.
+As of this writing, the RFC is implemented except for the `No_Raise` aspect.
Link to the original RFC:
https://github.com/AdaCore/ada-spark-rfcs/blob/topic/finalization-rehaul/considered/rfc-generalized-finalization.md
diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index 0d839b9..e51ab69 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -2026,8 +2026,22 @@ package Einfo is
-- checks for infinite recursion.
-- Has_Relaxed_Finalization [base type only]
--- Defined in all type entities. Indicates that the type is subject to
--- relaxed semantics for the finalization operations.
+-- Defined in all type entities. Set only for controlled types and types
+-- with controlled components. Indicates that the type is subject to the
+-- relaxed semantics for the finalization operations. These semantics are
+-- made up of two independent parts:
+--
+-- 1. The compiler is permitted to perform no automatic finalization of
+-- heap-allocated objects: Finalize is only called when the object is
+-- explicitly deallocated, or when the object is assigned a new value.
+-- As a consequence, no finalization collection is created for access
+-- types designating the type, and no header is allocated in front of
+-- heap-allocated objects of the type.
+--
+-- 2. If an exception is raised out of the Adjust or Finalize procedures,
+-- the compiler is permitted to enforce none of the guarantees given
+-- by the RM 7.6.1(14/1) and following subclauses, and to instead just
+-- let the exception be propagated upward.
-- Has_Shift_Operator [base type only]
-- Defined in integer types. Set in the base type of an integer type for
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index 50c3cd4..371cb11 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -14363,11 +14363,7 @@ package body Exp_Ch4 is
pragma Assert (Present (Fin_Context));
Insert_Action_After (Fin_Context,
- Make_Procedure_Call_Statement (Loc,
- Name =>
- New_Occurrence_Of (RTE (RE_Finalize_Object), Loc),
- Parameter_Associations => New_List (
- New_Occurrence_Of (Master_Node_Id, Loc))));
+ Make_Finalize_Call_For_Node (Loc, Master_Node_Id));
end if;
-- Mark the transient object to avoid double finalization
diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb
index 35c2628..7ff54cb 100644
--- a/gcc/ada/exp_ch5.adb
+++ b/gcc/ada/exp_ch5.adb
@@ -3203,14 +3203,12 @@ package body Exp_Ch5 is
end if;
-- We need to set up an exception handler for implementing
- -- 7.6.1(18). The remaining adjustments are tackled by the
- -- implementation of adjust for record_controllers (see
- -- s-finimp.adb).
-
- -- This is skipped if we have no finalization
+ -- 7.6.1(18), but this is skipped if the type has relaxed
+ -- semantics for finalization.
if Expand_Ctrl_Actions
and then not Restriction_Active (No_Finalization)
+ and then not Has_Relaxed_Finalization (Typ)
then
L := New_List (
Make_Block_Statement (Loc,
@@ -3245,29 +3243,32 @@ package body Exp_Ch5 is
and then Abort_Allowed
then
declare
- Blk : constant Entity_Id :=
- New_Internal_Entity
- (E_Block, Current_Scope, Sloc (N), 'B');
AUD : constant Entity_Id := RTE (RE_Abort_Undefer_Direct);
+ HSS : constant Node_Id := Handled_Statement_Sequence (N);
+
+ Blk_Id : Entity_Id;
begin
Set_Is_Abort_Block (N);
-
- Set_Scope (Blk, Current_Scope);
- Set_Etype (Blk, Standard_Void_Type);
- Set_Identifier (N, New_Occurrence_Of (Blk, Sloc (N)));
+ Add_Block_Identifier (N, Blk_Id);
Prepend_To (L, Build_Runtime_Call (Loc, RE_Abort_Defer));
- Set_At_End_Proc (Handled_Statement_Sequence (N),
- New_Occurrence_Of (AUD, Loc));
- -- Present the Abort_Undefer_Direct function to the backend
- -- so that it can inline the call to the function.
+ -- Like above, no need to deal with exception propagation
+ -- if the type has relaxed semantics for finalization.
- Add_Inlined_Body (AUD, N);
+ if Has_Relaxed_Finalization (Typ) then
+ Append_To (L, Build_Runtime_Call (Loc, RE_Abort_Undefer));
- Expand_At_End_Handler
- (Handled_Statement_Sequence (N), Blk);
+ else
+ Set_At_End_Proc (HSS, New_Occurrence_Of (AUD, Loc));
+ Expand_At_End_Handler (HSS, Blk_Id);
+
+ -- Present Abort_Undefer_Direct procedure to the back end
+ -- so that it can inline the call to the procedure.
+
+ Add_Inlined_Body (AUD, N);
+ end if;
end;
end if;
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index a6912f7..044b14a 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -45,6 +45,7 @@ with Exp_Tss; use Exp_Tss;
with Exp_Util; use Exp_Util;
with Freeze; use Freeze;
with GNAT_CUDA; use GNAT_CUDA;
+with Inline; use Inline;
with Lib; use Lib;
with Nlists; use Nlists;
with Nmake; use Nmake;
@@ -574,6 +575,11 @@ package body Exp_Ch7 is
-- conversion to the class-wide type in the case where the operation is
-- abstract.
+ function Finalize_Address_For_Node (Node : Entity_Id) return Entity_Id
+ renames Einfo.Entities.Finalization_Master_Node;
+ -- Return the Finalize_Address primitive for the object that has been
+ -- attached to a finalization Master_Node.
+
function Make_Call
(Loc : Source_Ptr;
Proc_Id : Entity_Id;
@@ -621,6 +627,11 @@ package body Exp_Ch7 is
-- [Deep_]Finalize (Acc_Typ (V).all);
-- end;
+ procedure Set_Finalize_Address_For_Node (Node, Fin_Id : Entity_Id)
+ renames Einfo.Entities.Set_Finalization_Master_Node;
+ -- Set the Finalize_Address primitive for the object that has been
+ -- attached to a finalization Master_Node.
+
----------------------------------
-- Attach_Object_To_Master_Node --
----------------------------------
@@ -915,6 +926,8 @@ package body Exp_Ch7 is
Attribute_Name => Name_Unrestricted_Access),
New_Occurrence_Of (Master_Node, Loc)));
+ Set_Finalize_Address_For_Node (Master_Node, Fin_Id);
+
Insert_After_And_Analyze
(Master_Node_Ins, Master_Node_Attach, Suppress => All_Checks);
end Attach_Object_To_Master_Node;
@@ -1734,6 +1747,10 @@ package body Exp_Ch7 is
Finalizer_Stmts : List_Id := No_List;
-- The statement list of the finalizer body
+ Has_Strict_Ctrl_Objs : Boolean := False;
+ -- A general flag which indicates whether N has at least one controlled
+ -- object with strict semantics for finalization.
+
Has_Tagged_Types : Boolean := False;
-- A general flag which indicates whether N has at least one library-
-- level tagged type declaration.
@@ -1805,11 +1822,12 @@ package body Exp_Ch7 is
begin
pragma Assert (Present (Decls));
- -- If the context contains controlled objects, then we create the
- -- finalization master, unless there is a single such object: in
- -- this common case, we'll directly finalize the object.
+ -- If the context contains controlled objects with strict semantics
+ -- for finalization, then we create the finalization master, unless
+ -- there is a single such object: in this common case, we'll directly
+ -- finalize the object.
- if Has_Ctrl_Objs then
+ if Has_Strict_Ctrl_Objs then
if Count > 1 then
if For_Package_Spec then
Master_Name :=
@@ -1900,15 +1918,41 @@ package body Exp_Ch7 is
-- The default name is _finalizer
else
- -- Generation of a finalization procedure exclusively for 'Old
- -- interally generated constants requires different name since
- -- there will need to be multiple finalization routines in the
- -- same scope. See Build_Finalizer for details.
-
Fin_Id :=
Make_Defining_Identifier (Loc,
Chars => New_External_Name (Name_uFinalizer));
+ -- The visibility semantics of At_End handlers force a strange
+ -- separation of spec and body for stack-related finalizers:
+
+ -- declare : Enclosing_Scope
+ -- procedure _finalizer;
+ -- begin
+ -- <controlled objects>
+ -- procedure _finalizer is
+ -- ...
+ -- at end
+ -- _finalizer;
+ -- end;
+
+ -- Both spec and body are within the same construct and scope, but
+ -- the body is part of the handled sequence of statements. This
+ -- placement confuses the elaboration mechanism on targets where
+ -- At_End handlers are expanded into "when all others" handlers:
+
+ -- exception
+ -- when all others =>
+ -- _finalizer; -- appears to require elab checks
+ -- at end
+ -- _finalizer;
+ -- end;
+
+ -- Since the compiler guarantees that the body of a _finalizer is
+ -- always inserted in the same construct where the At_End handler
+ -- resides, there is no need for elaboration checks.
+
+ Set_Kill_Elaboration_Checks (Fin_Id);
+
-- Inlining the finalizer produces a substantial speedup at -O2.
-- It is inlined by default at -O3. Either way, it is called
-- exactly twice (once on the normal path, and once for
@@ -1974,7 +2018,7 @@ package body Exp_Ch7 is
-- Abort_Undefer; -- Added if abort is allowed
-- end Fin_Id;
- -- If there are controlled objects to be finalized, generate:
+ -- If there are strict controlled objects to be finalized, generate:
-- procedure Fin_Id is
-- Abort : constant Boolean := Triggered_By_Abort;
@@ -1991,7 +2035,10 @@ package body Exp_Ch7 is
-- <exception propagation>
-- end Fin_Id;
- if Has_Ctrl_Objs and then Count > 1 then
+ -- If there are only controlled objects with relaxed semantics for
+ -- finalization, only the <finalization statements> are generated.
+
+ if Has_Strict_Ctrl_Objs and then Count > 1 then
Fin_Call :=
Make_Procedure_Call_Statement (Loc,
Name =>
@@ -2099,7 +2146,7 @@ package body Exp_Ch7 is
-- Raise_From_Controlled_Operation (E);
-- end if;
- if Has_Ctrl_Objs and Exceptions_OK and not For_Package then
+ if Has_Strict_Ctrl_Objs and Exceptions_OK and not For_Package then
Append_To (Finalizer_Stmts,
Build_Raise_Statement (Finalizer_Data));
end if;
@@ -2149,10 +2196,53 @@ package body Exp_Ch7 is
-- Non-package case
else
+ -- Insert the spec for the finalizer. The At_End handler must be
+ -- able to call the body which resides in a nested structure.
+
+ -- declare
+ -- procedure Fin_Id; -- Spec
+ -- begin
+ -- <objects and possibly statements>
+ -- procedure Fin_Id is ... -- Body
+ -- <statements>
+ -- at end
+ -- Fin_Id; -- At_End handler
+ -- end;
+
pragma Assert (Present (Decls));
Append_To (Decls, Fin_Spec);
- Append_To (Decls, Fin_Body);
+
+ -- When the finalizer acts solely as a cleanup routine, the body
+ -- is inserted right after the spec.
+
+ if Acts_As_Clean and not Has_Ctrl_Objs then
+ Insert_After (Fin_Spec, Fin_Body);
+
+ -- In other cases the body is inserted after the last statement
+
+ else
+ -- Manually freeze the spec. This is somewhat of a hack because
+ -- a subprogram is frozen when its body is seen and the freeze
+ -- node appears right before the body. However, in this case,
+ -- the spec must be frozen earlier since the At_End handler
+ -- must be able to call it.
+ --
+ -- declare
+ -- procedure Fin_Id; -- Spec
+ -- [Fin_Id] -- Freeze node
+ -- begin
+ -- ...
+ -- at end
+ -- Fin_Id; -- At_End handler
+ -- end;
+
+ Ensure_Freeze_Node (Fin_Id);
+ Insert_After (Fin_Spec, Freeze_Node (Fin_Id));
+ Set_Is_Frozen (Fin_Id);
+
+ Append_To (Stmts, Fin_Body);
+ end if;
end if;
Analyze (Fin_Spec, Suppress => All_Checks);
@@ -2227,11 +2317,13 @@ package body Exp_Ch7 is
procedure Processing_Actions
(Decl : Node_Id;
- Is_Protected : Boolean := False);
+ Is_Protected : Boolean := False;
+ Strict : Boolean := False);
-- Depending on the mode of operation of Process_Declarations, either
-- increment the controlled object count or process the declaration.
-- The Flag Is_Protected is set when the declaration denotes a simple
- -- protected object.
+ -- protected object. The flag Strict is true when the declaration is
+ -- for a controlled object with strict semantics for finalization.
--------------------------
-- Process_Package_Body --
@@ -2256,7 +2348,8 @@ package body Exp_Ch7 is
procedure Processing_Actions
(Decl : Node_Id;
- Is_Protected : Boolean := False)
+ Is_Protected : Boolean := False;
+ Strict : Boolean := False)
is
begin
-- Library-level tagged type
@@ -2277,6 +2370,9 @@ package body Exp_Ch7 is
else
if Preprocess then
Count := Count + 1;
+ if Strict then
+ Has_Strict_Ctrl_Objs := True;
+ end if;
else
Process_Object_Declaration (Decl, Is_Protected);
@@ -2291,6 +2387,7 @@ package body Exp_Ch7 is
Obj_Id : Entity_Id;
Obj_Typ : Entity_Id;
Pack_Id : Entity_Id;
+ Prev : Node_Id;
Spec : Node_Id;
Typ : Entity_Id;
@@ -2301,10 +2398,13 @@ package body Exp_Ch7 is
return;
end if;
- -- Process all declarations in reverse order
+ -- Process all declarations in reverse order and be prepared for them
+ -- to be moved during the processing.
Decl := Last_Non_Pragma (Decls);
while Present (Decl) loop
+ Prev := Prev_Non_Pragma (Decl);
+
-- Library-level tagged types
if Nkind (Decl) = N_Full_Type_Declaration then
@@ -2385,7 +2485,8 @@ package body Exp_Ch7 is
and then not Has_Completion (Obj_Id)
and then No (BIP_Initialization_Call (Obj_Id)))
then
- Processing_Actions (Decl);
+ Processing_Actions
+ (Decl, Strict => not Has_Relaxed_Finalization (Obj_Typ));
-- The object is of the form:
-- Obj : Access_Typ := Non_BIP_Function_Call'reference;
@@ -2403,7 +2504,10 @@ package body Exp_Ch7 is
(Is_Non_BIP_Func_Call (Expr)
and then not Is_Related_To_Func_Return (Obj_Id)))
then
- Processing_Actions (Decl);
+ Processing_Actions
+ (Decl,
+ Strict => not Has_Relaxed_Finalization
+ (Available_View (Designated_Type (Obj_Typ))));
-- Simple protected objects which use the type System.Tasking.
-- Protected_Objects.Protection to manage their locks should
@@ -2445,7 +2549,8 @@ package body Exp_Ch7 is
and then Has_Simple_Protected_Object (Obj_Typ)
and then not Restricted_Profile
then
- Processing_Actions (Decl, Is_Protected => True);
+ Processing_Actions
+ (Decl, Is_Protected => True, Strict => True);
end if;
-- Inspect the freeze node of an access-to-controlled type and
@@ -2513,7 +2618,7 @@ package body Exp_Ch7 is
Process_Package_Body (Proper_Body (Unit (Library_Unit (Decl))));
end if;
- Prev_Non_Pragma (Decl);
+ Decl := Prev;
end loop;
end Process_Declarations;
@@ -2556,15 +2661,15 @@ package body Exp_Ch7 is
Obj_Typ := Available_View (Designated_Type (Obj_Typ));
end if;
- -- If the object is a Master_Node, then nothing to do, except if it
- -- is the only object, in which case we move its declaration, call
- -- marker (if any) and initialization call, as well as mark it to
- -- avoid double processing.
+ -- If the object is a Master_Node, then nothing to do, unless there
+ -- is no or a single controlled object with strict semantics, in
+ -- which case we move its declaration, call marker (if any) and
+ -- initialization call, and also mark it to avoid double processing.
if Is_RTE (Obj_Typ, RE_Master_Node) then
Master_Node_Id := Obj_Id;
- if Count = 1 then
+ if not Has_Strict_Ctrl_Objs or else Count = 1 then
if Nkind (Next (Decl)) = N_Call_Marker then
Prepend_To (Decls, Remove_Next (Next (Decl)));
end if;
@@ -2575,15 +2680,16 @@ package body Exp_Ch7 is
end if;
-- Create the declaration of the Master_Node for the object and
- -- insert it before the declaration of the object itself, except
- -- for the case where it is the only object because it will play
- -- the role of a degenerated master and therefore needs to be
- -- inserted at the same place the master would have been.
+ -- insert it before the declaration of the object itself, unless
+ -- there is no or a single controlled object with strict semantics,
+ -- because it will effectively play the role of a degenerated master
+ -- and therefore needs to be inserted at the same place the master
+ -- would have been.
else pragma Assert (No (Finalization_Master_Node (Obj_Id)));
- -- For one object, use the Sloc the master would have had
+ -- In the latter case, use the Sloc the master would have had
- if Count = 1 then
+ if not Has_Strict_Ctrl_Objs or else Count = 1 then
Master_Node_Loc := Sloc (N);
else
Master_Node_Loc := Loc;
@@ -2597,7 +2703,7 @@ package body Exp_Ch7 is
Master_Node_Id, Obj_Id);
Push_Scope (Scope (Obj_Id));
- if Count = 1 then
+ if not Has_Strict_Ctrl_Objs or else Count = 1 then
Prepend_To (Decls, Master_Node_Decl);
else
Insert_Before (Decl, Master_Node_Decl);
@@ -2839,9 +2945,9 @@ package body Exp_Ch7 is
-- Now build the attachment call that will initialize the object's
-- Master_Node using the object's address and type's finalization
-- procedure and then attach the Master_Node to the master, unless
- -- there is a single controlled object.
+ -- there is no or a single controlled object with strict semantics.
- if Count = 1 then
+ if not Has_Strict_Ctrl_Objs or else Count = 1 then
-- Finalize_Address is not generated in CodePeer mode because the
-- body contains address arithmetic. So we don't want to generate
-- the attach in this case. Ditto if the object is a Master_Node.
@@ -2860,16 +2966,13 @@ package body Exp_Ch7 is
Prefix => New_Occurrence_Of (Fin_Id, Loc),
Attribute_Name => Name_Unrestricted_Access),
New_Occurrence_Of (Master_Node_Id, Loc)));
+
+ Set_Finalize_Address_For_Node (Master_Node_Id, Fin_Id);
end if;
-- We also generate the direct finalization call here
- Fin_Call :=
- Make_Procedure_Call_Statement (Loc,
- Name =>
- New_Occurrence_Of (RTE (RE_Finalize_Object), Loc),
- Parameter_Associations => New_List (
- New_Occurrence_Of (Master_Node_Id, Loc)));
+ Fin_Call := Make_Finalize_Call_For_Node (Loc, Master_Node_Id);
-- For CodePeer, the exception handlers normally generated here
-- generate complex flowgraphs which result in capacity problems.
@@ -2882,7 +2985,10 @@ package body Exp_Ch7 is
-- to be live. That is what we are interested in, not what
-- happens after the exception is raised.
- if Exceptions_OK and not CodePeer_Mode then
+ if Has_Strict_Ctrl_Objs
+ and then Exceptions_OK
+ and then not CodePeer_Mode
+ then
Fin_Call :=
Make_Block_Statement (Loc,
Handled_Statement_Sequence =>
@@ -5079,11 +5185,7 @@ package body Exp_Ch7 is
-- Then add the finalization call for the object
Insert_After_And_Analyze (Insert_Nod,
- Make_Procedure_Call_Statement (Loc,
- Name =>
- New_Occurrence_Of (RTE (RE_Finalize_Object), Loc),
- Parameter_Associations => New_List (
- New_Occurrence_Of (Master_Node_Id, Loc))));
+ Make_Finalize_Call_For_Node (Loc, Master_Node_Id));
-- Otherwise generate a direct finalization call for the object
@@ -7936,6 +8038,14 @@ package body Exp_Ch7 is
Make_Handled_Sequence_Of_Statements (Loc,
Statements => Stmts)));
+ -- If the type has relaxed semantics for finalization, the indirect
+ -- calls to Finalize_Address may be turned into direct ones and, in
+ -- this case, inlining them is generally profitable.
+
+ if Has_Relaxed_Finalization (Typ) then
+ Set_Is_Inlined (Proc_Id);
+ end if;
+
Set_TSS (Typ, Proc_Id);
end Make_Finalize_Address_Body;
@@ -8134,6 +8244,62 @@ package body Exp_Ch7 is
return New_List (Fin_Block);
end Make_Finalize_Address_Stmts;
+ ---------------------------------
+ -- Make_Finalize_Call_For_Node --
+ ---------------------------------
+
+ function Make_Finalize_Call_For_Node
+ (Loc : Source_Ptr;
+ Node : Entity_Id) return Node_Id
+ is
+ Fin_Id : constant Entity_Id := Finalize_Address_For_Node (Node);
+
+ Fin_Call : Node_Id;
+ Fin_Ref : Node_Id;
+
+ begin
+ -- Finalize_Address is not generated in CodePeer mode because the
+ -- body contains address arithmetic. So we don't want to generate
+ -- the call in this case.
+
+ if CodePeer_Mode then
+ return Make_Null_Statement (Loc);
+ end if;
+
+ -- The Finalize_Address primitive may be missing when the Master_Node
+ -- is written down in the source code for testing purposes.
+
+ if Present (Fin_Id) then
+ Fin_Ref :=
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Fin_Id, Loc),
+ Attribute_Name => Name_Unrestricted_Access);
+
+ else
+ Fin_Ref :=
+ Make_Selected_Component (Loc,
+ Prefix => New_Occurrence_Of (Node, Loc),
+ Selector_Name => Make_Identifier (Loc, Name_Finalize_Address));
+ end if;
+
+ Fin_Call :=
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ New_Occurrence_Of (RTE (RE_Finalize_Object), Loc),
+ Parameter_Associations => New_List (
+ New_Occurrence_Of (Node, Loc),
+ Fin_Ref));
+
+ -- Present Finalize_Address procedure to the back end so that it can
+ -- inline the call to the procedure made by Finalize_Object.
+
+ if Present (Fin_Id) and then Is_Inlined (Fin_Id) then
+ Add_Inlined_Body (Fin_Id, Fin_Call);
+ end if;
+
+ return Fin_Call;
+ end Make_Finalize_Call_For_Node;
+
-------------------------------------
-- Make_Handler_For_Ctrl_Operation --
-------------------------------------
diff --git a/gcc/ada/exp_ch7.ads b/gcc/ada/exp_ch7.ads
index 70b0a06..22303d4 100644
--- a/gcc/ada/exp_ch7.ads
+++ b/gcc/ada/exp_ch7.ads
@@ -222,6 +222,11 @@ package Exp_Ch7 is
-- an address into a pointer and subsequently calls Deep_Finalize on the
-- dereference.
+ function Make_Finalize_Call_For_Node
+ (Loc : Source_Ptr;
+ Node : Entity_Id) return Node_Id;
+ -- Create a call to finalize the object attached to the given Master_Node
+
function Make_Init_Call
(Obj_Ref : Node_Id;
Typ : Entity_Id) return Node_Id;
diff --git a/gcc/ada/gnat_rm.texi b/gcc/ada/gnat_rm.texi
index 4feef7e..24c2fdd 100644
--- a/gcc/ada/gnat_rm.texi
+++ b/gcc/ada/gnat_rm.texi
@@ -19,7 +19,7 @@
@copying
@quotation
-GNAT Reference Manual , Jun 27, 2024
+GNAT Reference Manual , Jul 29, 2024
AdaCore
@@ -29529,8 +29529,7 @@ procedure Finalize (Obj : in out Ctrl);
procedure Initialize (Obj : in out Ctrl);
@end example
-As of this writing, the relaxed semantics for finalization operations are
-only implemented for dynamically allocated objects.
+As of this writing, the RFC is implemented except for the @cite{No_Raise} aspect.
Link to the original RFC:
@indicateurl{https://github.com/AdaCore/ada-spark-rfcs/blob/topic/finalization-rehaul/considered/rfc-generalized-finalization.md}
diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi
index 80cfb41..ea1d2f9 100644
--- a/gcc/ada/gnat_ugn.texi
+++ b/gcc/ada/gnat_ugn.texi
@@ -19,7 +19,7 @@
@copying
@quotation
-GNAT User's Guide for Native Platforms , Jun 24, 2024
+GNAT User's Guide for Native Platforms , Jul 29, 2024
AdaCore
@@ -29670,8 +29670,8 @@ to permit their use in free software.
@printindex ge
-@anchor{d1}@w{ }
@anchor{gnat_ugn/gnat_utility_programs switches-related-to-project-files}@w{ }
+@anchor{d1}@w{ }
@c %**end of body
@bye
diff --git a/gcc/ada/libgnat/s-finpri.adb b/gcc/ada/libgnat/s-finpri.adb
index 9767090..a6c9db3 100644
--- a/gcc/ada/libgnat/s-finpri.adb
+++ b/gcc/ada/libgnat/s-finpri.adb
@@ -138,7 +138,7 @@ package body System.Finalization_Primitives is
Node : in out Master_Node)
is
begin
- pragma Assert (Node.Object_Address = System.Null_Address
+ pragma Assert (Node.Object_Address = Null_Address
and then Node.Finalize_Address = null);
Node.Object_Address := Object_Address;
@@ -310,7 +310,7 @@ package body System.Finalization_Primitives is
if Master.Exceptions_OK then
while Node /= null loop
begin
- Finalize_Object (Node.all);
+ Finalize_Object (Node.all, Node.Finalize_Address);
exception
when Exc : others =>
@@ -337,7 +337,7 @@ package body System.Finalization_Primitives is
else
while Node /= null loop
- Finalize_Object (Node.all);
+ Finalize_Object (Node.all, Node.Finalize_Address);
Node := Node.Next;
end loop;
@@ -361,16 +361,18 @@ package body System.Finalization_Primitives is
-- Finalize_Object --
---------------------
- procedure Finalize_Object (Node : in out Master_Node) is
- FA : constant Finalize_Address_Ptr := Node.Finalize_Address;
+ procedure Finalize_Object
+ (Node : in out Master_Node;
+ Finalize_Address : Finalize_Address_Ptr)
+ is
+ Addr : constant System.Address := Node.Object_Address;
begin
- if FA /= null then
- pragma Assert (Node.Object_Address /= System.Null_Address);
-
- Node.Finalize_Address := null;
+ if Addr /= Null_Address then
+ Node.Object_Address := Null_Address;
- FA (Node.Object_Address);
+ pragma Assert (Node.Finalize_Address = Finalize_Address);
+ Finalize_Address (Addr);
end if;
end Finalize_Object;
@@ -407,7 +409,7 @@ package body System.Finalization_Primitives is
procedure Suppress_Object_Finalize_At_End (Node : in out Master_Node) is
begin
- Node.Finalize_Address := null;
+ Node.Object_Address := Null_Address;
end Suppress_Object_Finalize_At_End;
-----------------------
diff --git a/gcc/ada/libgnat/s-finpri.ads b/gcc/ada/libgnat/s-finpri.ads
index 851917b..a61a7d7 100644
--- a/gcc/ada/libgnat/s-finpri.ads
+++ b/gcc/ada/libgnat/s-finpri.ads
@@ -102,9 +102,15 @@ package System.Finalization_Primitives with Preelaborate is
-- reverse of the order in which they were attached. Calls to the procedure
-- with a Master that has already been finalized have no effects.
- procedure Finalize_Object (Node : in out Master_Node);
- -- Finalizes the controlled object attached to Node. Calls to the procedure
- -- with a Node that has already been finalized have no effects.
+ procedure Finalize_Object
+ (Node : in out Master_Node;
+ Finalize_Address : Finalize_Address_Ptr);
+ -- Finalizes the controlled object attached to Node by generating a call to
+ -- Finalize_Address on it, which has to be equal to Node.Finalize_Address.
+ -- The weird redundancy is intended to help the optimizer turn an indirect
+ -- call to Finalize_Address into a direct one and then inline it if needed,
+ -- after having inlined Finalize_Object itself. Calls to the procedure with
+ -- a Node that has already been finalized have no effects.
procedure Suppress_Object_Finalize_At_End (Node : in out Master_Node);
-- Changes the state of Node to effectively suppress a call to Node's
@@ -179,7 +185,7 @@ private
type Master_Node is record
Finalize_Address : Finalize_Address_Ptr := null;
- Object_Address : System.Address := System.Null_Address;
+ Object_Address : System.Address := Null_Address;
Next : Master_Node_Ptr := null;
end record;
diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb
index 9b85d65..852055a 100644
--- a/gcc/ada/sem_ch6.adb
+++ b/gcc/ada/sem_ch6.adb
@@ -7103,6 +7103,10 @@ package body Sem_Ch6 is
and then Exception_Junk (Last_Stm))
or else Nkind (Last_Stm) in N_Push_xxx_Label | N_Pop_xxx_Label
+ -- Don't count subprogram bodies, for example finalizers
+
+ or else Nkind (Last_Stm) = N_Subprogram_Body
+
-- Inserted code, such as finalization calls, is irrelevant; we
-- only need to check original source. If we see a transfer of
-- control, we stop.