diff options
Diffstat (limited to 'gcc/ada/sem_ch12.adb')
-rw-r--r-- | gcc/ada/sem_ch12.adb | 276 |
1 files changed, 158 insertions, 118 deletions
diff --git a/gcc/ada/sem_ch12.adb b/gcc/ada/sem_ch12.adb index e0f7249..83ae95e 100644 --- a/gcc/ada/sem_ch12.adb +++ b/gcc/ada/sem_ch12.adb @@ -732,9 +732,10 @@ package body Sem_Ch12 is -- associated freeze node. Insert the freeze node before the first source -- body which follows immediately after N. If no such body is found, the -- freeze node is inserted at the end of the declarative region which - -- contains N. This can also be invoked to insert the freeze node of a - -- package that encloses an instantiation, in which case N may denote an - -- arbitrary node. + -- contains N, unless the instantiation is done in a package spec that is + -- not at library level, in which case it is inserted at the outer level. + -- This can also be invoked to insert the freeze node of a package that + -- encloses an instantiation, in which case N may denote an arbitrary node. procedure Install_Formal_Packages (Par : Entity_Id); -- Install the visible part of any formal of the parent that is a formal @@ -9208,8 +9209,7 @@ package body Sem_Ch12 is -- of a package declaration, and the inner instance is in -- the corresponding private part. - if Parent (List_Containing (Get_Unit_Instantiation_Node - (Par_Id))) + if Parent (List_Containing (Freeze_Node (Par_Id))) = Parent (List_Containing (N)) and then Sloc (Freeze_Node (Par_Id)) <= Sloc (N) then @@ -9266,7 +9266,8 @@ package body Sem_Ch12 is -- the body. elsif In_Same_List (Freeze_Node (Par_Id), Parent (N)) - and then Sloc (Freeze_Node (Par_Id)) < Sloc (Parent (N)) + and then + Sloc (Freeze_Node (Par_Id)) <= Sloc (Parent (N)) then Insert_Freeze_Node_For_Instance (Parent (N), Freeze_Node (Enclosing)); @@ -9403,7 +9404,7 @@ package body Sem_Ch12 is -- after that of Parent_Inst. This relation is established by -- comparing the Slocs of Parent_Inst freeze node and Inst. - elsif In_Same_List (Get_Unit_Instantiation_Node (Par_Id), N) + elsif In_Same_List (Freeze_Node (Par_Id), N) and then Sloc (Freeze_Node (Par_Id)) <= Sloc (N) then Insert_Freeze_Node_For_Instance (N, F_Node); @@ -9844,12 +9845,6 @@ package body Sem_Ch12 is (N : Node_Id; F_Node : Node_Id) is - Decl : Node_Id; - Decls : List_Id; - Inst : Entity_Id; - Par_Inst : Node_Id; - Par_N : Node_Id; - function Enclosing_Body (N : Node_Id) return Node_Id; -- Find enclosing package or subprogram body, if any. Freeze node may -- be placed at end of current declarative list if previous instance @@ -9908,138 +9903,183 @@ package body Sem_Ch12 is return Empty; end Previous_Instance; + -- Local variables + + Decl : Node_Id; + Decls : List_Id; + Inst : Entity_Id; + Par_Inst : Node_Id; + Par_N : Node_Id; + -- Start of processing for Insert_Freeze_Node_For_Instance begin - if not Is_List_Member (F_Node) then - Decl := N; - Decls := List_Containing (N); - Par_N := Parent (Decls); - Inst := Entity (F_Node); + -- Nothing to do if the freeze node has already been inserted - -- When processing a subprogram instantiation, utilize the actual - -- subprogram instantiation rather than its package wrapper as it - -- carries all the context information. + if Is_List_Member (F_Node) then + return; + end if; - if Is_Wrapper_Package (Inst) then - Inst := Related_Instance (Inst); - end if; + Inst := Entity (F_Node); - Par_Inst := Parent (Inst); + -- When processing a subprogram instantiation, utilize the actual + -- subprogram instantiation rather than its package wrapper as it + -- carries all the context information. - -- If this is a package instance, check whether the generic is - -- declared in a previous instance and the current instance is - -- not within the previous one. + if Is_Wrapper_Package (Inst) then + Inst := Related_Instance (Inst); + end if; - if Present (Generic_Parent (Par_Inst)) and then Is_In_Main_Unit (N) - then - declare - Enclosing_N : constant Node_Id := Enclosing_Body (N); - Par_I : constant Entity_Id := - Previous_Instance (Generic_Parent (Par_Inst)); - Scop : Entity_Id; + Par_Inst := Parent (Inst); - begin - if Present (Par_I) - and then Earlier (N, Freeze_Node (Par_I)) - then - Scop := Scope (Inst); - - -- If the current instance is within the one that contains - -- the generic, the freeze node for the current one must - -- appear in the current declarative part. Ditto, if the - -- current instance is within another package instance or - -- within a body that does not enclose the current instance. - -- In these three cases the freeze node of the previous - -- instance is not relevant. - - while Present (Scop) and then Scop /= Standard_Standard loop - exit when Scop = Par_I - or else - (Is_Generic_Instance (Scop) - and then Scope_Depth (Scop) > Scope_Depth (Par_I)); - Scop := Scope (Scop); - end loop; + -- If this is a package instance, check whether the generic is declared + -- in a previous instance and the current instance is not within the + -- previous one. - -- Previous instance encloses current instance + if Present (Generic_Parent (Par_Inst)) and then Is_In_Main_Unit (N) then + declare + Enclosing_N : constant Node_Id := Enclosing_Body (N); + Par_I : constant Entity_Id := + Previous_Instance (Generic_Parent (Par_Inst)); + Scop : Entity_Id; - if Scop = Par_I then - null; + begin + if Present (Par_I) and then Earlier (N, Freeze_Node (Par_I)) then + Scop := Scope (Inst); - -- If the next node is a source body we must freeze in - -- the current scope as well. + -- If the current instance is within the one that contains + -- the generic, the freeze node for the current one must + -- appear in the current declarative part. Ditto, if the + -- current instance is within another package instance or + -- within a body that does not enclose the current instance. + -- In these three cases the freeze node of the previous + -- instance is not relevant. - elsif Present (Next (N)) - and then Nkind (Next (N)) in N_Subprogram_Body - | N_Package_Body - and then Comes_From_Source (Next (N)) - then - null; + while Present (Scop) and then Scop /= Standard_Standard loop + exit when Scop = Par_I + or else + (Is_Generic_Instance (Scop) + and then Scope_Depth (Scop) > Scope_Depth (Par_I)); + Scop := Scope (Scop); + end loop; - -- Current instance is within an unrelated instance + -- Previous instance encloses current instance - elsif Is_Generic_Instance (Scop) then - null; + if Scop = Par_I then + null; - -- Current instance is within an unrelated body + -- If the next node is a source body we must freeze in the + -- current scope as well. - elsif Present (Enclosing_N) - and then Enclosing_N /= Enclosing_Body (Par_I) - then - null; + elsif Present (Next (N)) + and then Nkind (Next (N)) in N_Subprogram_Body + | N_Package_Body + and then Comes_From_Source (Next (N)) + then + null; - else - Insert_After (Freeze_Node (Par_I), F_Node); - return; - end if; - end if; - end; - end if; + -- Current instance is within an unrelated instance - -- When the instantiation occurs in a package declaration, append the - -- freeze node to the private declarations (if any). + elsif Is_Generic_Instance (Scop) then + null; - if Nkind (Par_N) = N_Package_Specification - and then Decls = Visible_Declarations (Par_N) - and then not Is_Empty_List (Private_Declarations (Par_N)) - then - Decls := Private_Declarations (Par_N); - Decl := First (Decls); - end if; - - -- Determine the proper freeze point of a package instantiation. We - -- adhere to the general rule of a package or subprogram body causing - -- freezing of anything before it in the same declarative region. In - -- this case, the proper freeze point of a package instantiation is - -- before the first source body which follows, or before a stub. This - -- ensures that entities coming from the instance are already frozen - -- and usable in source bodies. - - if Nkind (Par_N) /= N_Package_Declaration - and then Ekind (Inst) = E_Package - and then Is_Generic_Instance (Inst) - and then not In_Same_Source_Unit (Generic_Parent (Par_Inst), Inst) - then - while Present (Decl) loop - if (Nkind (Decl) in N_Unit_Body - or else - Nkind (Decl) in N_Body_Stub) - and then Comes_From_Source (Decl) + -- Current instance is within an unrelated body + + elsif Present (Enclosing_N) + and then Enclosing_N /= Enclosing_Body (Par_I) then - Insert_Before (Decl, F_Node); + null; + + else + Insert_After (Freeze_Node (Par_I), F_Node); return; end if; + end if; + end; + end if; - Next (Decl); - end loop; - end if; + Decl := N; + Decls := List_Containing (N); + Par_N := Parent (Decls); - -- In a package declaration, or if no previous body, insert at end - -- of list. + -- Determine the proper freeze point of an instantiation - Set_Sloc (F_Node, Sloc (Last (Decls))); - Insert_After (Last (Decls), F_Node); + if Is_Generic_Instance (Inst) then + loop + -- When the instantiation occurs in a package spec, append the + -- freeze node to the private declarations (if any). + + if Nkind (Par_N) = N_Package_Specification + and then Decls = Visible_Declarations (Par_N) + and then not Is_Empty_List (Private_Declarations (Par_N)) + then + Decls := Private_Declarations (Par_N); + Decl := First (Decls); + end if; + + -- We adhere to the general rule of a package or subprogram body + -- causing freezing of anything before it in the same declarative + -- region. In this respect, the proper freeze point of a package + -- instantiation is before the first source body which follows, or + -- before a stub. This ensures that entities from the instance are + -- already frozen and therefore usable in source bodies. + + if Nkind (Par_N) /= N_Package_Declaration + and then + not In_Same_Source_Unit (Generic_Parent (Par_Inst), Inst) + then + while Present (Decl) loop + if (Nkind (Decl) in N_Unit_Body + or else + Nkind (Decl) in N_Body_Stub) + and then Comes_From_Source (Decl) + then + Set_Sloc (F_Node, Sloc (Decl)); + Insert_Before (Decl, F_Node); + return; + end if; + + Next (Decl); + end loop; + end if; + + -- When the instantiation occurs in a package spec and there is + -- no source body which follows, and the package has a body but + -- is delayed, then insert immediately before its freeze node. + + if Nkind (Par_N) = N_Package_Specification + and then Present (Corresponding_Body (Parent (Par_N))) + and then Present (Freeze_Node (Defining_Entity (Par_N))) + then + Set_Sloc (F_Node, Sloc (Freeze_Node (Defining_Entity (Par_N)))); + Insert_Before (Freeze_Node (Defining_Entity (Par_N)), F_Node); + return; + + -- When the instantiation occurs in a package spec and there is + -- no source body which follows, not even of the package itself + -- then insert into the declaration list of the outer level. + + elsif Nkind (Par_N) = N_Package_Specification + and then No (Corresponding_Body (Parent (Par_N))) + and then Is_List_Member (Parent (Par_N)) + then + Decl := Parent (Par_N); + Decls := List_Containing (Decl); + Par_N := Parent (Decls); + + -- In a package declaration, or if no source body which follows + -- and at library level, then insert at end of list. + + else + exit; + end if; + end loop; end if; + + -- Insert and adjust the Sloc of the freeze node + + Set_Sloc (F_Node, Sloc (Last (Decls))); + Insert_After (Last (Decls), F_Node); end Insert_Freeze_Node_For_Instance; ----------------------------- |