This patch protects adjustment, finalization, and initialization-related code from scenarios where a private type may not have been successfully frozen due to a missing full view.
------------ -- Source -- ------------ -- missing_view.ads with Ada.Finalization; use Ada.Finalization; package Missing_View is type Ctrl is new Controlled with private; type Rec is new Controlled with private; private type Rec is new Controlled with record Comp : Ctrl; end record; end Missing_View; ---------------------------- -- Compilation and output -- ---------------------------- $ gcc -c missing_view.ads missing_view.ads:4:09: missing full declaration for private extension missing_view.ads:8:09: premature usage of incomplete type "Rec" defined at line 8 Tested on x86_64-pc-linux-gnu, committed on trunk 2017-01-12 Hristian Kirtchev <kirtc...@adacore.com> * exp_aggr.adb (Build_Record_Aggr_Code): Guard against a missing adjustment primitive when the ancestor type was not properly frozen. (Gen_Assign): Guard against a missing initialization primitive when the component type was not properly frozen. (Initialize_Array_Component): Guard against a missing adjustment primitive when the component type was not properly frozen. (Initialize_Record_Component): Guard against a missing adjustment primitive when the component type was not properly frozen. (Process_Transient_Component_Completion): The transient object may not be finalized when its associated type was not properly frozen. * exp_ch3.adb (Build_Assignment): Guard against a missing adjustment primitive when the component type was not properly frozen. (Build_Initialization_Call): Guard against a missing initialization primitive when the associated type was not properly frozen. (Expand_N_Object_Declaration): Guard against a missing adjustment primitive when the base type was not properly frozen. (Predefined_Primitive_Bodies): Create an empty Deep_Adjust body when there is no adjustment primitive available. Create an empty Deep_Finalize body when there is no finalization primitive available. * exp_ch4.adb (Apply_Accessibility_Check): Guard against a missing finalization primitive when the designated type was not properly frozen. (Expand_N_Allocator): Guard against a missing initialization primitive when the designated type was not properly frozen. * exp_ch5.adb (Make_Tag_Ctrl_Assignment): Add the adjustment call only when the corresponding adjustment primitive is available. * exp_ch7.adb (Build_Adjust_Or_Finalize_Statements): Generate the adjustment/finalization statements only when there is an available primitive to carry out the action. (Build_Initialize_Statements): Generate the initialization/finalization statements only when there is an available primitive to carry out the action. (Make_Adjust_Call): Do not generate a call when the underlying type is not present due to a possible missing full view. (Make_Final_Call): Do not generate a call when the underlying type is not present due to a possible missing full view. (Make_Finalize_Address_Stmts): Generate an empty body when the designated type lacks a finalization primitive. (Make_Init_Call): Do not generate a call when the underlying type is not present due to a possible missing full view. (Process_Component_For_Adjust): Add the adjustment call only when the corresponding adjustment primitive is available. (Process_Component_For_Finalize): Add the finalization call only when the corresponding finalization primitive is available. (Process_Object_Declaration): Use a null statement to emulate a missing call to the finalization primitive of the object type. * exp_ch7.ads (Make_Adjust_Call): Update the comment on usage. (Make_Final_Call): Update the comment on usage. (Make_Init_Call): Update the comment on usage. * exp_util.adb (Build_Transient_Object_Statements): Code reformatting.
Index: exp_aggr.adb =================================================================== --- exp_aggr.adb (revision 244350) +++ exp_aggr.adb (working copy) @@ -1128,6 +1128,7 @@ and then Needs_Finalization (Comp_Typ); Full_Typ : constant Entity_Id := Underlying_Type (Comp_Typ); + Adj_Call : Node_Id; Blk_Stmts : List_Id; Init_Stmt : Node_Id; @@ -1222,10 +1223,17 @@ and then Is_Controlled (Component_Type (Comp_Typ)) and then Nkind (Expr) = N_Aggregate) then - Append_To (Blk_Stmts, + Adj_Call := Make_Adjust_Call (Obj_Ref => New_Copy_Tree (Arr_Comp), - Typ => Comp_Typ)); + Typ => Comp_Typ); + + -- Guard against a missing [Deep_]Adjust when the component + -- type was not frozen properly. + + if Present (Adj_Call) then + Append_To (Blk_Stmts, Adj_Call); + end if; end if; -- Complete the protection of the initialization statements @@ -1390,6 +1398,7 @@ Comp_Typ : Entity_Id := Empty; Expr_Q : Node_Id; Indexed_Comp : Node_Id; + Init_Call : Node_Id; New_Indexes : List_Id; -- Start of processing for Gen_Assign @@ -1613,10 +1622,17 @@ end if; if Needs_Finalization (Ctype) then - Append_To (Stmts, + Init_Call := Make_Init_Call (Obj_Ref => New_Copy_Tree (Indexed_Comp), - Typ => Ctype)); + Typ => Ctype); + + -- Guard against a missing [Deep_]Initialize when the component + -- type was not properly frozen. + + if Present (Init_Call) then + Append_To (Stmts, Init_Call); + end if; end if; end if; @@ -2847,6 +2863,7 @@ Finalization_OK : constant Boolean := Needs_Finalization (Comp_Typ); Full_Typ : constant Entity_Id := Underlying_Type (Comp_Typ); + Adj_Call : Node_Id; Blk_Stmts : List_Id; Init_Stmt : Node_Id; @@ -2912,10 +2929,17 @@ -- [Deep_]Adjust (Rec_Comp); if Finalization_OK and then not Is_Limited_Type (Comp_Typ) then - Append_To (Blk_Stmts, + Adj_Call := Make_Adjust_Call (Obj_Ref => New_Copy_Tree (Rec_Comp), - Typ => Comp_Typ)); + Typ => Comp_Typ); + + -- Guard against a missing [Deep_]Adjust when the component type + -- was not properly frozen. + + if Present (Adj_Call) then + Append_To (Blk_Stmts, Adj_Call); + end if; end if; -- Complete the protection of the initialization statements @@ -3062,6 +3086,7 @@ if Nkind (N) = N_Extension_Aggregate then declare Ancestor : constant Node_Id := Ancestor_Part (N); + Adj_Call : Node_Id; Assign : List_Id; begin @@ -3274,10 +3299,17 @@ if Needs_Finalization (Etype (Ancestor)) and then not Is_Limited_Type (Etype (Ancestor)) then - Append_To (Assign, + Adj_Call := Make_Adjust_Call (Obj_Ref => New_Copy_Tree (Ref), - Typ => Etype (Ancestor))); + Typ => Etype (Ancestor)); + + -- Guard against a missing [Deep_]Adjust when the ancestor + -- type was not properly frozen. + + if Present (Adj_Call) then + Append_To (Assign, Adj_Call); + end if; end if; Append_To (L, @@ -7832,7 +7864,6 @@ not Restriction_Active (No_Exception_Propagation); begin - pragma Assert (Present (Fin_Call)); pragma Assert (Present (Hook_Clear)); -- Generate the following code if exception propagation is allowed: @@ -7872,6 +7903,7 @@ Abort_And_Exception : declare Blk_Decls : constant List_Id := New_List; Blk_Stmts : constant List_Id := New_List; + Fin_Stmts : constant List_Id := New_List; Fin_Data : Finalization_Exception_Data; @@ -7892,13 +7924,17 @@ -- Wrap the hook clear and the finalization call in order to trap -- a potential exception. + Append_To (Fin_Stmts, Hook_Clear); + + if Present (Fin_Call) then + Append_To (Fin_Stmts, Fin_Call); + end if; + Append_To (Blk_Stmts, Make_Block_Statement (Loc, Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List ( - Hook_Clear, - Fin_Call), + Statements => Fin_Stmts, Exception_Handlers => New_List ( Build_Exception_Handler (Fin_Data))))); @@ -7943,8 +7979,11 @@ begin Append_To (Blk_Stmts, Build_Runtime_Call (Loc, RE_Abort_Defer)); Append_To (Blk_Stmts, Hook_Clear); - Append_To (Blk_Stmts, Fin_Call); + if Present (Fin_Call) then + Append_To (Blk_Stmts, Fin_Call); + end if; + Append_To (Stmts, Build_Abort_Undefer_Block (Loc, Stmts => Blk_Stmts, @@ -7958,7 +7997,10 @@ else Append_To (Stmts, Hook_Clear); - Append_To (Stmts, Fin_Call); + + if Present (Fin_Call) then + Append_To (Stmts, Fin_Call); + end if; end if; end Process_Transient_Component_Completion; Index: exp_ch3.adb =================================================================== --- exp_ch3.adb (revision 244360) +++ exp_ch3.adb (working copy) @@ -1295,6 +1295,7 @@ First_Arg : Node_Id; Full_Init_Type : Entity_Id; Full_Type : Entity_Id; + Init_Call : Node_Id; Init_Type : Entity_Id; Proc : Entity_Id; @@ -1515,7 +1516,7 @@ then Append_To (Args, Make_Selected_Component (Loc, - Prefix => New_Copy_Tree (Prefix (Id_Ref)), + Prefix => New_Copy_Tree (Prefix (Id_Ref)), Selector_Name => Arg)); else Append_To (Args, Arg); @@ -1542,17 +1543,24 @@ Append_To (Res, Make_Procedure_Call_Statement (Loc, - Name => New_Occurrence_Of (Proc, Loc), + Name => New_Occurrence_Of (Proc, Loc), Parameter_Associations => Args)); if Needs_Finalization (Typ) and then Nkind (Id_Ref) = N_Selected_Component then if Chars (Selector_Name (Id_Ref)) /= Name_uParent then - Append_To (Res, + Init_Call := Make_Init_Call (Obj_Ref => New_Copy_Tree (First_Arg), - Typ => Typ)); + Typ => Typ); + + -- Guard against a missing [Deep_]Initialize when the type was not + -- properly frozen. + + if Present (Init_Call) then + Append_To (Res, Init_Call); + end if; end if; end if; @@ -1651,11 +1659,13 @@ function Build_Assignment (Id : Entity_Id; N : Node_Id) return List_Id is N_Loc : constant Source_Ptr := Sloc (N); Typ : constant Entity_Id := Underlying_Type (Etype (Id)); - Exp : Node_Id := N; - Kind : Node_Kind := Nkind (N); - Lhs : Node_Id; - Res : List_Id; + Adj_Call : Node_Id; + Exp : Node_Id := N; + Kind : Node_Kind := Nkind (N); + Lhs : Node_Id; + Res : List_Id; + begin Lhs := Make_Selected_Component (N_Loc, @@ -1734,10 +1744,17 @@ and then not (Nkind_In (Kind, N_Aggregate, N_Extension_Aggregate)) and then not Is_Limited_View (Typ) then - Append_To (Res, + Adj_Call := Make_Adjust_Call (Obj_Ref => New_Copy_Tree (Lhs), - Typ => Etype (Id))); + Typ => Etype (Id)); + + -- Guard against a missing [Deep_]Adjust when the component type + -- was not properly frozen. + + if Present (Adj_Call) then + Append_To (Res, Adj_Call); + end if; end if; -- If a component type has a predicate, add check to the component @@ -5830,7 +5847,9 @@ -- Local variables - Next_N : constant Node_Id := Next (N); + Next_N : constant Node_Id := Next (N); + + Adj_Call : Node_Id; Id_Ref : Node_Id; Tag_Assign : Node_Id; @@ -6332,10 +6351,17 @@ and then not Is_Limited_View (Typ) and then not Rewrite_As_Renaming then - Insert_Action_After (Init_After, + Adj_Call := Make_Adjust_Call ( Obj_Ref => New_Occurrence_Of (Def_Id, Loc), - Typ => Base_Typ)); + Typ => Base_Typ); + + -- Guard against a missing [Deep_]Adjust when the base type + -- was not properly frozen. + + if Present (Adj_Call) then + Insert_Action_After (Init_After, Adj_Call); + end if; end if; -- For tagged types, when an init value is given, the tag has to @@ -9530,7 +9556,9 @@ is Loc : constant Source_Ptr := Sloc (Tag_Typ); Res : constant List_Id := New_List; + Adj_Call : Node_Id; Decl : Node_Id; + Fin_Call : Node_Id; Prim : Elmt_Id; Eq_Needed : Boolean; Eq_Name : Name_Id; @@ -9756,42 +9784,45 @@ elsif not Has_Controlled_Component (Tag_Typ) then if not Is_Limited_Type (Tag_Typ) then - Decl := Predef_Deep_Spec (Loc, Tag_Typ, TSS_Deep_Adjust, True); + Adj_Call := Empty; + Decl := Predef_Deep_Spec (Loc, Tag_Typ, TSS_Deep_Adjust, True); if Is_Controlled (Tag_Typ) then - Set_Handled_Statement_Sequence (Decl, - Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List ( - Make_Adjust_Call ( - Obj_Ref => Make_Identifier (Loc, Name_V), - Typ => Tag_Typ)))); + Adj_Call := + Make_Adjust_Call ( + Obj_Ref => Make_Identifier (Loc, Name_V), + Typ => Tag_Typ); + end if; - else - Set_Handled_Statement_Sequence (Decl, - Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List ( - Make_Null_Statement (Loc)))); + if No (Adj_Call) then + Adj_Call := Make_Null_Statement (Loc); end if; + Set_Handled_Statement_Sequence (Decl, + Make_Handled_Sequence_Of_Statements (Loc, + Statements => New_List (Adj_Call))); + Append_To (Res, Decl); end if; - Decl := Predef_Deep_Spec (Loc, Tag_Typ, TSS_Deep_Finalize, True); + Fin_Call := Empty; + Decl := Predef_Deep_Spec (Loc, Tag_Typ, TSS_Deep_Finalize, True); if Is_Controlled (Tag_Typ) then - Set_Handled_Statement_Sequence (Decl, - Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List ( - Make_Final_Call - (Obj_Ref => Make_Identifier (Loc, Name_V), - Typ => Tag_Typ)))); + Fin_Call := + Make_Final_Call + (Obj_Ref => Make_Identifier (Loc, Name_V), + Typ => Tag_Typ); + end if; - else - Set_Handled_Statement_Sequence (Decl, - Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List (Make_Null_Statement (Loc)))); + if No (Fin_Call) then + Fin_Call := Make_Null_Statement (Loc); end if; + Set_Handled_Statement_Sequence (Decl, + Make_Handled_Sequence_Of_Statements (Loc, + Statements => New_List (Fin_Call))); + Append_To (Res, Decl); end if; Index: exp_ch4.adb =================================================================== --- exp_ch4.adb (revision 244350) +++ exp_ch4.adb (working copy) @@ -632,6 +632,13 @@ Make_Explicit_Dereference (Loc, New_Copy (Obj_Ref)), Typ => DesigT); + -- Guard against a missing [Deep_]Finalize when the designated + -- type was not properly frozen. + + if No (Fin_Call) then + Fin_Call := Make_Null_Statement (Loc); + end if; + -- When the target or profile supports deallocation, wrap the -- finalization call in a block to ensure proper deallocation -- even if finalization fails. Generate: @@ -722,6 +729,7 @@ Aggr_In_Place : constant Boolean := Is_Delayed_Aggregate (Exp); Indic : constant Node_Id := Subtype_Mark (Expression (N)); T : constant Entity_Id := Entity (Indic); + Adj_Call : Node_Id; Node : Node_Id; Tag_Assign : Node_Id; Temp : Entity_Id; @@ -1060,13 +1068,17 @@ -- the designated type can be an ancestor of the subtype mark of -- the allocator. - Insert_Action (N, + Adj_Call := Make_Adjust_Call (Obj_Ref => Unchecked_Convert_To (T, Make_Explicit_Dereference (Loc, Prefix => New_Occurrence_Of (Temp, Loc))), - Typ => T)); + Typ => T); + + if Present (Adj_Call) then + Insert_Action (N, Adj_Call); + end if; end if; -- Note: the accessibility check must be inserted after the call to @@ -4315,6 +4327,7 @@ Discr : Elmt_Id; Init : Entity_Id; Init_Arg1 : Node_Id; + Init_Call : Node_Id; Temp_Decl : Node_Id; Temp_Type : Entity_Id; @@ -4635,10 +4648,17 @@ -- Generate: -- [Deep_]Initialize (Init_Arg1); - Insert_Action (N, + Init_Call := Make_Init_Call (Obj_Ref => New_Copy_Tree (Init_Arg1), - Typ => T)); + Typ => T); + + -- Guard against a missing [Deep_]Initialize when the + -- designated type was not properly frozen. + + if Present (Init_Call) then + Insert_Action (N, Init_Call); + end if; end if; Rewrite (N, New_Occurrence_Of (Temp, Loc)); Index: exp_ch5.adb =================================================================== --- exp_ch5.adb (revision 244356) +++ exp_ch5.adb (working copy) @@ -4676,7 +4676,9 @@ and then not Comp_Asn and then not No_Ctrl_Actions (N) and then Tagged_Type_Expansion; - Tag_Id : Entity_Id; + Adj_Call : Node_Id; + Fin_Call : Node_Id; + Tag_Id : Entity_Id; begin -- Finalize the target of the assignment when controlled @@ -4709,10 +4711,14 @@ null; else - Append_To (Res, + Fin_Call := Make_Final_Call (Obj_Ref => Duplicate_Subexpr_No_Checks (L), - Typ => Etype (L))); + Typ => Etype (L)); + + if Present (Fin_Call) then + Append_To (Res, Fin_Call); + end if; end if; -- Save the Tag in a local variable Tag_Id @@ -4765,10 +4771,14 @@ -- init proc since it is an initialization more than an assignment). if Ctrl_Act then - Append_To (Res, + Adj_Call := Make_Adjust_Call (Obj_Ref => Duplicate_Subexpr_Move_Checks (L), - Typ => Etype (L))); + Typ => Etype (L)); + + if Present (Adj_Call) then + Append_To (Res, Adj_Call); + end if; end if; return Res; Index: exp_ch7.adb =================================================================== --- exp_ch7.adb (revision 244352) +++ exp_ch7.adb (working copy) @@ -3062,6 +3062,13 @@ Obj_Ref => Obj_Ref, Typ => Obj_Typ); + -- Guard against a missing [Deep_]Finalize when the object type + -- was not properly frozen. + + if No (Fin_Call) then + Fin_Call := Make_Null_Statement (Loc); + end if; + -- For CodePeer, the exception handlers normally generated here -- generate complex flowgraphs which result in capacity problems. -- Omitting these handlers for CodePeer is justified as follows: @@ -6905,10 +6912,12 @@ is Loc : constant Source_Ptr := Sloc (Obj_Ref); Adj_Id : Entity_Id := Empty; - Ref : Node_Id := Obj_Ref; + Ref : Node_Id; Utyp : Entity_Id; begin + Ref := Obj_Ref; + -- Recover the proper type which contains Deep_Adjust if Is_Class_Wide_Type (Typ) then @@ -6922,7 +6931,7 @@ -- Deal with untagged derivation of private views - if Is_Untagged_Derivation (Typ) then + if Present (Utyp) and then Is_Untagged_Derivation (Typ) then Utyp := Underlying_Type (Root_Type (Base_Type (Typ))); Ref := Unchecked_Convert_To (Utyp, Ref); Set_Assignment_OK (Ref); @@ -6931,14 +6940,21 @@ -- When dealing with the completion of a private type, use the base -- type instead. - if Utyp /= Base_Type (Utyp) then + if Present (Utyp) and then Utyp /= Base_Type (Utyp) then pragma Assert (Is_Private_Type (Typ)); Utyp := Base_Type (Utyp); Ref := Unchecked_Convert_To (Utyp, Ref); end if; - if Skip_Self then + -- The underlying type may not be present due to a missing full view. In + -- this case freezing did not take place and there is no [Deep_]Adjust + -- primitive to call. + + if No (Utyp) then + return Empty; + + elsif Skip_Self then if Has_Controlled_Component (Utyp) then if Is_Tagged_Type (Utyp) then Adj_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Adjust); @@ -6998,7 +7014,7 @@ return Make_Call (Loc, Proc_Id => Adj_Id, - Param => New_Copy_Tree (Ref), + Param => Ref, Skip_Self => Skip_Self); else return Empty; @@ -7171,23 +7187,13 @@ function Build_Adjust_Or_Finalize_Statements (Typ : Entity_Id) return List_Id is - Comp_Typ : constant Entity_Id := Component_Type (Typ); - Exceptions_OK : constant Boolean := - not Restriction_Active (No_Exception_Propagation); - Index_List : constant List_Id := New_List; - Loc : constant Source_Ptr := Sloc (Typ); - Num_Dims : constant Int := Number_Dimensions (Typ); + Comp_Typ : constant Entity_Id := Component_Type (Typ); + Exceptions_OK : constant Boolean := + not Restriction_Active (No_Exception_Propagation); + Index_List : constant List_Id := New_List; + Loc : constant Source_Ptr := Sloc (Typ); + Num_Dims : constant Int := Number_Dimensions (Typ); - Finalizer_Decls : List_Id := No_List; - Finalizer_Data : Finalization_Exception_Data; - Call : Node_Id; - Comp_Ref : Node_Id; - Core_Loop : Node_Id; - Dim : Int; - J : Entity_Id; - Loop_Id : Entity_Id; - Stmts : List_Id; - procedure Build_Indexes; -- Generate the indexes used in the dimension loops @@ -7206,13 +7212,26 @@ end loop; end Build_Indexes; + -- Local variables + + Final_Decls : List_Id := No_List; + Final_Data : Finalization_Exception_Data; + Block : Node_Id; + Call : Node_Id; + Comp_Ref : Node_Id; + Core_Loop : Node_Id; + Dim : Int; + J : Entity_Id; + Loop_Id : Entity_Id; + Stmts : List_Id; + -- Start of processing for Build_Adjust_Or_Finalize_Statements begin - Finalizer_Decls := New_List; + Final_Decls := New_List; Build_Indexes; - Build_Object_Declarations (Finalizer_Data, Finalizer_Decls, Loc); + Build_Object_Declarations (Final_Data, Final_Decls, Loc); Comp_Ref := Make_Indexed_Component (Loc, @@ -7233,99 +7252,111 @@ Call := Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ); end if; - -- Generate the block which houses the adjust or finalize call: + if Present (Call) then - -- begin - -- <adjust or finalize call> + -- Generate the block which houses the adjust or finalize call: - -- exception - -- when others => - -- if not Raised then - -- Raised := True; - -- Save_Occurrence (E, Get_Current_Excep.all.all); - -- end if; - -- end; + -- begin + -- <adjust or finalize call> - if Exceptions_OK then - Core_Loop := - Make_Block_Statement (Loc, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List (Call), - Exception_Handlers => New_List ( - Build_Exception_Handler (Finalizer_Data)))); - else - Core_Loop := Call; - end if; + -- exception + -- when others => + -- if not Raised then + -- Raised := True; + -- Save_Occurrence (E, Get_Current_Excep.all.all); + -- end if; + -- end; - -- Generate the dimension loops starting from the innermost one + if Exceptions_OK then + Core_Loop := + Make_Block_Statement (Loc, + Handled_Statement_Sequence => + Make_Handled_Sequence_Of_Statements (Loc, + Statements => New_List (Call), + Exception_Handlers => New_List ( + Build_Exception_Handler (Final_Data)))); + else + Core_Loop := Call; + end if; - -- for Jnn in [reverse] V'Range (Dim) loop - -- <core loop> - -- end loop; + -- Generate the dimension loops starting from the innermost one - J := Last (Index_List); - Dim := Num_Dims; - while Present (J) and then Dim > 0 loop - Loop_Id := J; - Prev (J); - Remove (Loop_Id); + -- for Jnn in [reverse] V'Range (Dim) loop + -- <core loop> + -- end loop; - Core_Loop := - Make_Loop_Statement (Loc, - Iteration_Scheme => - Make_Iteration_Scheme (Loc, - Loop_Parameter_Specification => - Make_Loop_Parameter_Specification (Loc, - Defining_Identifier => Loop_Id, - Discrete_Subtype_Definition => - Make_Attribute_Reference (Loc, - Prefix => Make_Identifier (Loc, Name_V), - Attribute_Name => Name_Range, - Expressions => New_List ( - Make_Integer_Literal (Loc, Dim))), + J := Last (Index_List); + Dim := Num_Dims; + while Present (J) and then Dim > 0 loop + Loop_Id := J; + Prev (J); + Remove (Loop_Id); - Reverse_Present => Prim = Finalize_Case)), + Core_Loop := + Make_Loop_Statement (Loc, + Iteration_Scheme => + Make_Iteration_Scheme (Loc, + Loop_Parameter_Specification => + Make_Loop_Parameter_Specification (Loc, + Defining_Identifier => Loop_Id, + Discrete_Subtype_Definition => + Make_Attribute_Reference (Loc, + Prefix => Make_Identifier (Loc, Name_V), + Attribute_Name => Name_Range, + Expressions => New_List ( + Make_Integer_Literal (Loc, Dim))), - Statements => New_List (Core_Loop), - End_Label => Empty); + Reverse_Present => + Prim = Finalize_Case)), - Dim := Dim - 1; - end loop; + Statements => New_List (Core_Loop), + End_Label => Empty); - -- Generate the block which contains the core loop, the declarations - -- of the abort flag, the exception occurrence, the raised flag and - -- the conditional raise: + Dim := Dim - 1; + end loop; - -- declare - -- Abort : constant Boolean := Triggered_By_Abort; - -- <or> - -- Abort : constant Boolean := False; -- no abort + -- Generate the block which contains the core loop, declarations + -- of the abort flag, the exception occurrence, the raised flag + -- and the conditional raise: - -- E : Exception_Occurrence; - -- Raised : Boolean := False; + -- declare + -- Abort : constant Boolean := Triggered_By_Abort; + -- <or> + -- Abort : constant Boolean := False; -- no abort - -- begin - -- <core loop> + -- E : Exception_Occurrence; + -- Raised : Boolean := False; - -- if Raised and then not Abort then - -- Raise_From_Controlled_Operation (E); - -- end if; - -- end; + -- begin + -- <core loop> - Stmts := New_List (Core_Loop); + -- if Raised and then not Abort then + -- Raise_From_Controlled_Operation (E); + -- end if; + -- end; - if Exceptions_OK then - Append_To (Stmts, Build_Raise_Statement (Finalizer_Data)); + Stmts := New_List (Core_Loop); + + if Exceptions_OK then + Append_To (Stmts, Build_Raise_Statement (Final_Data)); + end if; + + Block := + Make_Block_Statement (Loc, + Declarations => Final_Decls, + Handled_Statement_Sequence => + Make_Handled_Sequence_Of_Statements (Loc, + Statements => Stmts)); + + -- Otherwise previous errors or a missing full view may prevent the + -- proper freezing of the component type. If this is the case, there + -- is no [Deep_]Adjust or [Deep_]Finalize primitive to call. + + else + Block := Make_Null_Statement (Loc); end if; - return - New_List ( - Make_Block_Statement (Loc, - Declarations => - Finalizer_Decls, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, Stmts))); + return New_List (Block); end Build_Adjust_Or_Finalize_Statements; --------------------------------- @@ -7333,32 +7364,21 @@ --------------------------------- function Build_Initialize_Statements (Typ : Entity_Id) return List_Id is - Comp_Typ : constant Entity_Id := Component_Type (Typ); - Exceptions_OK : constant Boolean := - not Restriction_Active (No_Exception_Propagation); - Final_List : constant List_Id := New_List; - Index_List : constant List_Id := New_List; - Loc : constant Source_Ptr := Sloc (Typ); - Num_Dims : constant Int := Number_Dimensions (Typ); + Comp_Typ : constant Entity_Id := Component_Type (Typ); + Exceptions_OK : constant Boolean := + not Restriction_Active (No_Exception_Propagation); + Final_List : constant List_Id := New_List; + Index_List : constant List_Id := New_List; + Loc : constant Source_Ptr := Sloc (Typ); + Num_Dims : constant Int := Number_Dimensions (Typ); - Counter_Id : Entity_Id; - Dim : Int; - F : Node_Id; - Fin_Stmt : Node_Id; - Final_Block : Node_Id; - Final_Loop : Node_Id; - Finalizer_Data : Finalization_Exception_Data; - Finalizer_Decls : List_Id := No_List; - Init_Loop : Node_Id; - J : Node_Id; - Loop_Id : Node_Id; - Stmts : List_Id; - - function Build_Counter_Assignment return Node_Id; + function Build_Assignment (Counter_Id : Entity_Id) return Node_Id; -- Generate the following assignment: -- Counter := V'Length (1) * -- ... -- V'Length (N) - Counter; + -- + -- Counter_Id denotes the entity of the counter. function Build_Finalization_Call return Node_Id; -- Generate a deep finalization call for an array element @@ -7370,11 +7390,11 @@ function Build_Initialization_Call return Node_Id; -- Generate a deep initialization call for an array element - ------------------------------ - -- Build_Counter_Assignment -- - ------------------------------ + ---------------------- + -- Build_Assignment -- + ---------------------- - function Build_Counter_Assignment return Node_Id is + function Build_Assignment (Counter_Id : Entity_Id) return Node_Id is Dim : Int; Expr : Node_Id; @@ -7417,7 +7437,7 @@ Make_Op_Subtract (Loc, Left_Opnd => Expr, Right_Opnd => New_Occurrence_Of (Counter_Id, Loc))); - end Build_Counter_Assignment; + end Build_Assignment; ----------------------------- -- Build_Finalization_Call -- @@ -7476,14 +7496,31 @@ return Make_Init_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ); end Build_Initialization_Call; + -- Local variables + + Counter_Id : Entity_Id; + Dim : Int; + F : Node_Id; + Fin_Stmt : Node_Id; + Final_Block : Node_Id; + Final_Data : Finalization_Exception_Data; + Final_Decls : List_Id := No_List; + Final_Loop : Node_Id; + Init_Block : Node_Id; + Init_Call : Node_Id; + Init_Loop : Node_Id; + J : Node_Id; + Loop_Id : Node_Id; + Stmts : List_Id; + -- Start of processing for Build_Initialize_Statements begin - Counter_Id := Make_Temporary (Loc, 'C'); - Finalizer_Decls := New_List; + Counter_Id := Make_Temporary (Loc, 'C'); + Final_Decls := New_List; Build_Indexes; - Build_Object_Declarations (Finalizer_Data, Finalizer_Decls, Loc); + Build_Object_Declarations (Final_Data, Final_Decls, Loc); -- Generate the block which houses the finalization call, the index -- guard and the handler which triggers Program_Error later on. @@ -7502,115 +7539,124 @@ -- end; -- end if; - if Exceptions_OK then - Fin_Stmt := - Make_Block_Statement (Loc, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List (Build_Finalization_Call), - Exception_Handlers => New_List ( - Build_Exception_Handler (Finalizer_Data)))); - else - Fin_Stmt := Build_Finalization_Call; - end if; + Fin_Stmt := Build_Finalization_Call; - -- This is the core of the loop, the dimension iterators are added - -- one by one in reverse. + if Present (Fin_Stmt) then + if Exceptions_OK then + Fin_Stmt := + Make_Block_Statement (Loc, + Handled_Statement_Sequence => + Make_Handled_Sequence_Of_Statements (Loc, + Statements => New_List (Fin_Stmt), + Exception_Handlers => New_List ( + Build_Exception_Handler (Final_Data)))); + end if; - Final_Loop := - Make_If_Statement (Loc, - Condition => - Make_Op_Gt (Loc, - Left_Opnd => New_Occurrence_Of (Counter_Id, Loc), - Right_Opnd => Make_Integer_Literal (Loc, 0)), + -- This is the core of the loop, the dimension iterators are added + -- one by one in reverse. - Then_Statements => New_List ( - Make_Assignment_Statement (Loc, - Name => New_Occurrence_Of (Counter_Id, Loc), - Expression => - Make_Op_Subtract (Loc, - Left_Opnd => New_Occurrence_Of (Counter_Id, Loc), - Right_Opnd => Make_Integer_Literal (Loc, 1)))), + Final_Loop := + Make_If_Statement (Loc, + Condition => + Make_Op_Gt (Loc, + Left_Opnd => New_Occurrence_Of (Counter_Id, Loc), + Right_Opnd => Make_Integer_Literal (Loc, 0)), - Else_Statements => New_List (Fin_Stmt)); + Then_Statements => New_List ( + Make_Assignment_Statement (Loc, + Name => New_Occurrence_Of (Counter_Id, Loc), + Expression => + Make_Op_Subtract (Loc, + Left_Opnd => New_Occurrence_Of (Counter_Id, Loc), + Right_Opnd => Make_Integer_Literal (Loc, 1)))), - -- Generate all finalization loops starting from the innermost - -- dimension. + Else_Statements => New_List (Fin_Stmt)); - -- for Fnn in reverse V'Range (Dim) loop - -- <final loop> - -- end loop; + -- Generate all finalization loops starting from the innermost + -- dimension. - F := Last (Final_List); - Dim := Num_Dims; - while Present (F) and then Dim > 0 loop - Loop_Id := F; - Prev (F); - Remove (Loop_Id); + -- for Fnn in reverse V'Range (Dim) loop + -- <final loop> + -- end loop; - Final_Loop := - Make_Loop_Statement (Loc, - Iteration_Scheme => - Make_Iteration_Scheme (Loc, - Loop_Parameter_Specification => - Make_Loop_Parameter_Specification (Loc, - Defining_Identifier => Loop_Id, - Discrete_Subtype_Definition => - Make_Attribute_Reference (Loc, - Prefix => Make_Identifier (Loc, Name_V), - Attribute_Name => Name_Range, - Expressions => New_List ( - Make_Integer_Literal (Loc, Dim))), + F := Last (Final_List); + Dim := Num_Dims; + while Present (F) and then Dim > 0 loop + Loop_Id := F; + Prev (F); + Remove (Loop_Id); - Reverse_Present => True)), + Final_Loop := + Make_Loop_Statement (Loc, + Iteration_Scheme => + Make_Iteration_Scheme (Loc, + Loop_Parameter_Specification => + Make_Loop_Parameter_Specification (Loc, + Defining_Identifier => Loop_Id, + Discrete_Subtype_Definition => + Make_Attribute_Reference (Loc, + Prefix => Make_Identifier (Loc, Name_V), + Attribute_Name => Name_Range, + Expressions => New_List ( + Make_Integer_Literal (Loc, Dim))), - Statements => New_List (Final_Loop), - End_Label => Empty); + Reverse_Present => True)), - Dim := Dim - 1; - end loop; + Statements => New_List (Final_Loop), + End_Label => Empty); - -- Generate the block which contains the finalization loops, the - -- declarations of the abort flag, the exception occurrence, the - -- raised flag and the conditional raise. + Dim := Dim - 1; + end loop; - -- declare - -- Abort : constant Boolean := Triggered_By_Abort; - -- <or> - -- Abort : constant Boolean := False; -- no abort + -- Generate the block which contains the finalization loops, the + -- declarations of the abort flag, the exception occurrence, the + -- raised flag and the conditional raise. - -- E : Exception_Occurrence; - -- Raised : Boolean := False; + -- declare + -- Abort : constant Boolean := Triggered_By_Abort; + -- <or> + -- Abort : constant Boolean := False; -- no abort - -- begin - -- Counter := - -- V'Length (1) * - -- ... - -- V'Length (N) - Counter; + -- E : Exception_Occurrence; + -- Raised : Boolean := False; - -- <final loop> + -- begin + -- Counter := + -- V'Length (1) * + -- ... + -- V'Length (N) - Counter; - -- if Raised and then not Abort then - -- Raise_From_Controlled_Operation (E); - -- end if; + -- <final loop> - -- raise; - -- end; + -- if Raised and then not Abort then + -- Raise_From_Controlled_Operation (E); + -- end if; - Stmts := New_List (Build_Counter_Assignment, Final_Loop); + -- raise; + -- end; - if Exceptions_OK then - Append_To (Stmts, Build_Raise_Statement (Finalizer_Data)); - Append_To (Stmts, Make_Raise_Statement (Loc)); + Stmts := New_List (Build_Assignment (Counter_Id), Final_Loop); + + if Exceptions_OK then + Append_To (Stmts, Build_Raise_Statement (Final_Data)); + Append_To (Stmts, Make_Raise_Statement (Loc)); + end if; + + Final_Block := + Make_Block_Statement (Loc, + Declarations => Final_Decls, + Handled_Statement_Sequence => + Make_Handled_Sequence_Of_Statements (Loc, + Statements => Stmts)); + + -- Otherwise previous errors or a missing full view may prevent the + -- proper freezing of the component type. If this is the case, there + -- is no [Deep_]Finalize primitive to call. + + else + Final_Block := Make_Null_Statement (Loc); end if; - Final_Block := - Make_Block_Statement (Loc, - Declarations => - Finalizer_Decls, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts)); - -- Generate the block which contains the initialization call and -- the partial finalization code. @@ -7624,70 +7670,73 @@ -- <finalization code> -- end; - Init_Loop := - Make_Block_Statement (Loc, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List (Build_Initialization_Call), - Exception_Handlers => New_List ( - Make_Exception_Handler (Loc, - Exception_Choices => New_List (Make_Others_Choice (Loc)), - Statements => New_List (Final_Block))))); + Init_Call := Build_Initialization_Call; - Append_To (Statements (Handled_Statement_Sequence (Init_Loop)), - Make_Assignment_Statement (Loc, - Name => New_Occurrence_Of (Counter_Id, Loc), - Expression => - Make_Op_Add (Loc, - Left_Opnd => New_Occurrence_Of (Counter_Id, Loc), - Right_Opnd => Make_Integer_Literal (Loc, 1)))); + if Present (Init_Call) then + Init_Loop := + Make_Block_Statement (Loc, + Handled_Statement_Sequence => + Make_Handled_Sequence_Of_Statements (Loc, + Statements => New_List (Init_Call), + Exception_Handlers => New_List ( + Make_Exception_Handler (Loc, + Exception_Choices => New_List ( + Make_Others_Choice (Loc)), + Statements => New_List (Final_Block))))); - -- Generate all initialization loops starting from the innermost - -- dimension. + Append_To (Statements (Handled_Statement_Sequence (Init_Loop)), + Make_Assignment_Statement (Loc, + Name => New_Occurrence_Of (Counter_Id, Loc), + Expression => + Make_Op_Add (Loc, + Left_Opnd => New_Occurrence_Of (Counter_Id, Loc), + Right_Opnd => Make_Integer_Literal (Loc, 1)))); - -- for Jnn in V'Range (Dim) loop - -- <init loop> - -- end loop; + -- Generate all initialization loops starting from the innermost + -- dimension. - J := Last (Index_List); - Dim := Num_Dims; - while Present (J) and then Dim > 0 loop - Loop_Id := J; - Prev (J); - Remove (Loop_Id); + -- for Jnn in V'Range (Dim) loop + -- <init loop> + -- end loop; - Init_Loop := - Make_Loop_Statement (Loc, - Iteration_Scheme => - Make_Iteration_Scheme (Loc, - Loop_Parameter_Specification => - Make_Loop_Parameter_Specification (Loc, - Defining_Identifier => Loop_Id, - Discrete_Subtype_Definition => - Make_Attribute_Reference (Loc, - Prefix => Make_Identifier (Loc, Name_V), - Attribute_Name => Name_Range, - Expressions => New_List ( - Make_Integer_Literal (Loc, Dim))))), + J := Last (Index_List); + Dim := Num_Dims; + while Present (J) and then Dim > 0 loop + Loop_Id := J; + Prev (J); + Remove (Loop_Id); - Statements => New_List (Init_Loop), - End_Label => Empty); + Init_Loop := + Make_Loop_Statement (Loc, + Iteration_Scheme => + Make_Iteration_Scheme (Loc, + Loop_Parameter_Specification => + Make_Loop_Parameter_Specification (Loc, + Defining_Identifier => Loop_Id, + Discrete_Subtype_Definition => + Make_Attribute_Reference (Loc, + Prefix => Make_Identifier (Loc, Name_V), + Attribute_Name => Name_Range, + Expressions => New_List ( + Make_Integer_Literal (Loc, Dim))))), - Dim := Dim - 1; - end loop; + Statements => New_List (Init_Loop), + End_Label => Empty); - -- Generate the block which contains the counter variable and the - -- initialization loops. + Dim := Dim - 1; + end loop; - -- declare - -- Counter : Integer := 0; - -- begin - -- <init loop> - -- end; + -- Generate the block which contains the counter variable and the + -- initialization loops. - return - New_List ( - Make_Block_Statement (Loc, + -- declare + -- Counter : Integer := 0; + -- begin + -- <init loop> + -- end; + + Init_Block := + Make_Block_Statement (Loc, Declarations => New_List ( Make_Object_Declaration (Loc, Defining_Identifier => Counter_Id, @@ -7697,7 +7746,17 @@ Handled_Statement_Sequence => Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List (Init_Loop)))); + Statements => New_List (Init_Loop))); + + -- Otherwise previous errors or a missing full view may prevent the + -- proper freezing of the component type. If this is the case, there + -- is no [Deep_]Initialize primitive to call. + + else + Init_Block := Make_Null_Statement (Loc); + end if; + + return New_List (Init_Block); end Build_Initialize_Statements; ----------------------- @@ -7983,7 +8042,8 @@ Exceptions_OK : constant Boolean := not Restriction_Active (No_Exception_Propagation); Loc : constant Source_Ptr := Sloc (Typ); - Typ_Def : constant Node_Id := Type_Definition (Parent (Typ)); + Typ_Def : constant Node_Id := + Type_Definition (Parent (Typ)); Bod_Stmts : List_Id; Finalizer_Data : Finalization_Exception_Data; @@ -8002,12 +8062,7 @@ function Process_Component_List_For_Adjust (Comps : Node_Id) return List_Id is - Stmts : constant List_Id := New_List; - Decl : Node_Id; - Decl_Id : Entity_Id; - Decl_Typ : Entity_Id; - Has_POC : Boolean; - Num_Comps : Nat; + Stmts : constant List_Id := New_List; procedure Process_Component_For_Adjust (Decl : Node_Id); -- Process the declaration of a single controlled component @@ -8017,10 +8072,11 @@ ---------------------------------- procedure Process_Component_For_Adjust (Decl : Node_Id) is - Id : constant Entity_Id := Defining_Identifier (Decl); - Typ : constant Entity_Id := Etype (Id); - Adj_Stmt : Node_Id; + Id : constant Entity_Id := Defining_Identifier (Decl); + Typ : constant Entity_Id := Etype (Id); + Adj_Call : Node_Id; + begin -- begin -- [Deep_]Adjust (V.Id); @@ -8033,7 +8089,7 @@ -- end if; -- end; - Adj_Stmt := + Adj_Call := Make_Adjust_Call ( Obj_Ref => Make_Selected_Component (Loc, @@ -8041,19 +8097,32 @@ Selector_Name => Make_Identifier (Loc, Chars (Id))), Typ => Typ); - if Exceptions_OK then - Adj_Stmt := - Make_Block_Statement (Loc, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List (Adj_Stmt), - Exception_Handlers => New_List ( - Build_Exception_Handler (Finalizer_Data)))); + -- Guard against a missing [Deep_]Adjust when the component + -- type was not properly frozen. + + if Present (Adj_Call) then + if Exceptions_OK then + Adj_Call := + Make_Block_Statement (Loc, + Handled_Statement_Sequence => + Make_Handled_Sequence_Of_Statements (Loc, + Statements => New_List (Adj_Call), + Exception_Handlers => New_List ( + Build_Exception_Handler (Finalizer_Data)))); + end if; + + Append_To (Stmts, Adj_Call); end if; - - Append_To (Stmts, Adj_Stmt); end Process_Component_For_Adjust; + -- Local variables + + Decl : Node_Id; + Decl_Id : Entity_Id; + Decl_Typ : Entity_Id; + Has_POC : Boolean; + Num_Comps : Nat; + -- Start of processing for Process_Component_List_For_Adjust begin @@ -8389,7 +8458,8 @@ Exceptions_OK : constant Boolean := not Restriction_Active (No_Exception_Propagation); Loc : constant Source_Ptr := Sloc (Typ); - Typ_Def : constant Node_Id := Type_Definition (Parent (Typ)); + Typ_Def : constant Node_Id := + Type_Definition (Parent (Typ)); Bod_Stmts : List_Id; Counter : Int := 0; @@ -8447,7 +8517,7 @@ is Id : constant Entity_Id := Defining_Identifier (Decl); Typ : constant Entity_Id := Etype (Id); - Fin_Stmt : Node_Id; + Fin_Call : Node_Id; begin if Is_Local then @@ -8511,7 +8581,7 @@ -- end if; -- end; - Fin_Stmt := + Fin_Call := Make_Final_Call (Obj_Ref => Make_Selected_Component (Loc, @@ -8519,17 +8589,22 @@ Selector_Name => Make_Identifier (Loc, Chars (Id))), Typ => Typ); - if not Restriction_Active (No_Exception_Propagation) then - Fin_Stmt := - Make_Block_Statement (Loc, - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List (Fin_Stmt), - Exception_Handlers => New_List ( - Build_Exception_Handler (Finalizer_Data)))); + -- Guard against a missing [Deep_]Finalize when the component + -- type was not properly frozen. + + if Present (Fin_Call) then + if Exceptions_OK then + Fin_Call := + Make_Block_Statement (Loc, + Handled_Statement_Sequence => + Make_Handled_Sequence_Of_Statements (Loc, + Statements => New_List (Fin_Call), + Exception_Handlers => New_List ( + Build_Exception_Handler (Finalizer_Data)))); + end if; + + Append_To (Stmts, Fin_Call); end if; - - Append_To (Stmts, Fin_Stmt); end Process_Component_For_Finalize; -- Start of processing for Process_Component_List_For_Finalize @@ -9061,17 +9136,18 @@ Utyp : Entity_Id; begin + Ref := Obj_Ref; + -- Recover the proper type which contains [Deep_]Finalize if Is_Class_Wide_Type (Typ) then Utyp := Root_Type (Typ); Atyp := Utyp; - Ref := Obj_Ref; elsif Is_Concurrent_Type (Typ) then Utyp := Corresponding_Record_Type (Typ); Atyp := Empty; - Ref := Convert_Concurrent (Obj_Ref, Typ); + Ref := Convert_Concurrent (Ref, Typ); elsif Is_Private_Type (Typ) and then Present (Full_View (Typ)) @@ -9079,12 +9155,11 @@ then Utyp := Corresponding_Record_Type (Full_View (Typ)); Atyp := Typ; - Ref := Convert_Concurrent (Obj_Ref, Full_View (Typ)); + Ref := Convert_Concurrent (Ref, Full_View (Typ)); else Utyp := Typ; Atyp := Typ; - Ref := Obj_Ref; end if; Utyp := Underlying_Type (Base_Type (Utyp)); @@ -9113,7 +9188,8 @@ -- their parents. In this case, [Deep_]Finalize can be found in the full -- view of the parent type. - if Is_Tagged_Type (Utyp) + if Present (Utyp) + and then Is_Tagged_Type (Utyp) and then Is_Derived_Type (Utyp) and then Is_Empty_Elmt_List (Primitive_Operations (Utyp)) and then Is_Private_Type (Etype (Utyp)) @@ -9127,7 +9203,7 @@ -- When dealing with the completion of a private type, use the base type -- instead. - if Utyp /= Base_Type (Utyp) then + if Present (Utyp) and then Utyp /= Base_Type (Utyp) then pragma Assert (Present (Atyp) and then Is_Private_Type (Atyp)); Utyp := Base_Type (Utyp); @@ -9135,7 +9211,14 @@ Set_Assignment_OK (Ref); end if; - if Skip_Self then + -- The underlying type may not be present due to a missing full view. In + -- this case freezing did not take place and there is no [Deep_]Finalize + -- primitive to call. + + if No (Utyp) then + return Empty; + + elsif Skip_Self then if Has_Controlled_Component (Utyp) then if Is_Tagged_Type (Utyp) then Fin_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Finalize); @@ -9215,7 +9298,7 @@ return Make_Call (Loc, Proc_Id => Fin_Id, - Param => New_Copy_Tree (Ref), + Param => Ref, Skip_Self => Skip_Self); else return Empty; @@ -9310,18 +9393,21 @@ --------------------------------- function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id is - Loc : constant Source_Ptr := Sloc (Typ); - Ptr_Typ : constant Entity_Id := Make_Temporary (Loc, 'P'); - Decls : List_Id; - Desg_Typ : Entity_Id; - Obj_Expr : Node_Id; + Loc : constant Source_Ptr := Sloc (Typ); + Decls : List_Id; + Desig_Typ : Entity_Id; + Fin_Block : Node_Id; + Fin_Call : Node_Id; + Obj_Expr : Node_Id; + Ptr_Typ : Entity_Id; + begin if Is_Array_Type (Typ) then if Is_Constrained (First_Subtype (Typ)) then - Desg_Typ := First_Subtype (Typ); + Desig_Typ := First_Subtype (Typ); else - Desg_Typ := Base_Type (Typ); + Desig_Typ := Base_Type (Typ); end if; -- Class-wide types of constrained root types @@ -9353,26 +9439,28 @@ Parent_Typ := Underlying_Record_View (Parent_Typ); end if; - Desg_Typ := Class_Wide_Type (Underlying_Type (Parent_Typ)); + Desig_Typ := Class_Wide_Type (Underlying_Type (Parent_Typ)); end; -- General case else - Desg_Typ := Typ; + Desig_Typ := Typ; end if; -- Generate: -- type Ptr_Typ is access all Typ; -- for Ptr_Typ'Storage_Size use 0; + Ptr_Typ := Make_Temporary (Loc, 'P'); + Decls := New_List ( Make_Full_Type_Declaration (Loc, Defining_Identifier => Ptr_Typ, Type_Definition => Make_Access_To_Object_Definition (Loc, All_Present => True, - Subtype_Indication => New_Occurrence_Of (Desg_Typ, Loc))), + Subtype_Indication => New_Occurrence_Of (Desig_Typ, Loc))), Make_Attribute_Definition_Clause (Loc, Name => New_Occurrence_Of (Ptr_Typ, Loc), @@ -9405,7 +9493,7 @@ -- Generate: -- Dnn : constant Storage_Offset := - -- Desg_Typ'Descriptor_Size / Storage_Unit; + -- Desig_Typ'Descriptor_Size / Storage_Unit; Dope_Id := Make_Temporary (Loc, 'D'); @@ -9419,7 +9507,7 @@ Make_Op_Divide (Loc, Left_Opnd => Make_Attribute_Reference (Loc, - Prefix => New_Occurrence_Of (Desg_Typ, Loc), + Prefix => New_Occurrence_Of (Desig_Typ, Loc), Attribute_Name => Name_Descriptor_Size), Right_Opnd => Make_Integer_Literal (Loc, System_Storage_Unit)))); @@ -9442,20 +9530,30 @@ end; end if; - -- Create the block and the finalization call + Fin_Call := + Make_Final_Call ( + Obj_Ref => + Make_Explicit_Dereference (Loc, + Prefix => Unchecked_Convert_To (Ptr_Typ, Obj_Expr)), + Typ => Desig_Typ); - return New_List ( - Make_Block_Statement (Loc, - Declarations => Decls, + if Present (Fin_Call) then + Fin_Block := + Make_Block_Statement (Loc, + Declarations => Decls, + Handled_Statement_Sequence => + Make_Handled_Sequence_Of_Statements (Loc, + Statements => New_List (Fin_Call))); - Handled_Statement_Sequence => - Make_Handled_Sequence_Of_Statements (Loc, - Statements => New_List ( - Make_Final_Call ( - Obj_Ref => - Make_Explicit_Dereference (Loc, - Prefix => Unchecked_Convert_To (Ptr_Typ, Obj_Expr)), - Typ => Desg_Typ))))); + -- Otherwise previous errors or a missing full view may prevent the + -- proper freezing of the designated type. If this is the case, there + -- is no [Deep_]Finalize primitive to call. + + else + Fin_Block := Make_Null_Statement (Loc); + end if; + + return New_List (Fin_Block); end Make_Finalize_Address_Stmts; ------------------------------------- @@ -9530,13 +9628,15 @@ Utyp : Entity_Id; begin + Ref := Obj_Ref; + -- Deal with the type and object reference. Depending on the context, an -- object reference may need several conversions. if Is_Concurrent_Type (Typ) then Is_Conc := True; Utyp := Corresponding_Record_Type (Typ); - Ref := Convert_Concurrent (Obj_Ref, Typ); + Ref := Convert_Concurrent (Ref, Typ); elsif Is_Private_Type (Typ) and then Present (Full_View (Typ)) @@ -9544,18 +9644,16 @@ then Is_Conc := True; Utyp := Corresponding_Record_Type (Underlying_Type (Typ)); - Ref := Convert_Concurrent (Obj_Ref, Underlying_Type (Typ)); + Ref := Convert_Concurrent (Ref, Underlying_Type (Typ)); else Is_Conc := False; Utyp := Typ; - Ref := Obj_Ref; end if; + Utyp := Underlying_Type (Base_Type (Utyp)); Set_Assignment_OK (Ref); - Utyp := Underlying_Type (Base_Type (Utyp)); - -- Deal with untagged derivation of private views if Is_Untagged_Derivation (Typ) and then not Is_Conc then @@ -9571,12 +9669,20 @@ -- completion of a private type. We need to access the base type and -- generate a conversion to it. - if Utyp /= Base_Type (Utyp) then + if Present (Utyp) and then Utyp /= Base_Type (Utyp) then pragma Assert (Is_Private_Type (Typ)); Utyp := Base_Type (Utyp); Ref := Unchecked_Convert_To (Utyp, Ref); end if; + -- The underlying type may not be present due to a missing full view. + -- In this case freezing did not take place and there is no suitable + -- [Deep_]Initialize primitive to call. + + if No (Utyp) then + return Empty; + end if; + -- Select the appropriate version of initialize if Has_Controlled_Component (Utyp) then @@ -9596,8 +9702,7 @@ return Make_Procedure_Call_Statement (Loc, - Name => - New_Occurrence_Of (Proc, Loc), + Name => New_Occurrence_Of (Proc, Loc), Parameter_Associations => New_List (Ref)); end Make_Init_Call; Index: exp_ch7.ads =================================================================== --- exp_ch7.ads (revision 244350) +++ exp_ch7.ads (working copy) @@ -184,10 +184,11 @@ Typ : Entity_Id; Skip_Self : Boolean := False) return Node_Id; -- Create a call to either Adjust or Deep_Adjust depending on the structure - -- of type Typ. Obj_Ref is an expression with no-side effect (not required + -- of type Typ. Obj_Ref is an expression with no side effects (not required -- to have been previously analyzed) that references the object to be -- adjusted. Typ is the expected type of Obj_Ref. When Skip_Self is set, - -- only the components (if any) are adjusted. + -- only the components (if any) are adjusted. Return Empty if Adjust or + -- Deep_Adjust is not available, possibly due to previous errors. function Make_Detach_Call (Obj_Ref : Node_Id) return Node_Id; -- Create a call to unhook an object from an arbitrary list. Obj_Ref is the @@ -200,11 +201,13 @@ (Obj_Ref : Node_Id; Typ : Entity_Id; Skip_Self : Boolean := False) return Node_Id; - -- Create a call to either Finalize or Deep_Finalize depending on the - -- structure of type Typ. Obj_Ref is an expression (with no-side effect + -- Create a call to either Finalize or Deep_Finalize, depending on the + -- structure of type Typ. Obj_Ref is an expression (with no side effects -- and is not required to have been previously analyzed) that references -- the object to be finalized. Typ is the expected type of Obj_Ref. When - -- Skip_Self is set, only the components (if any) are finalized. + -- Skip_Self is set, only the components (if any) are finalized. Return + -- Empty if Finalize or Deep_Finalize is not available, possibly due to + -- previous errors. procedure Make_Finalize_Address_Body (Typ : Entity_Id); -- Create the body of TSS routine Finalize_Address if Typ is controlled and @@ -215,11 +218,12 @@ function Make_Init_Call (Obj_Ref : Node_Id; Typ : Entity_Id) return Node_Id; - -- Obj_Ref is an expression with no-side effect (not required to have been - -- previously analyzed) that references the object to be initialized. Typ - -- is the expected type of Obj_Ref, which is either a controlled type - -- (Is_Controlled) or a type with controlled components (Has_Controlled_ - -- Components). + -- Create a call to either Initialize or Deep_Initialize, depending on the + -- structure of type Typ. Obj_Ref is an expression with no side effects + -- (not required to have been previously analyzed) that references the + -- object to be initialized. Typ is the expected type of Obj_Ref. Return + -- Empty if Initialize or Deep_Initialize is not available, possibly due to + -- previous errors. function Make_Handler_For_Ctrl_Operation (Loc : Source_Ptr) return Node_Id; -- Generate an implicit exception handler with an 'others' choice, Index: exp_util.adb =================================================================== --- exp_util.adb (revision 244356) +++ exp_util.adb (working copy) @@ -2943,7 +2943,10 @@ Set_Etype (Obj_Ref, Desig_Typ); end if; - Fin_Call := Make_Final_Call (Obj_Ref, Desig_Typ); + Fin_Call := + Make_Final_Call + (Obj_Ref => Obj_Ref, + Typ => Desig_Typ); -- Otherwise finalize the hook. Generate: