------------------------------
function Is_Finalizable_Transient
- (Decl : Node_Id;
- Rel_Node : Node_Id) return Boolean
+ (Decl : Node_Id;
+ N : Node_Id) return Boolean
is
Obj_Id : constant Entity_Id := Defining_Identifier (Decl);
Obj_Typ : constant Entity_Id := Base_Type (Etype (Obj_Id));
-- Start of processing for Is_Aliased
begin
- -- A controlled transient object is not considered aliased when it
- -- appears inside an expression_with_actions node even when there are
- -- explicit aliases of it:
-
- -- do
- -- Trans_Id : Ctrl_Typ ...; -- transient object
- -- Alias : ... := Trans_Id; -- object is aliased
- -- Val : constant Boolean :=
- -- ... Alias ...; -- aliasing ends
- -- <finalize Trans_Id> -- object safe to finalize
- -- in Val end;
-
- -- Expansion ensures that all aliases are encapsulated in the actions
- -- list and do not leak to the expression by forcing the evaluation
- -- of the expression.
-
- if Nkind (Rel_Node) = N_Expression_With_Actions then
- return False;
-
- -- Otherwise examine the statements after the controlled transient
- -- object and look for various forms of aliasing.
-
- else
- Stmt := First_Stmt;
- while Present (Stmt) loop
- if Nkind (Stmt) = N_Object_Declaration then
- Expr := Expression (Stmt);
+ -- Examine the statements following the controlled object and look
+ -- for various forms of aliasing.
+
+ Stmt := First_Stmt;
+ while Present (Stmt) loop
+ -- Transient objects initialized by a reference are finalized
+ -- (see Initialized_By_Reference above), so we must make sure
+ -- not to finalize the referenced object twice. And we cannot
+ -- finalize it at all if it is referenced by the nontransient
+ -- object serviced by the transient scope.
+
+ if Nkind (Stmt) = N_Object_Declaration then
+ Expr := Expression (Stmt);
+
+ -- Aliasing of the form:
+ -- Obj : ... := Trans_Id'reference;
+
+ if Present (Expr)
+ and then Nkind (Expr) = N_Reference
+ and then Is_Entity_Name (Prefix (Expr))
+ and then Entity (Prefix (Expr)) = Trans_Id
+ then
+ return True;
+ end if;
- -- Aliasing of the form:
- -- Obj : ... := Trans_Id'reference;
+ -- (Transient) renamings are never finalized so we need not bother
+ -- about finalizing transient renamed objects twice. Therefore, we
+ -- we only need to look at the nontransient object serviced by the
+ -- transient scope, if it exists and is declared as a renaming.
- if Present (Expr)
- and then Nkind (Expr) = N_Reference
- and then Nkind (Prefix (Expr)) = N_Identifier
- and then Entity (Prefix (Expr)) = Trans_Id
- then
- return True;
- end if;
-
- elsif Nkind (Stmt) = N_Object_Renaming_Declaration then
- Ren_Obj := Find_Renamed_Object (Stmt);
+ elsif Nkind (Stmt) = N_Object_Renaming_Declaration
+ and then Stmt = N
+ then
+ Ren_Obj := Find_Renamed_Object (Stmt);
- -- Aliasing of the form:
- -- Obj : ... renames ... Trans_Id ...;
+ -- Aliasing of the form:
+ -- Obj : ... renames ... Trans_Id ...;
- if Present (Ren_Obj) and then Ren_Obj = Trans_Id then
- return True;
- end if;
+ if Present (Ren_Obj) and then Ren_Obj = Trans_Id then
+ return True;
end if;
+ end if;
- Next (Stmt);
- end loop;
+ Next (Stmt);
+ end loop;
- return False;
- end if;
+ return False;
end Is_Aliased;
--------------------------
return
Ekind (Obj_Id) in E_Constant | E_Variable
and then Needs_Finalization (Desig)
- and then Nkind (Rel_Node) /= N_Simple_Return_Statement
- and then not Is_Part_Of_BIP_Return_Statement (Rel_Node)
+ and then Nkind (N) /= N_Simple_Return_Statement
+ and then not Is_Part_Of_BIP_Return_Statement (N)
-- Do not consider a transient object that was already processed
return True;
end if;
- -- Specific cases of object renamings
-
- elsif Nkind (Decl) = N_Object_Renaming_Declaration 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 Lib_Level and then Finalize_Storage_Only (Obj_Typ) then
- null;
-
- -- Ignored Ghost object renamings do not need any cleanup actions
- -- because they will not appear in the final tree.
-
- elsif Is_Ignored_Ghost_Entity (Obj_Id) then
- null;
- 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