From 56c3e620aa79524033973d09f44cf587c2038198 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Wed, 26 Sep 2018 09:17:36 +0000 Subject: [PATCH] [Ada] Inlining of renamed subprogram instances in package body This fixes a small discrepancy in the handling of renamed subprograms declared in a package body, between those originally a regular subprogram and those an instance of a generic subprogram, the latter being slightly hindered. The difference comes from the setting of the Is_Public flag, which was more conservative in the latter case because instantiations of generic subprograms are done in compiler-generated local packages. It is eliminated by allowing Has_Referencer to recurse into nested packages, but only if they are themselves not instances of generic packages. The compiler must now fully inline Doit_I into Doit at -O2 in: package P is generic procedure Doit_G; procedure Doit; end P; package body P is N : Natural := 0; procedure Doit_G is begin N := 1; end Doit_G; procedure Doit_I is new Doit_G; procedure Doit renames Doit_I; end P; 2018-09-26 Eric Botcazou gcc/ada/ * sem_ch7.adb (Has_Referencer): Remove Top_Level parameter and add In_Nested_Instance and Has_Outer_Referencer_Of_Non_Subprograms parameters. Rename Has_Non_Subprograms_Referencer variable into Has_Referencer_Of_Non_Subprograms and initialize it with the new third parameter. Adjust recursive calls and to the renaming. Replace test on Top_Level with test on In_Nested_Instance to decide whether to clear the Is_Public flag on entities. (Hide_Public_Entities): Adjust call to Has_Referencer. From-SVN: r264615 --- gcc/ada/ChangeLog | 12 +++++++++ gcc/ada/sem_ch7.adb | 65 ++++++++++++++++++++++++++++++--------------- 2 files changed, 56 insertions(+), 21 deletions(-) diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 08087d97fc1..05530af8aa7 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,15 @@ +2018-09-26 Eric Botcazou + + * sem_ch7.adb (Has_Referencer): Remove Top_Level parameter and + add In_Nested_Instance and + Has_Outer_Referencer_Of_Non_Subprograms parameters. Rename + Has_Non_Subprograms_Referencer variable into + Has_Referencer_Of_Non_Subprograms and initialize it with the new + third parameter. Adjust recursive calls and to the renaming. + Replace test on Top_Level with test on In_Nested_Instance to + decide whether to clear the Is_Public flag on entities. + (Hide_Public_Entities): Adjust call to Has_Referencer. + 2018-09-26 Eric Botcazou * exp_disp.adb (Expand_Interface_Conversion): Use Present test. diff --git a/gcc/ada/sem_ch7.adb b/gcc/ada/sem_ch7.adb index cb4b853e46a..8aebb0f1b68 100644 --- a/gcc/ada/sem_ch7.adb +++ b/gcc/ada/sem_ch7.adb @@ -259,11 +259,12 @@ package body Sem_Ch7 is procedure Hide_Public_Entities (Decls : List_Id) is function Has_Referencer - (Decls : List_Id; - Top_Level : Boolean := False) return Boolean; + (Decls : List_Id; + In_Nested_Instance : Boolean; + Has_Outer_Referencer_Of_Non_Subprograms : Boolean) return Boolean; -- A "referencer" is a construct which may reference a previous -- declaration. Examine all declarations in list Decls in reverse - -- and determine whether once such referencer exists. All entities + -- and determine whether one such referencer exists. All entities -- in the range Last (Decls) .. Referencer are hidden from external -- visibility. @@ -286,14 +287,16 @@ package body Sem_Ch7 is -------------------- function Has_Referencer - (Decls : List_Id; - Top_Level : Boolean := False) return Boolean + (Decls : List_Id; + In_Nested_Instance : Boolean; + Has_Outer_Referencer_Of_Non_Subprograms : Boolean) return Boolean is Decl : Node_Id; Decl_Id : Entity_Id; Spec : Node_Id; - Has_Non_Subprograms_Referencer : Boolean := False; + Has_Referencer_Of_Non_Subprograms : Boolean := + Has_Outer_Referencer_Of_Non_Subprograms; -- Set if an inlined subprogram body was detected as a referencer. -- In this case, we do not return True immediately but keep hiding -- subprograms from external visibility. @@ -319,13 +322,23 @@ package body Sem_Ch7 is elsif Nkind (Decl) = N_Package_Declaration then Spec := Specification (Decl); + Decl_Id := Defining_Entity (Spec); -- Inspect the declarations of a non-generic package to try -- and hide more entities from external visibility. - if not Is_Generic_Unit (Defining_Entity (Spec)) then - if Has_Referencer (Private_Declarations (Spec)) - or else Has_Referencer (Visible_Declarations (Spec)) + if not Is_Generic_Unit (Decl_Id) then + if Has_Referencer (Private_Declarations (Spec), + In_Nested_Instance + or else + Is_Generic_Instance (Decl_Id), + Has_Referencer_Of_Non_Subprograms) + or else + Has_Referencer (Visible_Declarations (Spec), + In_Nested_Instance + or else + Is_Generic_Instance (Decl_Id), + Has_Referencer_Of_Non_Subprograms) then return True; end if; @@ -354,7 +367,12 @@ package body Sem_Ch7 is -- Inspect the declarations of a non-generic package body to -- try and hide more entities from external visibility. - elsif Has_Referencer (Declarations (Decl)) then + elsif Has_Referencer (Declarations (Decl), + In_Nested_Instance + or else + Is_Generic_Instance (Decl_Id), + Has_Referencer_Of_Non_Subprograms) + then return True; end if; @@ -382,7 +400,7 @@ package body Sem_Ch7 is if Is_Inlined (Decl_Id) or else Has_Pragma_Inline (Decl_Id) then - Has_Non_Subprograms_Referencer := True; + Has_Referencer_Of_Non_Subprograms := True; -- Inspect the statements of the subprogram body -- to determine whether the body references other @@ -401,7 +419,7 @@ package body Sem_Ch7 is if Is_Inlined (Decl_Id) or else Has_Pragma_Inline (Decl_Id) then - Has_Non_Subprograms_Referencer := True; + Has_Referencer_Of_Non_Subprograms := True; -- Inspect the statements of the subprogram body -- to determine whether the body references other @@ -425,15 +443,20 @@ package body Sem_Ch7 is begin -- Inspect the actions to find references to subprograms - Discard := Has_Referencer (Actions (Decl)); + Discard := + Has_Referencer (Actions (Decl), + In_Nested_Instance, + Has_Referencer_Of_Non_Subprograms); end; -- Exceptions, objects and renamings do not need to be public -- if they are not followed by a construct which can reference - -- and export them. The Is_Public flag is reset on top level - -- entities only as anything nested is local to its context. - -- Likewise for subprograms, but we work harder for them. - + -- and export them. Likewise for subprograms but we work harder + -- for them to see whether they are referenced on an individual + -- basis by looking into the table of referenced subprograms. + -- But we cannot say anything for entities declared in nested + -- instances because instantiations are not done yet so the + -- bodies are not visible and could contain references to them. elsif Nkind_In (Decl, N_Exception_Declaration, N_Object_Declaration, N_Object_Renaming_Declaration, @@ -442,12 +465,12 @@ package body Sem_Ch7 is then Decl_Id := Defining_Entity (Decl); - if Top_Level + if not In_Nested_Instance and then not Is_Imported (Decl_Id) and then not Is_Exported (Decl_Id) and then No (Interface_Name (Decl_Id)) and then - (not Has_Non_Subprograms_Referencer + (not Has_Referencer_Of_Non_Subprograms or else (Nkind (Decl) = N_Subprogram_Declaration and then not Subprogram_Table.Get (Decl_Id))) then @@ -475,7 +498,7 @@ package body Sem_Ch7 is Prev (Decl); end loop; - return Has_Non_Subprograms_Referencer; + return Has_Referencer_Of_Non_Subprograms; end Has_Referencer; ------------------------- @@ -609,7 +632,7 @@ package body Sem_Ch7 is Traversed_Table.Reset; Subprogram_Table.Reset; - Discard := Has_Referencer (Decls, Top_Level => True); + Discard := Has_Referencer (Decls, False, False); end Hide_Public_Entities; ---------------------------------- -- 2.30.2